diff --git a/.github/docs/pull_request_template.md b/.github/docs/pull_request_template.md new file mode 100644 index 00000000000..4515ddf65b9 --- /dev/null +++ b/.github/docs/pull_request_template.md @@ -0,0 +1,16 @@ +## Description + +Describe the changes that this PR introduces. Link any relevant # (issue) or # (pull request). + +## Types of changes + +- [ ] Bug fix +- [ ] New feature +- [ ] Breaking change +- [ ] Documentation Update + +## Checklist + +- [ ] I have changed storage version if on disk format has changed. +- [ ] I have requested a review from a maintainer. +- [ ] I have updated the documentation (if needed). diff --git a/.github/workflows/benchmark-workflow.yml b/.github/workflows/benchmark-workflow.yml new file mode 100644 index 00000000000..427e0fd64e8 --- /dev/null +++ b/.github/workflows/benchmark-workflow.yml @@ -0,0 +1,20 @@ +name: Benchmark +on: + workflow_dispatch: + workflow_call: + +jobs: + benchmark: + name: benchmark + env: + NUM_THREADS: 30 + GEN: ninja + runs-on: kuzu-self-hosted-benchmarking + steps: + - uses: actions/checkout@v3 + + - name: Build + run: make benchmark LTO=1 + + - name: Benchmark + run: python3 benchmark/benchmark_runner.py --dataset ldbc-sf100 --thread 10 diff --git a/.github/workflows/build-extensions.yml b/.github/workflows/build-extensions.yml index f8be4ed3de2..18d726ab6e6 100644 --- a/.github/workflows/build-extensions.yml +++ b/.github/workflows/build-extensions.yml @@ -74,7 +74,7 @@ jobs: docker run -d --name kuzu-x86 \ -v $PWD:/kuzu -w /kuzu \ -e NUM_THREADS=2 -e GEN=ninja -e CC=gcc -e CXX=g++ \ - i386/debian:latest tail -f /dev/null + i386/debian:stable tail -f /dev/null - name: Install dependencies run: | @@ -108,7 +108,7 @@ jobs: - name: Install OpenSSL run: | - brew install openssl@3 + brew install openssl@3 duckdb OPENSSL_ROOT=$(readlink -f /opt/homebrew/Cellar/openssl@3/*/) echo "OPENSSL_ROOT_DIR=$OPENSSL_ROOT" >> $GITHUB_ENV diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index b25ae646230..551ca7b4f46 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -11,6 +11,7 @@ on: push: branches: - master + workflow_dispatch: # Only allow one run in this group to run at a time, and cancel any runs in progress in this group. # We use the workflow name and then add the pull request number, or (if it's a push to master), we use the name of the branch. @@ -24,7 +25,7 @@ concurrency: jobs: gcc-build-test: name: gcc build & test - needs: [clang-formatting-check, sanity-checks] + needs: [clang-format, sanity-checks, python-lint-check] runs-on: kuzu-self-hosted-testing env: NUM_THREADS: 32 @@ -54,11 +55,6 @@ jobs: run: npm install --include=dev working-directory: tools/nodejs_api - - name: Extension test - run: | - cd scripts/ && python3 http-server.py & - make extension-test && make clean - - name: Build run: make all @@ -87,7 +83,7 @@ jobs: gcc-build-test-x86: name: gcc build & test 32-bit - needs: [clang-formatting-check, sanity-checks] + needs: [clang-format, sanity-checks] runs-on: ubuntu-latest steps: @@ -95,10 +91,10 @@ jobs: - name: Start Docker container run: | - docker run -d --name kuzu-x86 \ - -v $PWD:/kuzu -w /kuzu \ - -e NUM_THREADS=2 -e GEN=ninja -e CC=gcc -e CXX=g++ \ - i386/debian:latest tail -f /dev/null + docker run -d --name kuzu-x86 \ + -v $PWD:/kuzu -w /kuzu \ + -e NUM_THREADS=2 -e GEN=ninja -e CC=gcc -e CXX=g++ \ + i386/debian:stable tail -f /dev/null - name: Install dependencies run: | @@ -161,7 +157,7 @@ jobs: clang-build-test: name: clang build and test - needs: [clang-formatting-check, sanity-checks] + needs: [clang-format, sanity-checks, python-lint-check] runs-on: kuzu-self-hosted-testing env: NUM_THREADS: 32 @@ -187,11 +183,6 @@ jobs: run: npm install --include=dev working-directory: tools/nodejs_api - - name: Extension test - run: | - cd scripts/ && python3 http-server.py & - make extension-test && make clean - - name: Build run: make all @@ -209,7 +200,7 @@ jobs: msvc-build-test: name: msvc build & test - needs: [clang-formatting-check, sanity-checks] + needs: [clang-format, sanity-checks, python-lint-check] runs-on: self-hosted-windows env: # Shorten build path as much as possible @@ -224,6 +215,7 @@ jobs: AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + PG_HOST: ${{ secrets.PG_HOST }} RUN_ID: "$(hostname)-$([Math]::Floor((Get-Date).TimeOfDay.TotalSeconds))" steps: - uses: actions/checkout@v3 @@ -237,13 +229,6 @@ jobs: run: npm install --include=dev working-directory: tools/nodejs_api - - name: Extension test - shell: cmd - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cd scripts/ && start /b python http-server.py && cd .. - make extension-test && make clean - - name: Build shell: cmd run: | @@ -286,7 +271,7 @@ jobs: tidy-and-diagnostics: name: clang tidy & clangd diagnostics check - needs: [clang-formatting-check, sanity-checks] + needs: [clang-format, sanity-checks] runs-on: kuzu-self-hosted-testing env: NUM_THREADS: 32 @@ -323,25 +308,58 @@ jobs: - name: Ensure generated grammar files are up to date run: cmp src/antlr4/Cypher.g4 scripts/antlr4/Cypher.g4.copy - clang-formatting-check: - name: clang-format check + clang-format: + name: clang format runs-on: ubuntu-22.04 steps: - name: Install clang-format run: | - sudo apt-get update - sudo apt-get install -y clang-format-11 + sudo apt-get install -y lsb-release wget software-properties-common gnupg + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + yes | sudo ./llvm.sh 18 all - uses: actions/checkout@v3 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} + + - name: Check and fix source format + run: python3 scripts/run-clang-format.py --in-place --clang-format-executable /usr/bin/clang-format-18 -r src/ + + - name: Check and fix test format + run: python3 scripts/run-clang-format.py --in-place --clang-format-executable /usr/bin/clang-format-18 -r test/ + + - name: Check and fix extension format + run: python3 scripts/run-clang-format.py --in-place --clang-format-executable /usr/bin/clang-format-18 -r extension/ - - name: Check source format - run: python3 scripts/run-clang-format.py --clang-format-executable /usr/bin/clang-format-11 -r src/ + - name: Fail if any chang is made (master branch) + if: github.ref == 'refs/heads/master' + run: git diff --exit-code + + - name: Commit changes (non-master branch) + uses: EndBug/add-and-commit@v9 + if: github.ref != 'refs/heads/master' + with: + author_name: "CI Bot" + message: "Run clang-format" + + python-lint-check: + name: python lint check + runs-on: macos-14 + steps: + - uses: actions/checkout@v3 - - name: Check test format - run: python3 scripts/run-clang-format.py --clang-format-executable /usr/bin/clang-format-11 -r test/ + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: "3.11" - - name: Check extension format - run: python3 scripts/run-clang-format.py --clang-format-executable /usr/bin/clang-format-11 -r extension/ + - name: Run Python lint + working-directory: tools/python_api + run: | + make requirements + ./.venv/bin/ruff check src_py test --verbose rustfmt-check: name: rustfmt check @@ -359,22 +377,11 @@ jobs: benchmark: name: benchmark needs: [gcc-build-test, clang-build-test] - env: - NUM_THREADS: 30 - GEN: ninja - runs-on: kuzu-self-hosted-benchmarking - steps: - - uses: actions/checkout@v3 - - - name: Build - run: make benchmark LTO=1 - - - name: Benchmark - run: python3 benchmark/benchmark_runner.py --dataset ldbc-sf100 --thread 10 + uses: ./.github/workflows/benchmark-workflow.yml macos-clang-tidy: name: macos clang tidy & clangd diagnostics check - needs: [clang-formatting-check, sanity-checks] + needs: [clang-format, sanity-checks] runs-on: self-hosted-mac-x64 env: NUM_THREADS: 32 @@ -399,7 +406,7 @@ jobs: macos-build-test: name: apple clang build & test - needs: [clang-formatting-check, sanity-checks, rustfmt-check] + needs: [clang-format, sanity-checks, rustfmt-check, python-lint-check] runs-on: self-hosted-mac-x64 env: NUM_THREADS: 32 @@ -411,6 +418,7 @@ jobs: AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + PG_HOST: ${{ secrets.PG_HOST }} RUN_ID: "$(hostname)-$(date +%s)" steps: - uses: actions/checkout@v3 @@ -424,11 +432,6 @@ jobs: run: npm install --include=dev working-directory: tools/nodejs_api - - name: Extension test - run: | - cd scripts/ && python3 http-server.py & - make extension-test && make clean - - name: Build run: make all @@ -469,3 +472,129 @@ jobs: ulimit -n 10240 source /Users/runner/.cargo/env cargo build --locked --features arrow + + shell-test: + name: shell test + runs-on: ubuntu-latest + needs: [clang-format, sanity-checks] + env: + WERROR: 0 + steps: + - uses: actions/checkout@v3 + + - name: Build + run: make release NUM_THREADS=$(nproc) + + - name: Test + working-directory: tools/shell/test + run: | + pip3 install pytest pexpect + python3 -m pytest -v . + + linux-extension-test: + name: linux extension test + needs: [gcc-build-test, clang-build-test] + runs-on: kuzu-self-hosted-testing + env: + NUM_THREADS: 32 + TEST_JOBS: 16 + CLANGD_DIAGNOSTIC_JOBS: 32 + CLANGD_DIAGNOSTIC_INSTANCES: 6 + GEN: ninja + CC: gcc + CXX: g++ + UW_S3_ACCESS_KEY_ID: ${{ secrets.UW_S3_ACCESS_KEY_ID }} + UW_S3_SECRET_ACCESS_KEY: ${{ secrets.UW_S3_SECRET_ACCESS_KEY }} + AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + RUN_ID: "$(hostname)-$(date +%s)" + + steps: + - uses: actions/checkout@v3 + + - name: Update PostgreSQL host + working-directory: extension/postgres_scanner/test/test_files + env: + FNAME: postgres_scanner.test + FIND: "localhost" + run: | + node -e 'fs=require("fs");fs.readFile(process.env.FNAME,"utf8",(err,data)=>{if(err!=null)throw err;fs.writeFile(process.env.FNAME,data.replaceAll(process.env.FIND,process.env.PG_HOST),"utf8",e=>{if(e!=null)throw e;});});' + cat postgres_scanner.test + + - name: Extension test + run: | + cd scripts/ && python3 http-server.py & + make extension-test && make clean + + macos-extension-test: + name: macos extension test + needs: [macos-build-test] + runs-on: self-hosted-mac-x64 + env: + NUM_THREADS: 32 + TEST_JOBS: 16 + GEN: ninja + UW_S3_ACCESS_KEY_ID: ${{ secrets.UW_S3_ACCESS_KEY_ID }} + UW_S3_SECRET_ACCESS_KEY: ${{ secrets.UW_S3_SECRET_ACCESS_KEY }} + AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + PG_HOST: ${{ secrets.PG_HOST }} + RUN_ID: "$(hostname)-$(date +%s)" + steps: + - uses: actions/checkout@v3 + + - name: Update PostgreSQL host + working-directory: extension/postgres_scanner/test/test_files + env: + FNAME: postgres_scanner.test + FIND: "localhost" + run: | + node -e 'fs=require("fs");fs.readFile(process.env.FNAME,"utf8",(err,data)=>{if(err!=null)throw err;fs.writeFile(process.env.FNAME,data.replaceAll(process.env.FIND,process.env.PG_HOST),"utf8",e=>{if(e!=null)throw e;});});' + cat postgres_scanner.test + + - name: Extension test + run: | + cd scripts/ && python3 http-server.py & + make extension-test && make clean + + windows-extension-test: + name: windows extension test + needs: [msvc-build-test] + runs-on: self-hosted-windows + env: + # Shorten build path as much as possible + CARGO_TARGET_DIR: ${{ github.workspace }}/rs + CARGO_BUILD_JOBS: 18 + NUM_THREADS: 18 + TEST_JOBS: 9 + WERROR: 0 + UW_S3_ACCESS_KEY_ID: ${{ secrets.UW_S3_ACCESS_KEY_ID }} + UW_S3_SECRET_ACCESS_KEY: ${{ secrets.UW_S3_SECRET_ACCESS_KEY }} + AWS_S3_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_SECRET_ACCESS_KEY }} + PG_HOST: ${{ secrets.PG_HOST }} + RUN_ID: "$(hostname)-$([Math]::Floor((Get-Date).TimeOfDay.TotalSeconds))" + steps: + - uses: actions/checkout@v3 + + - name: Update PostgreSQL host + working-directory: extension/postgres_scanner/test/test_files + env: + FNAME: postgres_scanner.test + FIND: "localhost" + run: | + node -e 'fs=require("fs");fs.readFile(process.env.FNAME,"utf8",(err,data)=>{if(err!=null)throw err;fs.writeFile(process.env.FNAME,data.replaceAll(process.env.FIND,process.env.PG_HOST),"utf8",e=>{if(e!=null)throw e;});});' + cat postgres_scanner.test + + - name: Extension test + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + cd scripts/ && start /b python http-server.py && cd .. + make extension-test && make clean diff --git a/.github/workflows/multiplatform-build-test.yml b/.github/workflows/multiplatform-build-test.yml index a4009cfc528..b730bd021d6 100644 --- a/.github/workflows/multiplatform-build-test.yml +++ b/.github/workflows/multiplatform-build-test.yml @@ -9,118 +9,206 @@ jobs: ubuntu-2004-build-test: name: ubuntu-20.04 runs-on: ubuntu-20.04 + defaults: + run: + shell: bash env: CC: gcc-11 CXX: g++-11 steps: - uses: actions/checkout@v3 + continue-on-error: true - name: Install packages + continue-on-error: true run: | sudo apt-get update sudo apt-get install -y build-essential manpages-dev software-properties-common sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update - sudo apt-get install -y gcc-11 g++-11 python3.9 + sudo apt-get install -y gcc-11 g++-11 + + - uses: actions/setup-python@v5 + continue-on-error: true + with: + python-version: "3.11" - name: Ensure Python dependencies + continue-on-error: true run: | pip install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu pip install --user -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html - pip install --user backports.zoneinfo - name: Ensure Node.js dependencies + continue-on-error: true working-directory: tools/nodejs_api run: npm install --include=dev - name: Build - run: make release NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make release NUM_THREADS=$(nproc) + echo "Build,$?" > status.txt - name: Test - run: make test NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make test NUM_THREADS=$(nproc) + echo "Test,$?" >> status.txt - name: C and C++ examples - run: make example NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make example NUM_THREADS=$(nproc) + echo "C and C++ examples,$?" >> status.txt - name: Python test - run: make pytest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make pytest NUM_THREADS=$(nproc) + echo "Python test,$?" >> status.txt - name: Node.js test - run: make nodejstest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make nodejstest NUM_THREADS=$(nproc) + echo "Node.js test,$?" >> status.txt - name: Java test - run: make javatest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make javatest NUM_THREADS=$(nproc) + echo "Java test,$?" >> status.txt - name: Rust share build + continue-on-error: true run: echo $'[workspace]\nmembers = ["tools/rust_api","examples/rust"]' > Cargo.toml - name: Rust set env + continue-on-error: true run: echo "CARGO_BUILD_JOBS=$(nproc)" >> $GITHUB_ENV - name: Rust test + continue-on-error: true working-directory: tools/rust_api run: | cargo test --release --features arrow -- --test-threads=1 + echo "Rust test,$?" >> ../../status.txt - name: Rust example + continue-on-error: true working-directory: examples/rust - run: cargo build --release --features arrow + run: | + cargo build --release --features arrow + echo "Rust example,$?" >> ../../status.txt + + - name: Rename status.txt + continue-on-error: true + run: mv status.txt ubuntu-20.04.csv + + - uses: actions/upload-artifact@v4 + continue-on-error: true + with: + name: ubuntu-20.04 + path: ubuntu-20.04.csv macos-build-test: strategy: matrix: - runner: [macos-12, macos-13] + runner: [macos-13, macos-14] fail-fast: false name: ${{ matrix.runner }} runs-on: ${{ matrix.runner }} + defaults: + run: + shell: bash steps: - uses: actions/checkout@v3 + continue-on-error: true - uses: actions/setup-python@v4 + continue-on-error: true with: python-version: "3.10" - name: Ensure Python dependencies + continue-on-error: true run: | pip install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu pip install --user -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html - name: Ensure Node.js dependencies + continue-on-error: true working-directory: tools/nodejs_api run: npm install --include=dev - name: Build - run: make release NUM_THREADS=$(sysctl -n hw.physicalcpu) + continue-on-error: true + run: | + make release NUM_THREADS=$(sysctl -n hw.physicalcpu) + echo "Build,$?" > status.txt - name: Test - run: make test NUM_THREADS=$(sysctl -n hw.physicalcpu) + continue-on-error: true + run: | + make test NUM_THREADS=$(sysctl -n hw.physicalcpu) + echo "Test,$?" >> status.txt - name: C and C++ examples - run: make example NUM_THREADS=$(sysctl -n hw.physicalcpu) + continue-on-error: true + run: | + make example NUM_THREADS=$(sysctl -n hw.physicalcpu) + echo "C and C++ examples,$?" >> status.txt - name: Python test - run: make pytest NUM_THREADS=$(sysctl -n hw.physicalcpu) + continue-on-error: true + run: | + make pytest NUM_THREADS=$(sysctl -n hw.physicalcpu) + echo "Python test,$?" >> status.txt - name: Node.js test - run: make nodejstest NUM_THREADS=$(sysctl -n hw.physicalcpu) + continue-on-error: true + run: | + make nodejstest NUM_THREADS=$(sysctl -n hw.physicalcpu) + echo "Node.js test,$?" >> status.txt - name: Java test - run: make javatest NUM_THREADS=$(sysctl -n hw.physicalcpu) + continue-on-error: true + run: | + make javatest NUM_THREADS=$(sysctl -n hw.physicalcpu) + echo "Java test,$?" >> status.txt - name: Rust share build + continue-on-error: true run: echo $'[workspace]\nmembers = ["tools/rust_api","examples/rust"]' > Cargo.toml - name: Rust set env + continue-on-error: true run: echo "CARGO_BUILD_JOBS=$(sysctl -n hw.physicalcpu)" >> $GITHUB_ENV - name: Rust test + continue-on-error: true working-directory: tools/rust_api run: | cargo test --release --features arrow -- --test-threads=1 + echo "Rust test,$?" >> ../../status.txt - name: Rust example + continue-on-error: true working-directory: examples/rust - run: cargo build --release --features arrow + run: | + cargo build --release --features arrow + echo "Rust example,$?" >> ../../status.txt + + - name: Rename status.txt + continue-on-error: true + run: mv status.txt ${{ matrix.runner }}.csv + + - uses: actions/upload-artifact@v4 + continue-on-error: true + with: + name: ${{ matrix.runner }} + path: ${{ matrix.runner }}.csv windows-build-test: strategy: @@ -131,6 +219,7 @@ jobs: runs-on: ${{ matrix.runner }} steps: - name: Disable Windows Defender + continue-on-error: true shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true @@ -145,53 +234,78 @@ jobs: Set-MpPreference -SubmitSamplesConsent NeverSend - uses: actions/checkout@v3 + continue-on-error: true - uses: ilammy/msvc-dev-cmd@v1 + continue-on-error: true - uses: actions/setup-python@v4 + continue-on-error: true with: python-version: "3.10" - name: Ensure Python dependencies + continue-on-error: true shell: cmd run: | pip install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu pip install --user -r tools\python_api\requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html - name: Ensure Node.js dependencies + continue-on-error: true shell: cmd working-directory: .\tools\nodejs_api run: npm install --include=dev - name: Build + continue-on-error: true shell: cmd - run: make release NUM_THREADS=%NUMBER_OF_PROCESSORS% + run: | + make release NUM_THREADS=%NUMBER_OF_PROCESSORS% + echo Build,%ERRORLEVEL% > status.txt - name: Test + continue-on-error: true shell: cmd - run: make test NUM_THREADS=%NUMBER_OF_PROCESSORS% + run: | + make test NUM_THREADS=%NUMBER_OF_PROCESSORS% + echo Test,%ERRORLEVEL% >> status.txt - name: C and C++ examples + continue-on-error: true shell: cmd - run: make example NUM_THREADS=%NUMBER_OF_PROCESSORS% + run: | + make example NUM_THREADS=%NUMBER_OF_PROCESSORS% + echo C and C++ examples,%ERRORLEVEL% >> status.txt - name: Python test + continue-on-error: true shell: cmd - run: make pytest NUM_THREADS=%NUMBER_OF_PROCESSORS% + run: | + make pytest NUM_THREADS=%NUMBER_OF_PROCESSORS% + echo Python test,%ERRORLEVEL% >> status.txt - name: Node.js test + continue-on-error: true shell: cmd - run: make nodejstest NUM_THREADS=%NUMBER_OF_PROCESSORS% + run: | + make nodejstest NUM_THREADS=%NUMBER_OF_PROCESSORS% + echo Node.js test,%ERRORLEVEL% >> status.txt - name: Java test + continue-on-error: true shell: cmd - run: make javatest NUM_THREADS=%NUMBER_OF_PROCESSORS% + run: | + make javatest NUM_THREADS=%NUMBER_OF_PROCESSORS% + echo Java test,%ERRORLEVEL% >> status.txt - name: Rust share build + continue-on-error: true shell: cmd run: (echo [workspace]& echo members = ["tools/rust_api","examples/rust"]) > Cargo.toml - name: Rust test + continue-on-error: true shell: cmd run: | make clean @@ -199,12 +313,27 @@ jobs: set CXXFLAGS=/std:c++20 set CARGO_BUILD_JOBS=%NUMBER_OF_PROCESSORS% cargo test --release --features arrow -- --test-threads=1 + echo Rust test,%ERRORLEVEL% >> status.txt - name: Rust example + continue-on-error: true shell: cmd run: | set CARGO_BUILD_JOBS=%NUMBER_OF_PROCESSORS% cargo build --release --features arrow + echo Rust example,%ERRORLEVEL% >> status.txt + + - name: Rename status.txt + continue-on-error: true + shell: cmd + run: | + rename status.txt ${{ matrix.runner }}.csv + + - uses: actions/upload-artifact@v4 + continue-on-error: true + with: + name: ${{ matrix.runner }} + path: ${{ matrix.runner }}.csv debian-ubuntu-build-test: strategy: @@ -221,6 +350,7 @@ jobs: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 steps: - name: Install packages + continue-on-error: true run: | apt-get update apt-get install -y ca-certificates curl gnupg @@ -231,59 +361,101 @@ jobs: apt-get install -y git build-essential cmake gcc g++ python3 python3-dev python3-pip openjdk-17-jdk nodejs - uses: actions/checkout@v3 + continue-on-error: true - name: Ensure Python dependencies + continue-on-error: true run: | pip install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu ${{ matrix.image != 'debian:11' && '--break-system-packages' || '' }} pip install --user -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html ${{ matrix.image != 'debian:11' && '--break-system-packages' || '' }} - name: Ensure Node.js dependencies working-directory: tools/nodejs_api + continue-on-error: true run: npm install --include=dev - name: Install Rust + continue-on-error: true run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-update-default-toolchain echo "$HOME/.cargo/bin" >> $GITHUB_PATH - $HOME/.cargo/bin/rustup toolchain install 1.67 + $HOME/.cargo/bin/rustup toolchain install 1.76 - name: Build - run: make release NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make release NUM_THREADS=$(nproc) + echo "Build,$?" > status.txt - name: Test - run: make test NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make test NUM_THREADS=$(nproc) + echo "Test,$?" >> status.txt - name: C and C++ examples - run: make example NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make example NUM_THREADS=$(nproc) + echo "C and C++ examples,$?" >> status.txt - name: Python test - run: make pytest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make pytest NUM_THREADS=$(nproc) + echo "Python test,$?" >> status.txt - name: Node.js test - run: make nodejstest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make nodejstest NUM_THREADS=$(nproc) + echo "Node.js test,$?" >> status.txt - name: Java test - run: make javatest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make javatest NUM_THREADS=$(nproc) + echo "Java test,$?" >> status.txt - name: Rust share build + continue-on-error: true run: echo '[workspace]\nmembers = ["tools/rust_api","examples/rust"]' > Cargo.toml - name: Rust set env + continue-on-error: true run: echo "CARGO_BUILD_JOBS=$(nproc)" >> $GITHUB_ENV - name: Rust test + continue-on-error: true working-directory: tools/rust_api run: | cargo test --release --features arrow -- --test-threads=1 + echo "Rust test,$?" >> ../../status.txt - name: Rust example + continue-on-error: true working-directory: examples/rust - run: cargo build --release --features arrow + run: | + cargo build --release --features arrow + echo "Rust example,$?" >> ../../status.txt + + - name: Rename status.txt + continue-on-error: true + run: | + PLATFORM=$(echo ${{ matrix.image }} | tr ':' '-') + echo "PLATFORM=$PLATFORM" >> $GITHUB_ENV + mv status.txt $PLATFORM.csv + + - uses: actions/upload-artifact@v4 + continue-on-error: true + with: + name: ${{env.PLATFORM}} + path: ${{env.PLATFORM}}.csv - rhel-fedora-build-test: + rhel-fedora-build-test: strategy: matrix: - image: ["rockylinux:8", "rockylinux:9", "fedora:38"] + image: ["rockylinux:8", "rockylinux:9", "fedora:38", "fedora:39"] fail-fast: false name: ${{ matrix.image }} runs-on: ubuntu-latest @@ -296,6 +468,7 @@ jobs: HOME: /root steps: - name: Enable EPEL + continue-on-error: true if: ${{ matrix.image == 'rockylinux:8' || matrix.image == 'rockylinux:9' }} run: | dnf update -y @@ -303,150 +476,121 @@ jobs: dnf update -y - name: Enable SHA-1 on Rocky Linux 9 + continue-on-error: true if: matrix.image == 'rockylinux:9' run: update-crypto-policies --set LEGACY - name: Install packages + continue-on-error: true run: | curl -fsSL https://rpm.nodesource.com/setup_20.x | bash - - dnf install -y git cmake ${{ matrix.image == 'rockylinux:8' && 'gcc-toolset-12 python39 python39-devel' || 'gcc gcc-c++ python3-devel' }} java-17-openjdk-devel nodejs + dnf install -y git cmake ${{ matrix.image == 'rockylinux:8' && 'gcc-toolset-12 python3.11 python3.11-devel' || 'gcc gcc-c++ python3-devel' }} java-17-openjdk-devel nodejs - - name: Enable gcc-toolset-12 and python39 on Rocky Linux 8 + - name: Enable gcc-toolset-12 and python3.11 on Rocky Linux 8 + continue-on-error: true if: matrix.image == 'rockylinux:8' run: | - alternatives --set python /usr/bin/python3.9 - alternatives --set python3 /usr/bin/python3.9 - echo "PYTHON_EXECUTABLE=/usr/bin/python3.9" >> $GITHUB_ENV - echo "PYBIND11_PYTHON_VERSION=3.9" >> $GITHUB_ENV + alternatives --set python /usr/bin/python3.11 + alternatives --set python3 /usr/bin/python3.11 + echo "PYTHON_EXECUTABLE=/usr/bin/python3.11" >> $GITHUB_ENV + echo "PYBIND11_PYTHON_VERSION=3.11" >> $GITHUB_ENV source /opt/rh/gcc-toolset-12/enable echo $PATH >> $GITHUB_PATH - uses: actions/checkout@v3 + continue-on-error: true - name: Ensure Python dependencies + continue-on-error: true run: | python3 -m venv /opt/venv source /opt/venv/bin/activate - pip3 install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu - pip3 install -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html + pip3 install torch~=2.2.1 --extra-index-url https://download.pytorch.org/whl/cpu + pip3 install -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.2.1+cpu.html - name: Ensure Node.js dependencies + continue-on-error: true working-directory: tools/nodejs_api run: npm install --include=dev - name: Install Rust + continue-on-error: true run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-update-default-toolchain echo "$HOME/.cargo/bin" >> $GITHUB_PATH - $HOME/.cargo/bin/rustup toolchain install 1.67 + $HOME/.cargo/bin/rustup toolchain install 1.76 - name: Build - run: make release NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make release NUM_THREADS=$(nproc) + echo "Build,$?" > status.txt - name: Test - run: make test NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make test NUM_THREADS=$(nproc) + echo "Test,$?" >> status.txt - name: C and C++ examples - run: make example NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make example NUM_THREADS=$(nproc) + echo "C and C++ examples,$?" >> status.txt - name: Python test + continue-on-error: true run: | source /opt/venv/bin/activate make pytest NUM_THREADS=$(nproc) + echo "Python test,$?" >> status.txt - name: Node.js test - run: make nodejstest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make nodejstest NUM_THREADS=$(nproc) + echo "Node.js test,$?" >> status.txt - name: Java test - run: make javatest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make javatest NUM_THREADS=$(nproc) + echo "Java test,$?" >> status.txt - name: Rust share build + continue-on-error: true run: echo $'[workspace]\nmembers = ["tools/rust_api","examples/rust"]' > Cargo.toml - name: Rust set env + continue-on-error: true run: echo "CARGO_BUILD_JOBS=$(nproc)" >> $GITHUB_ENV - name: Rust test + continue-on-error: true working-directory: tools/rust_api run: | cargo test --release --features arrow -- --test-threads=1 + echo "Rust test,$?" >> ../../status.txt - name: Rust example + continue-on-error: true working-directory: examples/rust - run: cargo build --release --features arrow - - centos-7-build-test: - name: centos-7 - runs-on: ubuntu-latest - container: - image: quay.io/pypa/manylinux2014_x86_64 - env: - CC: gcc - CXX: g++ - PYBIND11_PYTHON_VERSION: 3.10 - PYTHON_EXECUTABLE: /usr/local/bin/python3.10 - JAVA_HOME: /usr/lib/jvm/java-11-openjdk - steps: - - name: Install packages - run: | - yum update -y - yum install -y npm java-11-openjdk-devel devtoolset-11 - - - name: Enable gcc-toolset-11 run: | - source /opt/rh/devtoolset-11/enable - echo $PATH >> $GITHUB_PATH - - - uses: actions/checkout@v3 - - - name: Ensure Python dependencies - run: | - ln -s /usr/local/bin/python3.10 /usr/bin/python3 - python3 -m pip install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu - python3 -m pip install --user -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html - - - name: Ensure Node.js dependencies - working-directory: tools/nodejs_api - run: npm install --include=dev - - - name: Install Rust - run: | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-update-default-toolchain - echo "$HOME/.cargo/bin" >> $GITHUB_PATH - $HOME/.cargo/bin/rustup toolchain install 1.67 - - - name: Build - run: make release NUM_THREADS=$(nproc) - - - name: Test - run: make test NUM_THREADS=$(nproc) - - - name: C and C++ examples - run: make example NUM_THREADS=$(nproc) - - - name: Python test - run: make pytest NUM_THREADS=$(nproc) - - - name: Node.js test - run: make nodejstest NUM_THREADS=$(nproc) - - - name: Java test - run: make javatest NUM_THREADS=$(nproc) - - - name: Rust share build - run: echo $'[workspace]\nmembers = ["tools/rust_api","examples/rust"]' > Cargo.toml - - - name: Rust set env - run: echo "CARGO_BUILD_JOBS=$(nproc)" >> $GITHUB_ENV + cargo build --release --features arrow + echo "Rust example,$?" >> ../../status.txt - - name: Rust test - working-directory: tools/rust_api + - name: Rename status.txt + continue-on-error: true run: | - cargo test --release --features arrow -- --test-threads=1 + PLATFORM=$(echo ${{ matrix.image }} | tr ':' '-') + echo "PLATFORM=$PLATFORM" >> $GITHUB_ENV + mv status.txt $PLATFORM.csv - - name: Rust example - working-directory: examples/rust - run: cargo build --release --features arrow + - uses: actions/upload-artifact@v4 + continue-on-error: true + with: + name: ${{env.PLATFORM}} + path: ${{env.PLATFORM}}.csv archlinux-build-test: name: archlinux @@ -459,56 +603,135 @@ jobs: JAVA_HOME: /usr/lib/jvm/java-17-openjdk steps: - name: Install packages + continue-on-error: true run: | pacman -Syu --noconfirm pacman -S --needed --noconfirm git base-devel cmake gcc python python-pip npm jdk17-openjdk - uses: actions/checkout@v3 + continue-on-error: true - name: Ensure Python dependencies + continue-on-error: true run: | pip install torch~=2.0.0 --extra-index-url https://download.pytorch.org/whl/cpu --break-system-packages pip install --user -r tools/python_api/requirements_dev.txt -f https://data.pyg.org/whl/torch-2.0.0+cpu.html --break-system-packages - name: Ensure Node.js dependencies + continue-on-error: true working-directory: tools/nodejs_api run: npm install --include=dev - name: Install Rust + continue-on-error: true run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-update-default-toolchain echo "$HOME/.cargo/bin" >> $GITHUB_PATH - $HOME/.cargo/bin/rustup toolchain install 1.67 + $HOME/.cargo/bin/rustup toolchain install 1.76 - name: Build - run: make release NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make release NUM_THREADS=$(nproc) + echo "Build,$?" > status.txt - name: Test - run: make test NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make test NUM_THREADS=$(nproc) + echo "Test,$?" >> status.txt - name: C and C++ examples - run: make example NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make example NUM_THREADS=$(nproc) + echo "C and C++ examples,$?" >> status.txt - name: Python test - run: make pytest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make pytest NUM_THREADS=$(nproc) + echo "Python test,$?" >> status.txt - name: Node.js test - run: make nodejstest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make nodejstest NUM_THREADS=$(nproc) + echo "Node.js test,$?" >> status.txt - name: Java test - run: make javatest NUM_THREADS=$(nproc) + continue-on-error: true + run: | + make javatest NUM_THREADS=$(nproc) + echo "Java test,$?" >> status.txt - name: Rust share build + continue-on-error: true run: echo $'[workspace]\nmembers = ["tools/rust_api","examples/rust"]' > Cargo.toml - name: Rust set env + continue-on-error: true run: echo "CARGO_BUILD_JOBS=$(nproc)" >> $GITHUB_ENV - name: Rust test working-directory: tools/rust_api + continue-on-error: true run: | cargo test --release --features arrow -- --test-threads=1 + echo "Rust test,$?" >> ../../status.txt - name: Rust example working-directory: examples/rust - run: cargo build --release --features arrow + continue-on-error: true + run: | + cargo build --release --features arrow + echo "Rust example,$?" >> ../../status.txt + + - name: Rename status.txt + continue-on-error: true + run: | + mv status.txt archlinux.csv + + - uses: actions/upload-artifact@v4 + continue-on-error: true + with: + name: archlinux + path: archlinux.csv + + collect-results: + runs-on: ubuntu-latest + env: + DISCORD_CHANNEL_ID: ${{ secrets.DISCORD_CHANNEL_ID }} + DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }} + GITHUB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + needs: + [ + ubuntu-2004-build-test, + macos-build-test, + windows-build-test, + debian-ubuntu-build-test, + rhel-fedora-build-test, + archlinux-build-test, + ] + steps: + - uses: actions/checkout@v3 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: results + + - name: List artifacts + run: ls -R results + + - name: Create summary + run: | + pip3 install pandas tabulate discord.py + python3 scripts/multiplatform-test-helper/collect-results.py results + python3 scripts/multiplatform-test-helper/notify-discord.py results.json + + - name: Upload summary + uses: actions/upload-artifact@v4 + with: + name: results + path: results.md diff --git a/.gitignore b/.gitignore index a073684b3d1..6c496cb8e21 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ compile_commands.json ### Python # Byte-compiled / optimized / DLL files __pycache__/ +.venv/ *.py[cod] *$py.class cmake-build-debug/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8520f18aaa3..88aae897602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.15) -project(Kuzu VERSION 0.3.1.1 LANGUAGES CXX C) +project(Kuzu VERSION 0.3.2.5 LANGUAGES CXX C) find_package(Threads REQUIRED) @@ -46,6 +46,7 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) message(STATUS "32-bit architecture detected") add_compile_definitions(__32BIT__) + set(__32BIT__ TRUE) endif() if(NOT CMAKE_BUILD_TYPE) @@ -103,8 +104,8 @@ if(MSVC) # Enables support for custom hardware exception handling add_compile_options("/EHa") # Remove the default to avoid warnings - STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - STRING(REPLACE "/EHs" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + STRING(REPLACE "/EHs" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Store all libraries and binaries in the same directory so that kuzu_shared.dll is found at runtime set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/src") set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/src") @@ -196,7 +197,7 @@ endif () if(${BUILD_KUZU}) add_definitions(-DKUZU_ROOT_DIRECTORY="${PROJECT_SOURCE_DIR}") add_definitions(-DKUZU_CMAKE_VERSION="${CMAKE_PROJECT_VERSION}") -add_definitions(-DKUZU_EXTENSION_VERSION="0.1.0") +add_definitions(-DKUZU_EXTENSION_VERSION="0.2.5") include_directories(src/include) include_directories(third_party/antlr4_cypher/include) @@ -226,7 +227,9 @@ elseif (${BUILD_BENCHMARK}) endif () add_subdirectory(tools) endif () -add_subdirectory(extension) +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/extension/CMakeLists.txt") + add_subdirectory(extension) +endif () if (${BUILD_EXAMPLES}) add_subdirectory(examples/c) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 23bd98c367b..4d6ed6826d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ Welcome to Kùzu! We are excited that you are interested in contributing to Kùzu. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines. -Join our project's [Slack workspace](https://join.slack.com/t/kuzudb/shared_invite/zt-1w0thj6s7-0bLaU8Sb~4fDMKJ~oejG_g) for real-time communication with the core team and other contributors. +Join our project's [Discord community](https://discord.gg/VtX2gw9Rug) for real-time communication with the core team and other contributors. If you have a question or need help, feel free to ask in the appropriate channel or create an issue. ## Code of Conduct diff --git a/LICENSE b/LICENSE index 2eac1b77815..60179b0a3ec 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Kùzu Contributors +Copyright (c) 2022-2024 Kùzu Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 3b541b55845..1eeae88d6a6 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ allconfig: $(call config-cmake-release, \ -DBUILD_BENCHMARK=TRUE \ -DBUILD_EXAMPLES=TRUE \ - -DBUILD_EXTENSIONS=httpfs \ + -DBUILD_EXTENSIONS="httpfs;duckdb_scanner;postgres_scanner" \ -DBUILD_JAVA=TRUE \ -DBUILD_NODEJS=TRUE \ -DBUILD_PYTHON=TRUE \ @@ -79,7 +79,7 @@ alldebug: $(call run-cmake-debug, \ -DBUILD_BENCHMARK=TRUE \ -DBUILD_EXAMPLES=TRUE \ - -DBUILD_EXTENSIONS=httpfs \ + -DBUILD_EXTENSIONS="httpfs;duckdb_scanner;postgres_scanner" \ -DBUILD_JAVA=TRUE \ -DBUILD_NODEJS=TRUE \ -DBUILD_PYTHON=TRUE \ @@ -156,21 +156,21 @@ example: extension-test: $(call run-cmake-release, \ - -DBUILD_EXTENSIONS=httpfs \ + -DBUILD_EXTENSIONS="httpfs;duckdb_scanner;postgres_scanner" \ -DBUILD_EXTENSION_TESTS=TRUE \ ) - ctest --test-dir build/release/extension/httpfs/test --output-on-failure -j ${TEST_JOBS} + ctest --test-dir build/release/extension --output-on-failure -j ${TEST_JOBS} aws s3 rm s3://kuzu-dataset-us/${RUN_ID}/ --recursive extension-debug: $(call run-cmake-debug, \ - -DBUILD_EXTENSIONS=httpfs \ + -DBUILD_EXTENSIONS="httpfs;duckdb_scanner;postgres_scanner" \ -DBUILD_KUZU=FALSE \ ) extension-release: $(call run-cmake-release, \ - -DBUILD_EXTENSIONS=httpfs \ + -DBUILD_EXTENSIONS="httpfs;duckdb_scanner;postgres_scanner" \ -DBUILD_KUZU=FALSE \ ) diff --git a/README.md b/README.md index f229aab0690..00b0fbe4f64 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,13 @@

- Github Actions Badge - + Github Actions Badge - - + - discord - + discord - twitter - + twitter

# Kùzu @@ -46,20 +42,15 @@ Kùzu is available under a permissible license. So try it out and help us make i | C/C++ | [precompiled binaries](https://github.com/kuzudb/kuzu/releases/latest) | | CLI | [precompiled binaries](https://github.com/kuzudb/kuzu/releases/latest) | -To learn more about installation, see our [Installation](https://kuzudb.com/docusaurus/installation/) page. +To learn more about installation, see our [Installation](https://docs.kuzudb.com/installation) page. ## Getting Started -Refer to our [Getting Started](https://kuzudb.com/docusaurus/getting-started/) page for your first example. - -More information can be found at -- [Data Import](https://kuzudb.com/docusaurus/data-import/) -- [Cypher Reference](https://kuzudb.com/docusaurus/cypher/) -- [Client APIs](https://kuzudb.com/docusaurus/client-apis/) +Refer to our [Getting Started](https://docs.kuzudb.com/get-started/) page for your first example. ## Build from Source -Instructions can be found at [Build Kùzu from Source](https://kuzudb.com/docusaurus/development/building-kuzu). +You can build from source using the instructions provided in the [developer guide](https://docs.kuzudb.com/developer-guide). ## Contributing We welcome contributions to Kùzu. If you are interested in contributing to Kùzu, please read our [Contributing Guide](CONTRIBUTING.md). diff --git a/dataset/load-from-test/fixed_list/fixed_list_correct.csv b/dataset/load-from-test/array/array_correct.csv similarity index 100% rename from dataset/load-from-test/fixed_list/fixed_list_correct.csv rename to dataset/load-from-test/array/array_correct.csv diff --git a/dataset/load-from-test/fixed_list/fixed_list_int64.csv b/dataset/load-from-test/array/array_int64.csv similarity index 100% rename from dataset/load-from-test/fixed_list/fixed_list_int64.csv rename to dataset/load-from-test/array/array_int64.csv diff --git a/dataset/load-from-test/fixed_list/fixed_list_null.csv b/dataset/load-from-test/array/array_null.csv similarity index 100% rename from dataset/load-from-test/fixed_list/fixed_list_null.csv rename to dataset/load-from-test/array/array_null.csv diff --git a/dataset/load-from-test/fixed_list/fixed_list_null2.csv b/dataset/load-from-test/array/array_null2.csv similarity index 100% rename from dataset/load-from-test/fixed_list/fixed_list_null2.csv rename to dataset/load-from-test/array/array_null2.csv diff --git a/dataset/load-from-test/fixed_list/unsupported_type.csv b/dataset/load-from-test/array/array_string.csv similarity index 100% rename from dataset/load-from-test/fixed_list/unsupported_type.csv rename to dataset/load-from-test/array/array_string.csv diff --git a/dataset/load-from-test/fixed_list/unsupported_type2.csv b/dataset/load-from-test/array/array_uint8.csv similarity index 100% rename from dataset/load-from-test/fixed_list/unsupported_type2.csv rename to dataset/load-from-test/array/array_uint8.csv diff --git a/dataset/load-from-test/fixed_list/fixed_list_with_null.csv b/dataset/load-from-test/array/array_with_null.csv similarity index 100% rename from dataset/load-from-test/fixed_list/fixed_list_with_null.csv rename to dataset/load-from-test/array/array_with_null.csv diff --git a/dataset/load-from-test/fixed_list/error_conversion.csv b/dataset/load-from-test/array/error_conversion.csv similarity index 100% rename from dataset/load-from-test/fixed_list/error_conversion.csv rename to dataset/load-from-test/array/error_conversion.csv diff --git a/dataset/load-from-test/fixed_list/error_conversion2.csv b/dataset/load-from-test/array/error_conversion2.csv similarity index 100% rename from dataset/load-from-test/fixed_list/error_conversion2.csv rename to dataset/load-from-test/array/error_conversion2.csv diff --git a/dataset/load-from-test/fixed_list/incorrect_num.csv b/dataset/load-from-test/array/incorrect_num.csv similarity index 100% rename from dataset/load-from-test/fixed_list/incorrect_num.csv rename to dataset/load-from-test/array/incorrect_num.csv diff --git a/dataset/load-from-test/fixed_list/long_fixed_list.csv b/dataset/load-from-test/array/long_array.csv similarity index 100% rename from dataset/load-from-test/fixed_list/long_fixed_list.csv rename to dataset/load-from-test/array/long_array.csv diff --git a/dataset/load-from-test/fixed_list/long_fixed_list2.csv b/dataset/load-from-test/array/long_array2.csv similarity index 100% rename from dataset/load-from-test/fixed_list/long_fixed_list2.csv rename to dataset/load-from-test/array/long_array2.csv diff --git a/dataset/load-from-test/fixed_list/zero_ele.csv b/dataset/load-from-test/array/zero_ele.csv similarity index 100% rename from dataset/load-from-test/fixed_list/zero_ele.csv rename to dataset/load-from-test/array/zero_ele.csv diff --git a/dataset/load-from-test/var_list/bracket_error.csv b/dataset/load-from-test/list/bracket_error.csv similarity index 100% rename from dataset/load-from-test/var_list/bracket_error.csv rename to dataset/load-from-test/list/bracket_error.csv diff --git a/dataset/load-from-test/var_list/change_config.csv b/dataset/load-from-test/list/change_config.csv similarity index 100% rename from dataset/load-from-test/var_list/change_config.csv rename to dataset/load-from-test/list/change_config.csv diff --git a/dataset/load-from-test/var_list/change_config_error.csv b/dataset/load-from-test/list/change_config_error.csv similarity index 100% rename from dataset/load-from-test/var_list/change_config_error.csv rename to dataset/load-from-test/list/change_config_error.csv diff --git a/dataset/load-from-test/var_list/conversion_error.csv b/dataset/load-from-test/list/conversion_error.csv similarity index 100% rename from dataset/load-from-test/var_list/conversion_error.csv rename to dataset/load-from-test/list/conversion_error.csv diff --git a/dataset/load-from-test/var_list/delim_error.csv b/dataset/load-from-test/list/delim_error.csv similarity index 100% rename from dataset/load-from-test/var_list/delim_error.csv rename to dataset/load-from-test/list/delim_error.csv diff --git a/dataset/load-from-test/var_list/quote_error.csv b/dataset/load-from-test/list/quote_error.csv similarity index 100% rename from dataset/load-from-test/var_list/quote_error.csv rename to dataset/load-from-test/list/quote_error.csv diff --git a/dataset/load-from-test/var_list/should_pass.csv b/dataset/load-from-test/list/should_pass.csv similarity index 100% rename from dataset/load-from-test/var_list/should_pass.csv rename to dataset/load-from-test/list/should_pass.csv diff --git a/dataset/load-from-test/var_list/single_quote.csv b/dataset/load-from-test/list/single_quote.csv similarity index 100% rename from dataset/load-from-test/var_list/single_quote.csv rename to dataset/load-from-test/list/single_quote.csv diff --git a/dataset/load-from-test/var_list/single_quote2.csv b/dataset/load-from-test/list/single_quote2.csv similarity index 100% rename from dataset/load-from-test/var_list/single_quote2.csv rename to dataset/load-from-test/list/single_quote2.csv diff --git a/dataset/load-from-test/var_list/single_struct_bracket.csv b/dataset/load-from-test/list/single_struct_bracket.csv similarity index 100% rename from dataset/load-from-test/var_list/single_struct_bracket.csv rename to dataset/load-from-test/list/single_struct_bracket.csv diff --git a/dataset/load-from-test/struct/struct_with_fixed_list.csv b/dataset/load-from-test/struct/struct_with_array.csv similarity index 100% rename from dataset/load-from-test/struct/struct_with_fixed_list.csv rename to dataset/load-from-test/struct/struct_with_array.csv diff --git a/dataset/long-string-pk-tests/schema.cypher b/dataset/long-string-pk-tests/schema.cypher index c2d3476cb82..014a774e006 100644 --- a/dataset/long-string-pk-tests/schema.cypher +++ b/dataset/long-string-pk-tests/schema.cypher @@ -1,2 +1,2 @@ -CREATE NODE TABLE Person(name STRING, spouse STRING, PRIMARY KEY (name)) +CREATE NODE TABLE Person (name STRING, spouse STRING, PRIMARY KEY (name)) create REL TABLE Knows (FROM Person TO Person); diff --git a/dataset/tinysnb/copy.cypher b/dataset/tinysnb/copy.cypher index f918361f5cb..1e852119b3c 100644 --- a/dataset/tinysnb/copy.cypher +++ b/dataset/tinysnb/copy.cypher @@ -1,7 +1,9 @@ +CALL ENABLE_MULTI_COPY=true COPY person FROM "dataset/tinysnb/vPerson.csv" (HeaDER=true, deLim=','); COPY organisation FROM "dataset/tinysnb/vOrganisation.csv"; COPY movies FROM "dataset/tinysnb/vMovies.csv"; COPY knows FROM "dataset/tinysnb/eKnows.csv"; +COPY knows FROM "dataset/tinysnb/eKnows_2.csv"; COPY studyAt FROM "dataset/tinysnb/eStudyAt.csv" (HeaDER=true); COPY workAt FROM "dataset/tinysnb/eWorkAt.csv"; COPY meets FROM "dataset/tinysnb/eMeets.csv"; diff --git a/dataset/tinysnb/eKnows.csv b/dataset/tinysnb/eKnows.csv index 471e63a0c2d..4d9278b3061 100644 --- a/dataset/tinysnb/eKnows.csv +++ b/dataset/tinysnb/eKnows.csv @@ -4,11 +4,3 @@ 2,0,2021-06-30,1946-08-25 19:07:22,10 years 5 months 13 hours 24 us,"[2huh9y89fsfw23,23nsihufhw723]","{locations:['paris'], transfer: {day: 2000-01-01, amount: [20, 5000]}}",4, 2,3,1950-05-14,1946-08-25 19:07:22,23 minutes,"[fwehu9h9832wewew,23u9h989sdfsss]","{locations:['paris'], transfer: {day: 2011-05-01, amount: [2000, 5340]}}","cool stuff found", 2,5,1950-05-14,2012-12-11 20:07:22,20 years 30 days 48 hours,"[fwh9y81232uisuiehuf,ewnuihxy8dyf232]","{locations:['vancouver'], transfer: {day: 2020-01-01, amount: [120, 50]}}","matthew perry", -3,0,2021-06-30,2002-07-31 11:42:53.12342,30 hours 40 days,"[fnioh8323aeweae34d,osd89e2ejshuih12]","{locations:['london','toronto'], transfer: {day: 2012-11-21, amount: [223, 5230]}}",10, -3,2,1950-05-14,2007-02-12 12:11:42.123,28 minutes 30 milliseconds,"[fwh983-sdjisdfji,ioh89y32r2huir]","{locations:['paris','beijing'], transfer: {day: 2011-03-11, amount: [2323, 50]}}",1, -3,5,2000-01-01,1998-10-02 13:09:22.423,300 milliseconds,"[psh989823oaaioe,nuiuah1nosndfisf]","{locations:[], transfer: {day: 1980-11-21, amount: [20, 5]}}",2, -5,0,2021-06-30,1936-11-02 11:02:01,480us,"[fwewe]","{locations:['shanghai','nanjing'], transfer: {day: 1998-11-12, amount: [22, 53240]}}",15, -5,2,1950-05-14,1982-11-11 13:12:05.123,23 minutes,"[fewh9182912e3,h9y8y89soidfsf,nuhudf78w78efw,hioshe0f9023sdsd]","{locations:['paris'], transfer: {day: 2000-01-01, amount: [20, 5000]}}","happy new year", -5,3,2000-01-01,1999-04-21 15:12:11.42,48 hours 52 milliseconds,"[23h9sdslnfowhu2932,shuhf98922323sf]","{locations:['paris'], transfer: {day: 2000-01-01, amount: [20, 5000]}}",4, -7,8,1905-12-12,2025-01-01 11:22:33.52,47 minutes 58 seconds,"[ahu2333333333333,12weeeeeeeeeeeeeeeeee]","{locations:['toronto','thisisalongcityname'], transfer: {day: 1930-11-22, amount: [18, 323]}}",8, -7,9,1905-12-12,2020-03-01 12:11:41.6552,47 minutes 58 seconds,"[peweeeeeeeeeeeeeeeee,kowje9w0eweeeeeeeee]","{locations:['waterloo'], transfer: {day: 2000-01-01, amount: [1000, 5000]}}",10, diff --git a/dataset/tinysnb/eKnows_2.csv b/dataset/tinysnb/eKnows_2.csv new file mode 100644 index 00000000000..5b023bcf814 --- /dev/null +++ b/dataset/tinysnb/eKnows_2.csv @@ -0,0 +1,8 @@ +3,0,2021-06-30,2002-07-31 11:42:53.12342,30 hours 40 days,"[fnioh8323aeweae34d,osd89e2ejshuih12]","{locations:['london','toronto'], transfer: {day: 2012-11-21, amount: [223, 5230]}}",10, +3,2,1950-05-14,2007-02-12 12:11:42.123,28 minutes 30 milliseconds,"[fwh983-sdjisdfji,ioh89y32r2huir]","{locations:['paris','beijing'], transfer: {day: 2011-03-11, amount: [2323, 50]}}",1, +3,5,2000-01-01,1998-10-02 13:09:22.423,300 milliseconds,"[psh989823oaaioe,nuiuah1nosndfisf]","{locations:[], transfer: {day: 1980-11-21, amount: [20, 5]}}",2, +5,0,2021-06-30,1936-11-02 11:02:01,480us,"[fwewe]","{locations:['shanghai','nanjing'], transfer: {day: 1998-11-12, amount: [22, 53240]}}",15, +5,2,1950-05-14,1982-11-11 13:12:05.123,23 minutes,"[fewh9182912e3,h9y8y89soidfsf,nuhudf78w78efw,hioshe0f9023sdsd]","{locations:['paris'], transfer: {day: 2000-01-01, amount: [20, 5000]}}","happy new year", +5,3,2000-01-01,1999-04-21 15:12:11.42,48 hours 52 milliseconds,"[23h9sdslnfowhu2932,shuhf98922323sf]","{locations:['paris'], transfer: {day: 2000-01-01, amount: [20, 5000]}}",4, +7,8,1905-12-12,2025-01-01 11:22:33.52,47 minutes 58 seconds,"[ahu2333333333333,12weeeeeeeeeeeeeeeeee]","{locations:['toronto','thisisalongcityname'], transfer: {day: 1930-11-22, amount: [18, 323]}}",8, +7,9,1905-12-12,2020-03-01 12:11:41.6552,47 minutes 58 seconds,"[peweeeeeeeeeeeeeeeee,kowje9w0eweeeeeeeee]","{locations:['waterloo'], transfer: {day: 2000-01-01, amount: [1000, 5000]}}",10, diff --git a/examples/rust/Cargo.lock b/examples/rust/Cargo.lock index f6e2e480e29..d47685b733c 100644 --- a/examples/rust/Cargo.lock +++ b/examples/rust/Cargo.lock @@ -404,7 +404,7 @@ dependencies = [ [[package]] name = "kuzu" -version = "0.3.1" +version = "0.3.2" dependencies = [ "arrow", "cmake", diff --git a/extension/CMakeLists.txt b/extension/CMakeLists.txt index 162294bf26b..0f362842346 100644 --- a/extension/CMakeLists.txt +++ b/extension/CMakeLists.txt @@ -1,3 +1,29 @@ if("httpfs" IN_LIST BUILD_EXTENSIONS) add_subdirectory(httpfs) endif() + +if ("duckdb_scanner" IN_LIST BUILD_EXTENSIONS) + if(NOT __32BIT__) + # DuckDB does not officially support 32-bit builds, so we disable the + # extension for 32-bit builds + add_subdirectory(duckdb_scanner) + endif() +endif() + +if ("postgres_scanner" IN_LIST BUILD_EXTENSIONS) + add_subdirectory(postgres_scanner) +endif() + +if (${BUILD_EXTENSION_TESTS}) + add_definitions(-DTEST_FILES_DIR="extension") + add_subdirectory(${CMAKE_SOURCE_DIR}/test/gtest ${CMAKE_CURRENT_BINARY_DIR}/test/gtest EXCLUDE_FROM_ALL) + # Make gtest available to subdirectories. + add_library(GTest::GTest INTERFACE IMPORTED) + target_link_libraries(GTest::GTest INTERFACE gtest_main) + target_link_libraries(GTest::GTest INTERFACE gmock_main) + enable_testing() + add_subdirectory(${CMAKE_SOURCE_DIR}/test/test_helper ${CMAKE_CURRENT_BINARY_DIR}/test/test_helper) + add_subdirectory(${CMAKE_SOURCE_DIR}/test/test_runner ${CMAKE_CURRENT_BINARY_DIR}/test/test_runner) + add_subdirectory(${CMAKE_SOURCE_DIR}/test/graph_test ${CMAKE_CURRENT_BINARY_DIR}/test/graph_test) + add_subdirectory(${CMAKE_SOURCE_DIR}/test/runner ${CMAKE_CURRENT_BINARY_DIR}/test/runner) +endif() diff --git a/extension/duckdb_scanner/CMakeLists.txt b/extension/duckdb_scanner/CMakeLists.txt new file mode 100644 index 00000000000..0d1279f5996 --- /dev/null +++ b/extension/duckdb_scanner/CMakeLists.txt @@ -0,0 +1,56 @@ +find_package(DuckDB REQUIRED) + +include_directories( + ${PROJECT_SOURCE_DIR}/src/include + src/include + ${DuckDB_INCLUDE_DIRS}) + +add_library(duckdb_scanner + SHARED + src/duckdb_scanner_extension.cpp + src/duckdb_storage.cpp + src/duckdb_scan.cpp + src/duckdb_type_converter.cpp + src/duckdb_catalog.cpp + src/duckdb_table_catalog_entry.cpp) + +set_target_properties(duckdb_scanner + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" +) + +target_link_libraries(duckdb_scanner + PRIVATE + ${DuckDB_LIBRARIES}) + +set_target_properties(duckdb_scanner PROPERTIES + OUTPUT_NAME duckdb_scanner + PREFIX "lib" + SUFFIX ".kuzu_extension" +) + +if (WIN32) + # On windows, there is no dynamic lookup available, so it's not + # possible to generically look for symbols on library load. There are + # two main alternatives to statically linking kuzu, neither of which is + # appealing: + # 1. Link against the shared library. This works well assuming + # the DLL is locatable, but this assumption isn't valid for users + # of kuzu_shell.exe. + # 2. Link against the executable (kuzu_shell.exe). This is + # strange but works well for kuzu_shell.exe. However, it forces + # users who are embedding kuzu in their application to recompile + # the extension _and_ export the symbols for the extension to + # locate on load. + # We choose the simplest option. Windows isn't known + # for its small libraries anyways... + # Future work could make it possible to embed extension into kuzu, + # which would help fix this problem. + target_link_libraries(duckdb_scanner PRIVATE kuzu) +endif() + +if (APPLE) + set_target_properties(duckdb_scanner PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") +endif () diff --git a/extension/duckdb_scanner/src/duckdb_catalog.cpp b/extension/duckdb_scanner/src/duckdb_catalog.cpp new file mode 100644 index 00000000000..cf11fea6ac8 --- /dev/null +++ b/extension/duckdb_scanner/src/duckdb_catalog.cpp @@ -0,0 +1,134 @@ +#include "duckdb_catalog.h" + +#include "common/exception/binder.h" +#include "duckdb_table_catalog_entry.h" +#include "duckdb_type_converter.h" + +namespace kuzu { +namespace duckdb_scanner { + +void DuckDBCatalogContent::init(const std::string& dbPath, const std::string& catalogName, + main::ClientContext* context) { + auto [db, con] = getConnection(dbPath); + auto query = common::stringFormat( + "select table_name from information_schema.tables where table_catalog = '{}' and " + "table_schema = '{}';", + catalogName, getDefaultSchemaName()); + auto result = con.Query(query); + std::unique_ptr resultChunk; + try { + resultChunk = result->Fetch(); + } catch (std::exception& e) { + throw common::BinderException(e.what()); + } + if (resultChunk->size() == 0) { + return; + } + common::ValueVector tableNamesVector{*common::LogicalType::STRING(), + context->getMemoryManager()}; + duckdb_scanner::duckdb_conversion_func_t conversionFunc; + duckdb_scanner::getDuckDBVectorConversionFunc(common::PhysicalTypeID::STRING, conversionFunc); + conversionFunc(resultChunk->data[0], tableNamesVector, resultChunk->size()); + for (auto i = 0u; i < resultChunk->size(); i++) { + auto tableName = tableNamesVector.getValue(i).getAsString(); + createForeignTable(con, tableName, dbPath, catalogName); + } +} + +static std::string getQuery(const binder::BoundCreateTableInfo& info) { + auto extraInfo = common::ku_dynamic_cast(info.extraInfo.get()); + return common::stringFormat("SELECT * FROM {}.{}.{}", extraInfo->catalogName, + extraInfo->schemaName, info.tableName); +} + +void DuckDBCatalogContent::createForeignTable(duckdb::Connection& con, const std::string& tableName, + const std::string& dbPath, const std::string& catalogName) { + auto tableID = assignNextTableID(); + auto info = bindCreateTableInfo(con, tableName, dbPath, catalogName); + if (info == nullptr) { + return; + } + auto extraInfo = common::ku_dynamic_cast(info->extraInfo.get()); + std::vector columnTypes; + std::vector columnNames; + for (auto& propertyInfo : extraInfo->propertyInfos) { + columnNames.push_back(propertyInfo.name); + columnTypes.push_back(propertyInfo.type); + } + DuckDBScanBindData bindData(getQuery(*info), std::move(columnTypes), std::move(columnNames), + std::bind(&DuckDBCatalogContent::getConnection, this, dbPath)); + auto tableEntry = std::make_unique(info->tableName, tableID, + getScanFunction(std::move(bindData))); + for (auto& propertyInfo : extraInfo->propertyInfos) { + tableEntry->addProperty(propertyInfo.name, propertyInfo.type.copy()); + } + tables->createEntry(std::move(tableEntry)); +} + +static bool getTableInfo(duckdb::Connection& con, const std::string& tableName, + const std::string& schemaName, const std::string& catalogName, + std::vector& columnTypes, std::vector& columnNames) { + auto query = + common::stringFormat("select data_type,column_name from information_schema.columns where " + "table_name = '{}' and table_schema = '{}' and table_catalog = '{}';", + tableName, schemaName, catalogName); + auto result = con.Query(query); + if (result->RowCount() == 0) { + return false; + } + columnTypes.reserve(result->RowCount()); + columnNames.reserve(result->RowCount()); + for (auto i = 0u; i < result->RowCount(); i++) { + try { + columnTypes.push_back(DuckDBTypeConverter::convertDuckDBType( + result->GetValue(0, i).GetValue())); + } catch (common::BinderException& e) { + return false; + } + columnNames.push_back(result->GetValue(1, i).GetValue()); + } + return true; +} + +bool DuckDBCatalogContent::bindPropertyInfos(duckdb::Connection& con, const std::string& tableName, + const std::string& catalogName, std::vector& propertyInfos) { + std::vector columnTypes; + std::vector columnNames; + if (!getTableInfo(con, tableName, getDefaultSchemaName(), catalogName, columnTypes, + columnNames)) { + return false; + } + for (auto i = 0u; i < columnNames.size(); i++) { + auto propertyInfo = binder::PropertyInfo(columnNames[i], columnTypes[i]); + propertyInfos.push_back(std::move(propertyInfo)); + } + return true; +} + +std::unique_ptr DuckDBCatalogContent::bindCreateTableInfo( + duckdb::Connection& con, const std::string& tableName, const std::string& dbPath, + const std::string& catalogName) { + std::vector propertyInfos; + if (!bindPropertyInfos(con, tableName, catalogName, propertyInfos)) { + return nullptr; + } + return std::make_unique(common::TableType::FOREIGN, tableName, + std::make_unique(dbPath, catalogName, + getDefaultSchemaName(), std::move(propertyInfos))); +} + +std::string DuckDBCatalogContent::getDefaultSchemaName() const { + return "main"; +} + +std::pair DuckDBCatalogContent::getConnection( + const std::string& dbPath) const { + duckdb::DuckDB db(dbPath); + duckdb::Connection con(db); + return std::make_pair(std::move(db), std::move(con)); +} + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/duckdb_scan.cpp b/extension/duckdb_scanner/src/duckdb_scan.cpp new file mode 100644 index 00000000000..e1ac8454e00 --- /dev/null +++ b/extension/duckdb_scanner/src/duckdb_scan.cpp @@ -0,0 +1,233 @@ +#include "duckdb_scan.h" + +#include "common/types/types.h" +#include "function/table/bind_input.h" + +using namespace kuzu::function; +using namespace kuzu::common; + +namespace kuzu { +namespace duckdb_scanner { + +void getDuckDBVectorConversionFunc(PhysicalTypeID physicalTypeID, + duckdb_conversion_func_t& conversion_func); + +DuckDBScanBindData::DuckDBScanBindData(std::string query, + std::vector columnTypes, std::vector columnNames, + init_duckdb_conn_t initDuckDBConn) + : TableFuncBindData{std::move(columnTypes), std::move(columnNames)}, query{std::move(query)}, + initDuckDBConn{std::move(initDuckDBConn)} { + conversionFunctions.resize(this->columnTypes.size()); + for (auto i = 0u; i < this->columnTypes.size(); i++) { + getDuckDBVectorConversionFunc(this->columnTypes[i].getPhysicalType(), + conversionFunctions[i]); + } +} + +std::unique_ptr DuckDBScanBindData::copy() const { + return std::make_unique(query, columnTypes, columnNames, initDuckDBConn); +} + +DuckDBScanSharedState::DuckDBScanSharedState(std::unique_ptr queryResult) + : TableFuncSharedState(), queryResult{std::move(queryResult)} {} + +struct DuckDBScanFunction { + static constexpr char DUCKDB_SCAN_FUNC_NAME[] = "duckdb_scan"; + + static common::offset_t tableFunc(function::TableFuncInput& input, + function::TableFuncOutput& output); + + static std::unique_ptr bindFunc(DuckDBScanBindData bindData, + main::ClientContext* /*context*/, function::TableFuncBindInput* input); + + static std::unique_ptr initSharedState( + function::TableFunctionInitInput& input); + + static std::unique_ptr initLocalState( + function::TableFunctionInitInput& input, function::TableFuncSharedState* state, + storage::MemoryManager* + /*mm*/); +}; + +std::unique_ptr DuckDBScanFunction::initSharedState( + function::TableFunctionInitInput& input) { + auto scanBindData = reinterpret_cast(input.bindData); + auto [db, conn] = scanBindData->initDuckDBConn(); + auto result = conn.SendQuery(scanBindData->query); + if (result->HasError()) { + throw common::RuntimeException( + common::stringFormat("Failed to execute query: {} in duckdb.", result->GetError())); + } + return std::make_unique(std::move(result)); +} + +std::unique_ptr DuckDBScanFunction::initLocalState( + function::TableFunctionInitInput& /*input*/, function::TableFuncSharedState* /*state*/, + storage::MemoryManager* /*mm*/) { + return std::make_unique(); +} + +template +void convertDuckDBVectorToVector(duckdb::Vector& duckDBVector, ValueVector& result, + uint64_t numValuesToCopy) { + auto duckDBData = (T*)duckDBVector.GetData(); + auto validityMasks = duckdb::FlatVector::Validity(duckDBVector); + memcpy(result.getData(), duckDBData, numValuesToCopy * result.getNumBytesPerValue()); + for (auto i = 0u; i < numValuesToCopy; i++) { + result.setNull(i, !validityMasks.RowIsValid(i)); + } +} + +template<> +void convertDuckDBVectorToVector(duckdb::Vector& duckDBVector, ValueVector& result, + uint64_t numValuesToCopy); +template<> +void convertDuckDBVectorToVector(duckdb::Vector& duckDBVector, ValueVector& result, + uint64_t numValuesToCopy); + +template<> +void convertDuckDBVectorToVector(duckdb::Vector& duckDBVector, ValueVector& result, + uint64_t numValuesToCopy) { + auto strs = reinterpret_cast(duckDBVector.GetData()); + auto validityMasks = duckdb::FlatVector::Validity(duckDBVector); + for (auto i = 0u; i < numValuesToCopy; i++) { + result.setNull(i, !validityMasks.RowIsValid(i)); + if (!result.isNull(i)) { + result.setValue(i, strs[i].GetString()); + } + } +} + +void getDuckDBVectorConversionFunc(PhysicalTypeID physicalTypeID, + duckdb_conversion_func_t& conversion_func) { + switch (physicalTypeID) { + case PhysicalTypeID::BOOL: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::INT128: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::INT64: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::INT32: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::INT16: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::INT8: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::UINT64: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::UINT32: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::UINT16: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::UINT8: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::DOUBLE: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::FLOAT: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::STRING: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::INTERVAL: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::LIST: { + conversion_func = convertDuckDBVectorToVector; + } break; + case PhysicalTypeID::STRUCT: { + conversion_func = convertDuckDBVectorToVector; + } break; + default: + KU_UNREACHABLE; + } +} + +template<> +void convertDuckDBVectorToVector(duckdb::Vector& duckDBVector, ValueVector& result, + uint64_t numValuesToCopy) { + memcpy(result.getData(), duckDBVector.GetData(), + numValuesToCopy * result.getNumBytesPerValue()); + auto numValuesInDataVec = 0; + auto listEntries = reinterpret_cast(duckDBVector.GetData()); + auto validityMasks = duckdb::FlatVector::Validity(duckDBVector); + for (auto i = 0u; i < numValuesToCopy; i++) { + result.setNull(i, !validityMasks.RowIsValid(i)); + if (!result.isNull(i)) { + numValuesInDataVec += listEntries[i].length; + } + } + ListVector::resizeDataVector(&result, numValuesInDataVec); + auto dataVec = ListVector::getDataVector(&result); + duckdb_conversion_func_t conversion_func; + getDuckDBVectorConversionFunc(dataVec->dataType.getPhysicalType(), conversion_func); + conversion_func(duckdb::ListVector::GetEntry(duckDBVector), *dataVec, numValuesInDataVec); +} + +template<> +void convertDuckDBVectorToVector(duckdb::Vector& duckDBVector, ValueVector& result, + uint64_t numValuesToCopy) { + auto& duckdbChildrenVectors = duckdb::StructVector::GetEntries(duckDBVector); + for (auto i = 0u; i < duckdbChildrenVectors.size(); i++) { + duckdb_conversion_func_t conversionFunc; + auto& duckdbChildVector = duckdbChildrenVectors[i]; + auto fieldVector = StructVector::getFieldVector(&result, i); + getDuckDBVectorConversionFunc(fieldVector->dataType.getPhysicalType(), conversionFunc); + conversionFunc(*duckdbChildVector, *fieldVector, numValuesToCopy); + } +} + +static void convertDuckDBResultToVector(duckdb::DataChunk& duckDBResult, DataChunk& result, + std::vector conversionFuncs) { + for (auto i = 0u; i < conversionFuncs.size(); i++) { + result.state->selVector->selectedSize = duckDBResult.size(); + assert(duckDBResult.data[i].GetVectorType() == duckdb::VectorType::FLAT_VECTOR); + conversionFuncs[i](duckDBResult.data[i], *result.getValueVector(i), + result.state->selVector->selectedSize); + } +} + +common::offset_t DuckDBScanFunction::tableFunc(function::TableFuncInput& input, + function::TableFuncOutput& output) { + auto duckdbScanSharedState = reinterpret_cast(input.sharedState); + auto duckdbScanBindData = reinterpret_cast(input.bindData); + std::unique_ptr result; + try { + result = duckdbScanSharedState->queryResult->Fetch(); + } catch (std::exception& e) { + return 0; + } + if (result == nullptr) { + return 0; + } + convertDuckDBResultToVector(*result, output.dataChunk, duckdbScanBindData->conversionFunctions); + return output.dataChunk.state->selVector->selectedSize; +} + +std::unique_ptr DuckDBScanFunction::bindFunc( + DuckDBScanBindData bindData, main::ClientContext* /*clientContext*/, + function::TableFuncBindInput* /*input*/) { + return bindData.copy(); +} + +TableFunction getScanFunction(DuckDBScanBindData bindData) { + return TableFunction(DuckDBScanFunction::DUCKDB_SCAN_FUNC_NAME, DuckDBScanFunction::tableFunc, + std::bind(DuckDBScanFunction::bindFunc, std::move(bindData), std::placeholders::_1, + std::placeholders::_2), + DuckDBScanFunction::initSharedState, DuckDBScanFunction::initLocalState, + std::vector{}); +} + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/duckdb_scanner_extension.cpp b/extension/duckdb_scanner/src/duckdb_scanner_extension.cpp new file mode 100644 index 00000000000..a215592aae6 --- /dev/null +++ b/extension/duckdb_scanner/src/duckdb_scanner_extension.cpp @@ -0,0 +1,28 @@ +#include "duckdb_scanner_extension.h" + +#include "duckdb_scan.h" +#include "duckdb_storage.h" + +namespace kuzu { +namespace duckdb_scanner { + +void DuckDBScannerExtension::load(main::ClientContext* context) { + auto db = context->getDatabase(); + db->registerStorageExtension("duckdb", std::make_unique()); +} + +} // namespace duckdb_scanner +} // namespace kuzu + +extern "C" { +// Because we link against the static library on windows, we implicitly inherit KUZU_STATIC_DEFINE, +// which cancels out any exporting, so we can't use KUZU_API. +#if defined(_WIN32) +#define INIT_EXPORT __declspec(dllexport) +#else +#define INIT_EXPORT __attribute__((visibility("default"))) +#endif +INIT_EXPORT void init(kuzu::main::ClientContext* context) { + kuzu::duckdb_scanner::DuckDBScannerExtension::load(context); +} +} diff --git a/extension/duckdb_scanner/src/duckdb_storage.cpp b/extension/duckdb_scanner/src/duckdb_storage.cpp new file mode 100644 index 00000000000..78dc791bc3c --- /dev/null +++ b/extension/duckdb_scanner/src/duckdb_storage.cpp @@ -0,0 +1,33 @@ +#include "duckdb_storage.h" + +#include "catalog/catalog_entry/table_catalog_entry.h" +#include "common/exception/binder.h" +#include "duckdb_catalog.h" + +namespace kuzu { +namespace duckdb_scanner { + +std::unique_ptr attachDuckDB(std::string dbName, std::string dbPath, + main::ClientContext* clientContext) { + if (dbName == "") { + if (dbPath.find('.') != std::string::npos) { + auto fileNamePos = dbPath.find_last_of('/') + 1; + dbName = dbPath.substr(fileNamePos, dbPath.find_last_of('.') - fileNamePos); + } else { + dbName = dbPath; + } + } + auto duckdbCatalog = std::make_unique(); + duckdbCatalog->init(dbPath, dbName, clientContext); + return std::make_unique(dbName, std::move(duckdbCatalog)); +} + +DuckDBStorageExtension::DuckDBStorageExtension() : StorageExtension{attachDuckDB} {} + +bool DuckDBStorageExtension::canHandleDB(std::string dbType) const { + common::StringUtils::toUpper(dbType); + return dbType == "DUCKDB"; +} + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/duckdb_table_catalog_entry.cpp b/extension/duckdb_scanner/src/duckdb_table_catalog_entry.cpp new file mode 100644 index 00000000000..fcc1c5c522a --- /dev/null +++ b/extension/duckdb_scanner/src/duckdb_table_catalog_entry.cpp @@ -0,0 +1,20 @@ +#include "duckdb_table_catalog_entry.h" + +namespace kuzu { +namespace catalog { + +DuckDBTableCatalogEntry::DuckDBTableCatalogEntry(std::string name, common::table_id_t tableID, + function::TableFunction scanFunction) + : TableCatalogEntry{CatalogEntryType::FOREIGN_TABLE_ENTRY, std::move(name), tableID}, + scanFunction{std::move(scanFunction)} {} + +common::TableType DuckDBTableCatalogEntry::getTableType() const { + return common::TableType::FOREIGN; +} + +std::unique_ptr DuckDBTableCatalogEntry::copy() const { + return std::make_unique(*this); +} + +} // namespace catalog +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/duckdb_type_converter.cpp b/extension/duckdb_scanner/src/duckdb_type_converter.cpp new file mode 100644 index 00000000000..f7212080145 --- /dev/null +++ b/extension/duckdb_scanner/src/duckdb_type_converter.cpp @@ -0,0 +1,134 @@ +#include "duckdb_type_converter.h" + +#include "common/exception/binder.h" +#include "common/string_utils.h" + +namespace kuzu { +namespace duckdb_scanner { + +using namespace kuzu::common; + +common::LogicalType DuckDBTypeConverter::convertDuckDBType(std::string typeStr) { + typeStr = common::StringUtils::ltrim(typeStr); + typeStr = common::StringUtils::rtrim(typeStr); + if (typeStr == "BIGINT" || typeStr == "INT8" || typeStr == "LONG") { + return LogicalType{LogicalTypeID::INT64}; + } else if (typeStr == "BLOB" || typeStr == "BYTEA" || typeStr == "BINARY" || + typeStr == "VARBINARY") { + return LogicalType{LogicalTypeID::BLOB}; + } else if (typeStr == "BOOLEAN" || typeStr == "BOOL" || typeStr == "LOGICAL") { + return LogicalType{LogicalTypeID::BOOL}; + } else if (typeStr == "DATE") { + return LogicalType{LogicalTypeID::DATE}; + } else if (typeStr == "DOUBLE" || typeStr == "FLOAT8") { + return LogicalType{LogicalTypeID::DOUBLE}; + } else if (typeStr == "HUGEINT") { + return LogicalType{LogicalTypeID::INT128}; + } else if (typeStr == "INTEGER" || typeStr == "INT4" || typeStr == "INT" || + typeStr == "SIGNED") { + return LogicalType{LogicalTypeID::INT32}; + } else if (typeStr == "INTERVAL") { + return LogicalType{LogicalTypeID::INTERVAL}; + } else if (typeStr == "REAL" || typeStr == "FLOAT" || typeStr == "FLOAT4") { + return LogicalType{LogicalTypeID::FLOAT}; + } else if (typeStr == "SMALLINT" || typeStr == "INT2" || typeStr == "SHORT") { + return LogicalType{LogicalTypeID::INT16}; + } else if (typeStr == "TIMESTAMP" || typeStr == "DATETIME") { + return LogicalType{LogicalTypeID::TIMESTAMP}; + } else if (typeStr == "TIMESTAMP_NS") { + return LogicalType{LogicalTypeID::TIMESTAMP_NS}; + } else if (typeStr == "TIMESTAMP_MS") { + return LogicalType{LogicalTypeID::TIMESTAMP_MS}; + } else if (typeStr == "TIMESTAMP_S") { + return LogicalType{LogicalTypeID::TIMESTAMP_SEC}; + } else if (typeStr == "TIMESTAMP WITH TIME ZONE" || typeStr == "TIMESTAMPTZ") { + return LogicalType{LogicalTypeID::TIMESTAMP_TZ}; + } else if (typeStr == "TINYINT" || typeStr == "INT1") { + return LogicalType{LogicalTypeID::INT8}; + } else if (typeStr == "UBIGINT") { + return LogicalType{LogicalTypeID::UINT64}; + } else if (typeStr == "UINTEGER") { + return LogicalType{LogicalTypeID::UINT32}; + } else if (typeStr == "USMALLINT") { + return LogicalType{LogicalTypeID::UINT16}; + } else if (typeStr == "UTINYINT") { + return LogicalType{LogicalTypeID::UINT8}; + } else if (typeStr == "UUID") { + return LogicalType{LogicalTypeID::UUID}; + } else if (typeStr == "VARCHAR" || typeStr == "CHAR" || typeStr == "BPCHAR" || + typeStr == "TEXT" || typeStr == "STRING") { + return LogicalType{LogicalTypeID::STRING}; + } else if (typeStr.ends_with("[]")) { + auto innerType = convertDuckDBType(typeStr.substr(0, typeStr.size() - 2)); + return *LogicalType::LIST(innerType.copy()); + } else if (typeStr.starts_with("STRUCT")) { + return *LogicalType::STRUCT(parseStructTypeInfo(typeStr)); + } else if (typeStr.starts_with("UNION")) { + auto unionFields = parseStructTypeInfo(typeStr); + auto unionTagField = StructField(UnionType::TAG_FIELD_NAME, + std::make_unique(UnionType::TAG_FIELD_TYPE)); + unionFields.insert(unionFields.begin(), std::move(unionTagField)); + return *LogicalType::UNION(std::move(unionFields)); + } else if (typeStr.starts_with("MAP")) { + auto leftBracketPos = typeStr.find('('); + auto rightBracketPos = typeStr.find_last_of(')'); + auto mapTypeStr = typeStr.substr(leftBracketPos + 1, rightBracketPos - leftBracketPos - 1); + auto keyValueTypes = StringUtils::splitComma(mapTypeStr); + return *LogicalType::MAP(convertDuckDBType(keyValueTypes[0]), + convertDuckDBType(keyValueTypes[1])); + } + throw BinderException{stringFormat("Unsupported duckdb type: {}.", typeStr)}; +} + +std::vector DuckDBTypeConverter::parseStructFields(const std::string& structTypeStr) { + std::vector structFieldsStr; + auto startPos = 0u; + auto curPos = 0u; + auto numOpenBrackets = 0u; + while (curPos < structTypeStr.length()) { + switch (structTypeStr[curPos]) { + case '(': { + numOpenBrackets++; + } break; + case ')': { + numOpenBrackets--; + } break; + case ',': { + if (numOpenBrackets == 0) { + structFieldsStr.push_back( + StringUtils::ltrim(structTypeStr.substr(startPos, curPos - startPos))); + startPos = curPos + 1; + } + } break; + default: { + // Normal character, continue. + } + } + curPos++; + } + structFieldsStr.push_back( + StringUtils::ltrim(structTypeStr.substr(startPos, curPos - startPos))); + return structFieldsStr; +} + +std::vector DuckDBTypeConverter::parseStructTypeInfo( + const std::string& structTypeStr) { + auto leftBracketPos = structTypeStr.find('('); + auto rightBracketPos = structTypeStr.find_last_of(')'); + // Remove the leading and trailing brackets. + auto structFieldsStr = + structTypeStr.substr(leftBracketPos + 1, rightBracketPos - leftBracketPos - 1); + std::vector structFields; + auto structFieldStrs = parseStructFields(structFieldsStr); + for (auto& structFieldStr : structFieldStrs) { + auto pos = structFieldStr.find(' '); + auto fieldName = structFieldStr.substr(0, pos); + auto fieldTypeString = structFieldStr.substr(pos + 1); + structFields.emplace_back(fieldName, + std::make_unique(DuckDBTypeConverter::convertDuckDBType(fieldTypeString))); + } + return structFields; +} + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/include/duckdb_catalog.h b/extension/duckdb_scanner/src/include/duckdb_catalog.h new file mode 100644 index 00000000000..2ecb068003c --- /dev/null +++ b/extension/duckdb_scanner/src/include/duckdb_catalog.h @@ -0,0 +1,55 @@ +#pragma once + +#include "binder/ddl/bound_create_table_info.h" +#include "catalog/catalog_content.h" +#include "duckdb_scan.h" + +namespace kuzu { +namespace duckdb_scanner { + +struct BoundExtraCreateDuckDBTableInfo : public binder::BoundExtraCreateTableInfo { + std::string dbPath; + std::string catalogName; + std::string schemaName; + + BoundExtraCreateDuckDBTableInfo(std::string dbPath, std::string catalogName, + std::string schemaName, std::vector propertyInfos) + : BoundExtraCreateTableInfo{std::move(propertyInfos)}, dbPath{std::move(dbPath)}, + catalogName{std::move(catalogName)}, schemaName{std::move(schemaName)} {} + BoundExtraCreateDuckDBTableInfo(const BoundExtraCreateDuckDBTableInfo& other) + : BoundExtraCreateTableInfo{copyVector(other.propertyInfos)}, dbPath{other.dbPath}, + catalogName{other.catalogName}, schemaName{other.schemaName} {} + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } +}; + +class DuckDBCatalogContent : public catalog::CatalogContent { +public: + DuckDBCatalogContent() : catalog::CatalogContent{nullptr /* vfs */} {} + + virtual void init(const std::string& dbPath, const std::string& catalogName, + main::ClientContext* context); + +protected: + bool bindPropertyInfos(duckdb::Connection& con, const std::string& tableName, + const std::string& catalogName, std::vector& propertyInfos); + +private: + virtual std::unique_ptr bindCreateTableInfo( + duckdb::Connection& con, const std::string& tableName, const std::string& dbPath, + const std::string& catalogName); + + virtual std::string getDefaultSchemaName() const; + + virtual std::pair getConnection( + const std::string& dbPath) const; + +private: + void createForeignTable(duckdb::Connection& con, const std::string& tableName, + const std::string& dbPath, const std::string& catalogName); +}; + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/include/duckdb_scan.h b/extension/duckdb_scanner/src/include/duckdb_scan.h new file mode 100644 index 00000000000..28c2c600247 --- /dev/null +++ b/extension/duckdb_scanner/src/include/duckdb_scan.h @@ -0,0 +1,46 @@ +#pragma once + +#include "common/vector/value_vector.h" +#include "function/scalar_function.h" +#include "function/table/bind_data.h" +#include "function/table_functions.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +// Supress warnings from duckdb.hpp +#undef ARROW_FLAG_DICTIONARY_ORDERED +#include "common/types/types.h" +#include "duckdb.hpp" +#pragma GCC diagnostic pop + +namespace kuzu { +namespace duckdb_scanner { + +using duckdb_conversion_func_t = std::function; +using init_duckdb_conn_t = std::function()>; + +struct DuckDBScanBindData : public function::TableFuncBindData { + explicit DuckDBScanBindData(std::string query, std::vector columnTypes, + std::vector columnNames, init_duckdb_conn_t initDuckDBConn); + + std::unique_ptr copy() const override; + + std::string query; + std::vector conversionFunctions; + init_duckdb_conn_t initDuckDBConn; +}; + +struct DuckDBScanSharedState : public function::TableFuncSharedState { + explicit DuckDBScanSharedState(std::unique_ptr queryResult); + + std::unique_ptr queryResult; +}; + +void getDuckDBVectorConversionFunc(common::PhysicalTypeID physicalTypeID, + duckdb_conversion_func_t& conversion_func); + +function::TableFunction getScanFunction(DuckDBScanBindData bindData); + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/include/duckdb_scanner_extension.h b/extension/duckdb_scanner/src/include/duckdb_scanner_extension.h new file mode 100644 index 00000000000..2911768f0cc --- /dev/null +++ b/extension/duckdb_scanner/src/include/duckdb_scanner_extension.h @@ -0,0 +1,15 @@ +#pragma once + +#include "extension/extension.h" +#include "main/database.h" + +namespace kuzu { +namespace duckdb_scanner { + +class DuckDBScannerExtension final : public extension::Extension { +public: + static void load(main::ClientContext* context); +}; + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/include/duckdb_storage.h b/extension/duckdb_scanner/src/include/duckdb_storage.h new file mode 100644 index 00000000000..aed030ba93f --- /dev/null +++ b/extension/duckdb_scanner/src/include/duckdb_storage.h @@ -0,0 +1,17 @@ +#pragma once + +#include "common/string_utils.h" +#include "storage/storage_extension.h" + +namespace kuzu { +namespace duckdb_scanner { + +class DuckDBStorageExtension final : public storage::StorageExtension { +public: + DuckDBStorageExtension(); + + bool canHandleDB(std::string dbType) const override; +}; + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/include/duckdb_table_catalog_entry.h b/extension/duckdb_scanner/src/include/duckdb_table_catalog_entry.h new file mode 100644 index 00000000000..8ba4b5bdb92 --- /dev/null +++ b/extension/duckdb_scanner/src/include/duckdb_table_catalog_entry.h @@ -0,0 +1,33 @@ +#pragma once + +#include "catalog/catalog_entry/table_catalog_entry.h" +#include "function/table_functions.h" + +namespace kuzu { +namespace catalog { + +class DuckDBTableCatalogEntry final : public TableCatalogEntry { +public: + //===--------------------------------------------------------------------===// + // constructors + //===--------------------------------------------------------------------===// + DuckDBTableCatalogEntry(std::string name, common::table_id_t tableID, + function::TableFunction scanFunction); + + //===--------------------------------------------------------------------===// + // getter & setter + //===--------------------------------------------------------------------===// + common::TableType getTableType() const override; + function::TableFunction getScanFunction() override { return scanFunction; } + + //===--------------------------------------------------------------------===// + // serialization & deserialization + //===--------------------------------------------------------------------===// + std::unique_ptr copy() const override; + +private: + function::TableFunction scanFunction; +}; + +} // namespace catalog +} // namespace kuzu diff --git a/extension/duckdb_scanner/src/include/duckdb_type_converter.h b/extension/duckdb_scanner/src/include/duckdb_type_converter.h new file mode 100644 index 00000000000..5c4de9e9925 --- /dev/null +++ b/extension/duckdb_scanner/src/include/duckdb_type_converter.h @@ -0,0 +1,18 @@ +#pragma once + +#include "common/types/types.h" + +namespace kuzu { +namespace duckdb_scanner { + +class DuckDBTypeConverter { +public: + static common::LogicalType convertDuckDBType(std::string typeStr); + +private: + static std::vector parseStructFields(const std::string& structTypeStr); + static std::vector parseStructTypeInfo(const std::string& structTypeStr); +}; + +} // namespace duckdb_scanner +} // namespace kuzu diff --git a/extension/duckdb_scanner/test/duckdb_database/other.db b/extension/duckdb_scanner/test/duckdb_database/other.db new file mode 100644 index 00000000000..7cbc6ecccf9 Binary files /dev/null and b/extension/duckdb_scanner/test/duckdb_database/other.db differ diff --git a/extension/duckdb_scanner/test/duckdb_database/tinysnb.db b/extension/duckdb_scanner/test/duckdb_database/tinysnb.db new file mode 100644 index 00000000000..5a14eee06ad Binary files /dev/null and b/extension/duckdb_scanner/test/duckdb_database/tinysnb.db differ diff --git a/extension/duckdb_scanner/test/test_files/duckdb_scanner.test b/extension/duckdb_scanner/test/test_files/duckdb_scanner.test new file mode 100644 index 00000000000..aa5a891cd63 --- /dev/null +++ b/extension/duckdb_scanner/test/test_files/duckdb_scanner.test @@ -0,0 +1,64 @@ +-GROUP DuckDBScanner +-DATASET CSV empty + +-- + +-CASE ScanDuckDBTable +-STATEMENT load extension "${KUZU_ROOT_DIRECTORY}/extension/duckdb_scanner/build/libduckdb_scanner.kuzu_extension" +---- ok +-STATEMENT ATTACH '${KUZU_ROOT_DIRECTORY}/extension/duckdb_scanner/test/duckdb_database/tinysnb.db' as tinysnb (dbtype 'duckdb'); +---- ok +-STATEMENT LOAD FROM tinysnb_person RETURN *; +---- 8 +0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]]|1.731000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 +10|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|2|False|True|83|4.900000|1990-11-27|2023-02-21 13:25:30|3 years 2 days 13:02:00|[10,11,12,3,4,5,6,7]|[Ad,De,Hi,Kye,Orlan]|[[7],[10],[6,7]]|1.323000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18 +2|Bob|2|True|False|30|5.100000|1900-01-01|2008-11-03 15:25:30.000526|10 years 5 months 13:00:00.000024|[12,8]|[Bobby]|[[8,9],[9,10]]|0.990000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12 +3|Carol|1|False|True|45|5.000000|1940-06-22|1911-08-20 02:32:21|48:24:11|[4,5]|[Carmen,Fred]|[[8,10]]|1.000000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13 +5|Dan|2|False|True|20|4.800000|1950-07-23|2031-11-30 12:25:30|10 years 5 months 13:00:00.000024|[1,9]|[Wolfeschlegelstein,Daniel]|[[7,4],[8,8],[9]]|1.300000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14 +7|Elizabeth|1|False|True|20|4.700000|1980-10-26|1976-12-23 11:21:42|48:24:11|[2]|[Ein]|[[6],[7],[8]]|1.463000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15 +8|Farooq|2|True|False|25|4.500000|1980-10-26|1972-07-31 13:22:30.678559|00:18:00.024|[3,4,5,6,7]|[Fesdwe]|[[8]]|1.510000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16 +9|Greg|2|False|False|40|4.900000|1980-10-26|1976-12-23 11:21:42|10 years 5 months 13:00:00.000024|[1]|[Grad]|[[10]]|1.600000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17 +-STATEMENT LOAD FROM tinysnb_organisation RETURN *; +---- 3 +1|ABFsUni|325|3.700000|-2|10 years 5 months 13 hours 24 us|3 years 5 days|1.000000|{revenue: 138, "location": ['toronto','montr,eal'], stock: {price: [96,56], volume: 1000}}|3.12 +4|CsWork|934|4.100000|-100|2 years 4 days 10 hours|26 years 52 days 48:00:00|0.780000|{revenue: 152, "location": ["vanco,uver north area"], stock: {price: [15,78,671], volume: 432}}|abcd +6|DEsWork|824|4.100000|7|2 years 4 hours 22 us 34 minutes|82:00:00.1|0.520000|{revenue: 558, "location": ['very long city name','new york'], stock: {price: [22], volume: 99}}|2023-12-15 +-STATEMENT LOAD FROM tinysnb_movies RETURN *; +---- 3 +Roma|298|the movie is very interesting and funny|{rating: 1223.000000, stars: 100, "views": 10003, "release": 2011-02-11 16:44:22, release_ns: 2011-02-11 16:44:22.123456, release_ms: 2011-02-11 16:44:22.123, release_sec: 2011-02-11 16:44:22, release_tz: 2011-02-11 16:44:22.123456+00, film: 2013-02-22, u8: 1, u16: 15, u32: 200, u64: 4, hugedata: -15}|pure ascii characters|{} +Sóló cón tu párejâ|126| this is a very very good movie|{rating: 5.300000, stars: 2, "views": 152, "release": 2011-08-20 11:25:30, release_ns: 2011-08-20 11:25:30.123456, release_ms: 2011-08-20 11:25:30.123, release_sec: 2011-08-20 11:25:30, release_tz: 2011-08-20 11:25:30.123456+00, film: 2012-05-11, u8: 220, u16: 20, u32: 1, u64: 180, hugedata: 1844674407370955161811111111}|\xAA\xABinteresting\x0B|{audience1=52, audience53=42} +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie|2544| the movie is very very good|{rating: 7.000000, stars: 10, "views": 982, "release": 2018-11-13 13:33:11, release_ns: 2018-11-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2018-11-13 13:33:11, release_tz: 2018-11-13 13:33:11.123456+00, film: 2014-09-12, u8: 12, u16: 120, u32: 55, u64: 1, hugedata: -1844674407370955161511}|\xAB\xCD|{audience1=33} +-STATEMENT LOAD FROM tinysnb_tableOfTypes RETURN count(*); +---- 1 +49999 +-STATEMENT LOAD FROM tinysnb_tableOfTypes WHERE id = 49992 or id = 28532 RETURN *; +---- 2 +28532|74|72.472423|True|1977-08-16|TKn|[94,92]|[AUSrJTUWVOESDor,ODOS6RfqMhsFO9aFUa,ziauQj]|[[123,55,181],[32]]|{ID: 666, "name": DiqSQ5u5UhS8aZi} +49992|50|31.582059|False|2056-05-02||[62,24,94]|[LpQO8OT3x45a]|[[268,281,166],[144,16,126,208,298],[22,287]]|{ID: 936, "name": sGPSafxMAhKiP} +-STATEMENT LOAD FROM tinysnb_person1 RETURN *; +---- error +Catalog exception: Table: person1 does not exist. +-STATEMENT DETACH tinysnb; +---- ok +-STATEMENT LOAD FROM tinysnb_person RETURN *; +---- error +Binder exception: No database named tinysnb has been attached. +-LOG AttachMultipleDuckDB +-STATEMENT ATTACH '${KUZU_ROOT_DIRECTORY}/extension/duckdb_scanner/test/duckdb_database/tinysnb.db' (dbtype 'duckdb'); +---- ok +-STATEMENT ATTACH '${KUZU_ROOT_DIRECTORY}/extension/duckdb_scanner/test/duckdb_database/other.db' as other (dbtype 'duckdb'); +---- ok +-STATEMENT LOAD FROM other_person RETURN *; +---- 4 +1 +2 +3 +5 +-STATEMENT LOAD FROM tinysnb_person RETURN count(*); +---- 1 +8 + +-CASE InvalidDuckDBDatabase +-STATEMENT LOAD FROM tinysnb1_person RETURN *; +---- error +Binder exception: No database named tinysnb1 has been attached. diff --git a/extension/httpfs/CMakeLists.txt b/extension/httpfs/CMakeLists.txt index 813386e6a70..8c6b0f1d4f5 100644 --- a/extension/httpfs/CMakeLists.txt +++ b/extension/httpfs/CMakeLists.txt @@ -31,6 +31,7 @@ set_target_properties(httpfs PROPERTIES PREFIX "lib" SUFFIX ".kuzu_extension" ) + set_target_properties(httpfs PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" diff --git a/extension/httpfs/src/crypto.cpp b/extension/httpfs/src/crypto.cpp index 4d345170e80..637f79754ec 100644 --- a/extension/httpfs/src/crypto.cpp +++ b/extension/httpfs/src/crypto.cpp @@ -26,10 +26,10 @@ void hmac256(const std::string& message, const char* secret, size_t secretLen, h } if (mbedtls_md_setup(&hmacCtx, mdType, 1) || - mbedtls_md_hmac_starts( - &hmacCtx, reinterpret_cast(secret), secretLen) || - mbedtls_md_hmac_update( - &hmacCtx, reinterpret_cast(message.c_str()), message.length()) || + mbedtls_md_hmac_starts(&hmacCtx, reinterpret_cast(secret), + secretLen) || + mbedtls_md_hmac_update(&hmacCtx, reinterpret_cast(message.c_str()), + message.length()) || mbedtls_md_hmac_finish(&hmacCtx, reinterpret_cast(out))) { throw common::RuntimeException("HMAC256 Error"); } diff --git a/extension/httpfs/src/httpfs.cpp b/extension/httpfs/src/httpfs.cpp index 3da57dedf63..e0e1d9ac000 100644 --- a/extension/httpfs/src/httpfs.cpp +++ b/extension/httpfs/src/httpfs.cpp @@ -16,8 +16,8 @@ HTTPResponse::HTTPResponse(httplib::Response& res, const std::string& url) } HTTPFileInfo::HTTPFileInfo(std::string path, FileSystem* fileSystem, int flags) - : FileInfo{std::move(path), fileSystem}, flags{flags}, length{0}, - availableBuffer{0}, bufferIdx{0}, fileOffset{0}, bufferStartPos{0}, bufferEndPos{0} {} + : FileInfo{std::move(path), fileSystem}, flags{flags}, length{0}, availableBuffer{0}, + bufferIdx{0}, fileOffset{0}, bufferStartPos{0}, bufferEndPos{0} {} void HTTPFileInfo::initialize() { initializeClient(); @@ -40,8 +40,8 @@ void HTTPFileInfo::initialize() { hfs->getRangeRequest(this, this->path, {}, 0, nullptr /* buffer */, 2); if (rangeRequest->code != 206) { // LCOV_EXCL_START - throw IOException(stringFormat( - "Unable to connect to URL \"{}\": {} ({})", this->path, res->code, res->error)); + throw IOException(stringFormat("Unable to connect to URL \"{}\": {} ({})", + this->path, res->code, res->error)); // LCOV_EXCL_STOP } auto rangeFound = rangeRequest->headers["Content-Range"].find("/"); @@ -92,13 +92,13 @@ void HTTPFileInfo::initialize() { } } catch (std::invalid_argument& e) { // LCOV_EXCL_START - throw IOException(stringFormat( - "Invalid Content-Length header received: {}", res->headers["Content-Length"])); + throw IOException(stringFormat("Invalid Content-Length header received: {}", + res->headers["Content-Length"])); // LCOV_EXCL_STOP } catch (std::out_of_range& e) { // LCOV_EXCL_START - throw IOException(stringFormat( - "Invalid Content-Length header received: {}", res->headers["Content-Length"])); + throw IOException(stringFormat("Invalid Content-Length header received: {}", + res->headers["Content-Length"])); // LCOV_EXCL_STOP } } @@ -116,8 +116,8 @@ std::unique_ptr HTTPFileSystem::openFile(const std::string& pa return std::move(httpFileInfo); } -std::vector HTTPFileSystem::glob( - main::ClientContext* /*context*/, const std::string& path) const { +std::vector HTTPFileSystem::glob(main::ClientContext* /*context*/, + const std::string& path) const { // Glob is not supported on HTTPFS, simply return the path itself. return {path}; } @@ -126,8 +126,8 @@ bool HTTPFileSystem::canHandleFile(const std::string& path) const { return path.rfind("https://", 0) == 0 || path.rfind("http://", 0) == 0; } -void HTTPFileSystem::readFromFile( - common::FileInfo* fileInfo, void* buffer, uint64_t numBytes, uint64_t position) const { +void HTTPFileSystem::readFromFile(common::FileInfo* fileInfo, void* buffer, uint64_t numBytes, + uint64_t position) const { auto httpFileInfo = ku_dynamic_cast(fileInfo); auto numBytesToRead = numBytes; auto bufferOffset = 0; @@ -158,8 +158,8 @@ void HTTPFileSystem::readFromFile( } if (numBytesToRead > 0 && httpFileInfo->availableBuffer == 0) { - auto newBufferAvailableSize = std::min( - httpFileInfo->READ_BUFFER_LEN, httpFileInfo->length - httpFileInfo->fileOffset); + auto newBufferAvailableSize = std::min(httpFileInfo->READ_BUFFER_LEN, + httpFileInfo->length - httpFileInfo->fileOffset); // Bypass buffer if we read more than buffer size. if (numBytesToRead > newBufferAvailableSize) { @@ -261,7 +261,9 @@ std::unique_ptr HTTPFileSystem::runRequestWithRetry( status = res->status; response = res.value(); } - } catch (IOException& e) { exception = std::current_exception(); } + } catch (IOException& e) { + exception = std::current_exception(); + } if (err == httplib::Error::Success) { switch (status) { @@ -292,8 +294,8 @@ std::unique_ptr HTTPFileSystem::runRequestWithRetry( std::rethrow_exception(exception); } else if (err == httplib::Error::Success) { // LCOV_EXCL_START - throw IOException(stringFormat( - "Request returned HTTP {} for HTTP {} to '{}'", status, method, url)); + throw IOException(stringFormat("Request returned HTTP {} for HTTP {} to '{}'", + status, method, url)); // LCOV_EXCL_STOP } else { // LCOV_EXCL_START @@ -305,8 +307,8 @@ std::unique_ptr HTTPFileSystem::runRequestWithRetry( } } -std::unique_ptr HTTPFileSystem::headRequest( - FileInfo* fileInfo, const std::string& url, HeaderMap headerMap) const { +std::unique_ptr HTTPFileSystem::headRequest(FileInfo* fileInfo, + const std::string& url, HeaderMap headerMap) const { auto httpFileInfo = ku_dynamic_cast(fileInfo); auto parsedURL = parseUrl(url); auto host = parsedURL.first; @@ -330,8 +332,8 @@ std::unique_ptr HTTPFileSystem::getRangeRequest(FileInfo* fileInfo auto hostPath = parsedURL.second; auto headers = getHTTPHeaders(headerMap); - headers->insert(std::make_pair( - "Range", stringFormat("bytes={}-{}", fileOffset, fileOffset + bufferLen - 1))); + headers->insert(std::make_pair("Range", + stringFormat("bytes={}-{}", fileOffset, fileOffset + bufferLen - 1))); uint64_t bufferOffset = 0; diff --git a/extension/httpfs/src/httpfs_extension.cpp b/extension/httpfs/src/httpfs_extension.cpp index 61b358d777f..1814a55a815 100644 --- a/extension/httpfs/src/httpfs_extension.cpp +++ b/extension/httpfs/src/httpfs_extension.cpp @@ -12,18 +12,18 @@ void HttpfsExtension::load(main::ClientContext* context) { db->registerFileSystem(std::make_unique()); db->registerFileSystem(std::make_unique()); db->addExtensionOption("s3_access_key_id", common::LogicalTypeID::STRING, common::Value{""}); - db->addExtensionOption( - "s3_secret_access_key", common::LogicalTypeID::STRING, common::Value{""}); - db->addExtensionOption( - "s3_endpoint", common::LogicalTypeID::STRING, common::Value{"s3.amazonaws.com"}); + db->addExtensionOption("s3_secret_access_key", common::LogicalTypeID::STRING, + common::Value{""}); + db->addExtensionOption("s3_endpoint", common::LogicalTypeID::STRING, + common::Value{"s3.amazonaws.com"}); db->addExtensionOption("s3_url_style", common::LogicalTypeID::STRING, common::Value{"vhost"}); db->addExtensionOption("s3_region", common::LogicalTypeID::STRING, common::Value{"us-east-1"}); db->addExtensionOption("s3_uploader_max_num_parts_per_file", common::LogicalTypeID::INT64, common::Value{(int64_t)800000000000}); - db->addExtensionOption( - "s3_uploader_max_filesize", common::LogicalTypeID::INT64, common::Value{(int64_t)10000}); - db->addExtensionOption( - "s3_uploader_threads_limit", common::LogicalTypeID::INT64, common::Value{(int64_t)50}); + db->addExtensionOption("s3_uploader_max_filesize", common::LogicalTypeID::INT64, + common::Value{(int64_t)10000}); + db->addExtensionOption("s3_uploader_threads_limit", common::LogicalTypeID::INT64, + common::Value{(int64_t)50}); AWSEnvironmentCredentialsProvider::setOptionValue(context); } diff --git a/extension/httpfs/src/include/httpfs.h b/extension/httpfs/src/include/httpfs.h index 5aaa6fc3507..47d377c8db3 100644 --- a/extension/httpfs/src/include/httpfs.h +++ b/extension/httpfs/src/include/httpfs.h @@ -63,8 +63,8 @@ class HTTPFileSystem : public common::FileSystem { main::ClientContext* context = nullptr, common::FileLockType lock_type = common::FileLockType::NO_LOCK) override; - std::vector glob( - main::ClientContext* context, const std::string& path) const override; + std::vector glob(main::ClientContext* context, + const std::string& path) const override; bool canHandleFile(const std::string& path) const override; @@ -88,8 +88,8 @@ class HTTPFileSystem : public common::FileSystem { const std::function& request, const std::string& url, std::string method, const std::function& retry = {}); - virtual std::unique_ptr headRequest( - common::FileInfo* fileInfo, const std::string& url, HeaderMap headerMap) const; + virtual std::unique_ptr headRequest(common::FileInfo* fileInfo, + const std::string& url, HeaderMap headerMap) const; virtual std::unique_ptr getRangeRequest(common::FileInfo* fileInfo, const std::string& url, HeaderMap headerMap, uint64_t fileOffset, char* buffer, diff --git a/extension/httpfs/src/include/s3fs.h b/extension/httpfs/src/include/s3fs.h index b7ee438acf9..925a14db232 100644 --- a/extension/httpfs/src/include/s3fs.h +++ b/extension/httpfs/src/include/s3fs.h @@ -112,8 +112,8 @@ class S3FileSystem final : public HTTPFileSystem { main::ClientContext* context = nullptr, common::FileLockType lock_type = common::FileLockType::NO_LOCK) override; - std::vector glob( - main::ClientContext* context, const std::string& path) const override; + std::vector glob(main::ClientContext* context, + const std::string& path) const override; bool canHandleFile(const std::string& path) const override; @@ -128,8 +128,8 @@ class S3FileSystem final : public HTTPFileSystem { void writeFile(common::FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, uint64_t offset) const override; - std::shared_ptr allocateWriteBuffer( - uint16_t writeBufferIdx, uint64_t partSize, uint16_t maxThreads); + std::shared_ptr allocateWriteBuffer(uint16_t writeBufferIdx, uint64_t partSize, + uint16_t maxThreads); void flushAllBuffers(S3FileInfo* fileInfo); @@ -140,8 +140,8 @@ class S3FileSystem final : public HTTPFileSystem { std::string payloadHash = "", std::string contentType = ""); protected: - std::unique_ptr headRequest( - common::FileInfo* fileInfo, const std::string& url, HeaderMap headerMap) const override; + std::unique_ptr headRequest(common::FileInfo* fileInfo, const std::string& url, + HeaderMap headerMap) const override; std::unique_ptr getRangeRequest(common::FileInfo* fileInfo, const std::string& url, HeaderMap headerMap, uint64_t fileOffset, char* buffer, @@ -179,8 +179,8 @@ struct AWSListObjectV2 { static constexpr char OPEN_PREFIX_TAG[] = ""; static constexpr char CLOSE_PREFIX_TAG[] = ""; - static std::string request( - std::string& path, S3AuthParams& authParams, std::string& continuationToken); + static std::string request(std::string& path, S3AuthParams& authParams, + std::string& continuationToken); static void parseKey(std::string& awsResponse, std::vector& result); static std::vector parseCommonPrefix(std::string& awsResponse); static std::string parseContinuationToken(std::string& awsResponse); diff --git a/extension/httpfs/src/s3fs.cpp b/extension/httpfs/src/s3fs.cpp index 8b70e88ab29..fc3e0578bf7 100644 --- a/extension/httpfs/src/s3fs.cpp +++ b/extension/httpfs/src/s3fs.cpp @@ -130,7 +130,7 @@ std::unique_ptr S3FileSystem::openFile(const std::string& path bool likes(const char* string, uint64_t slen, const char* pattern, uint64_t plen) { uint64_t sidx = 0; uint64_t pidx = 0; -main_loop : { +main_loop: { // main matching loop while (sidx < slen && pidx < plen) { char s = string[sidx]; @@ -188,7 +188,7 @@ main_loop : { // we are finished only if we have consumed the full pattern return pidx == plen && sidx == slen; } -parse_bracket : { +parse_bracket: { // inside a bracket if (pidx == plen) { return false; @@ -287,8 +287,8 @@ static bool match(std::vector::const_iterator key, return key == key_end && pattern == pattern_end; } -std::vector S3FileSystem::glob( - main::ClientContext* context, const std::string& path) const { +std::vector S3FileSystem::glob(main::ClientContext* context, + const std::string& path) const { auto s3AuthParams = getS3AuthParams(context); auto parsedS3URL = parseS3URL(path, s3AuthParams); auto parsedGlobURL = parsedS3URL.trimmedS3URL; @@ -311,8 +311,8 @@ std::vector S3FileSystem::glob( commonPrefixes.pop_back(); std::string commonPrefixContinuationToken = ""; do { - auto prefixRequest = AWSListObjectV2::request( - prefixPath, s3AuthParams, commonPrefixContinuationToken); + auto prefixRequest = AWSListObjectV2::request(prefixPath, s3AuthParams, + commonPrefixContinuationToken); AWSListObjectV2::parseKey(prefixRequest, s3Keys); auto commonPrefixesToInsert = AWSListObjectV2::parseCommonPrefix(prefixRequest); commonPrefixes.insert(commonPrefixes.end(), commonPrefixesToInsert.begin(), @@ -455,8 +455,8 @@ std::string S3FileSystem::initializeMultiPartUpload(S3FileInfo* fileInfo) const return getUploadID(result); } -void S3FileSystem::writeFile( - common::FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, uint64_t offset) const { +void S3FileSystem::writeFile(common::FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, + uint64_t offset) const { auto s3FileInfo = ku_dynamic_cast(fileInfo); if (!((s3FileInfo->flags & O_ACCMODE) & O_WRONLY)) { throw IOException("Write called on a file which is not open in write mode."); @@ -485,8 +485,8 @@ void S3FileSystem::writeFile( } } -std::shared_ptr S3FileSystem::allocateWriteBuffer( - uint16_t writeBufferIdx, uint64_t partSize, uint16_t maxThreads) { +std::shared_ptr S3FileSystem::allocateWriteBuffer(uint16_t writeBufferIdx, + uint64_t partSize, uint16_t maxThreads) { std::unique_lock lck(bufferInfoLock); if (numUsedBuffers >= maxThreads) { bufferInfoCV.wait(lck, [&] { return numUsedBuffers < maxThreads; }); @@ -509,8 +509,8 @@ void S3FileSystem::flushAllBuffers(S3FileInfo* fileInfo) { } } std::unique_lock lck(fileInfo->uploadsInProgressLock); - fileInfo->uploadsInProgressCV.wait( - lck, [fileInfo] { return fileInfo->uploadsInProgress == 0; }); + fileInfo->uploadsInProgressCV.wait(lck, + [fileInfo] { return fileInfo->uploadsInProgress == 0; }); fileInfo->rethrowIOError(); } @@ -650,8 +650,8 @@ HeaderMap S3FileSystem::createS3Header(std::string url, std::string query, std:: return res; } -std::unique_ptr S3FileSystem::headRequest( - common::FileInfo* fileInfo, const std::string& url, HeaderMap /*headerMap*/) const { +std::unique_ptr S3FileSystem::headRequest(common::FileInfo* fileInfo, + const std::string& url, HeaderMap /*headerMap*/) const { auto& authParams = ku_dynamic_cast(fileInfo)->authParams; auto parsedS3URL = parseS3URL(url, authParams); auto httpURL = parsedS3URL.getHTTPURL(); @@ -666,8 +666,8 @@ std::unique_ptr S3FileSystem::getRangeRequest(common::FileInfo* fi auto parsedS3URL = parseS3URL(url, authParams); auto s3HTTPUrl = parsedS3URL.getHTTPURL(); auto headers = createS3Header(parsedS3URL.path, "", parsedS3URL.host, "s3", "GET", authParams); - return HTTPFileSystem::getRangeRequest( - fileInfo, s3HTTPUrl, headers, fileOffset, buffer, bufferLen); + return HTTPFileSystem::getRangeRequest(fileInfo, s3HTTPUrl, headers, fileOffset, buffer, + bufferLen); } std::unique_ptr S3FileSystem::postRequest(common::FileInfo* fileInfo, @@ -680,8 +680,8 @@ std::unique_ptr S3FileSystem::postRequest(common::FileInfo* fileIn auto payloadHash = getPayloadHash(inputBuffer, inputBufferLen); auto headers = createS3Header(parsedS3URL.path, httpParams, parsedS3URL.host, "s3", "POST", authParams, payloadHash, "application/octet-stream"); - return HTTPFileSystem::postRequest( - fileInfo, httpURL, headers, outputBuffer, outputBufferLen, inputBuffer, inputBufferLen); + return HTTPFileSystem::postRequest(fileInfo, httpURL, headers, outputBuffer, outputBufferLen, + inputBuffer, inputBufferLen); } std::unique_ptr S3FileSystem::putRequest(common::FileInfo* fileInfo, @@ -708,8 +708,8 @@ std::string S3FileSystem::getPayloadHash(const uint8_t* buffer, uint64_t bufferL } } -void S3FileSystem::flushBuffer( - S3FileInfo* fileInfo, std::shared_ptr bufferToFlush) const { +void S3FileSystem::flushBuffer(S3FileInfo* fileInfo, + std::shared_ptr bufferToFlush) const { if (bufferToFlush->numBytesWritten == 0) { return; } @@ -734,8 +734,8 @@ void S3FileSystem::flushBuffer( uploadThread.detach(); } -void S3FileSystem::uploadBuffer( - S3FileInfo* fileInfo, std::shared_ptr bufferToUpload) { +void S3FileSystem::uploadBuffer(S3FileInfo* fileInfo, + std::shared_ptr bufferToUpload) { auto s3FileSystem = ku_dynamic_cast(fileInfo->fileSystem); std::string queryParam = "partNumber=" + std::to_string(bufferToUpload->partID + 1) + "&" + @@ -797,8 +797,8 @@ std::string S3FileSystem::getUploadID(const std::string& response) { return response.substr(openTagPos, closeTagPos - openTagPos); } -std::string AWSListObjectV2::request( - std::string& path, S3AuthParams& authParams, std::string& continuationToken) { +std::string AWSListObjectV2::request(std::string& path, S3AuthParams& authParams, + std::string& continuationToken) { auto parsedURL = S3FileSystem::parseS3URL(path, authParams); std::string requestPath; if (authParams.urlStyle == "path") { @@ -830,8 +830,8 @@ std::string AWSListObjectV2::request( listObjectV2URL.c_str(), *headers, [&](const httplib::Response& response) { if (response.status >= 400) { - throw IOException{common::stringFormat( - "HTTP GET error on '{}' (HTTP {})", listObjectV2URL, response.status)}; + throw IOException{common::stringFormat("HTTP GET error on '{}' (HTTP {})", + listObjectV2URL, response.status)}; } return true; }, diff --git a/extension/httpfs/test/CMakeLists.txt b/extension/httpfs/test/CMakeLists.txt index 08b6fe8acfb..e69de29bb2d 100644 --- a/extension/httpfs/test/CMakeLists.txt +++ b/extension/httpfs/test/CMakeLists.txt @@ -1,11 +0,0 @@ -add_definitions(-DTEST_FILES_DIR="extension/httpfs/test/test_files") -add_subdirectory(${CMAKE_SOURCE_DIR}/test/gtest ${CMAKE_CURRENT_BINARY_DIR}/test/gtest EXCLUDE_FROM_ALL) -# Make gtest available to subdirectories. -add_library(GTest::GTest INTERFACE IMPORTED) -target_link_libraries(GTest::GTest INTERFACE gtest_main) -target_link_libraries(GTest::GTest INTERFACE gmock_main) -enable_testing() -add_subdirectory(${CMAKE_SOURCE_DIR}/test/test_helper ${CMAKE_CURRENT_BINARY_DIR}/test/test_helper) -add_subdirectory(${CMAKE_SOURCE_DIR}/test/test_runner ${CMAKE_CURRENT_BINARY_DIR}/test/test_runner) -add_subdirectory(${CMAKE_SOURCE_DIR}/test/graph_test ${CMAKE_CURRENT_BINARY_DIR}/test/graph_test) -add_subdirectory(${CMAKE_SOURCE_DIR}/test/runner ${CMAKE_CURRENT_BINARY_DIR}/test/runner) diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/aes.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/aes.h index e9466f8ad21..49bf0c97cb2 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/aes.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/aes.h @@ -160,8 +160,8 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context* ctx); * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_aes_setkey_enc( - mbedtls_aes_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_aes_setkey_enc(mbedtls_aes_context* ctx, const unsigned char* key, + unsigned int keybits); /** * \brief This function sets the decryption key. @@ -179,8 +179,8 @@ int mbedtls_aes_setkey_enc( * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_aes_setkey_dec( - mbedtls_aes_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_aes_setkey_dec(mbedtls_aes_context* ctx, const unsigned char* key, + unsigned int keybits); #if defined(MBEDTLS_CIPHER_MODE_XTS) /** @@ -200,8 +200,8 @@ int mbedtls_aes_setkey_dec( * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_aes_xts_setkey_enc( - mbedtls_aes_xts_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context* ctx, const unsigned char* key, + unsigned int keybits); /** * \brief This function prepares an XTS context for decryption and @@ -220,8 +220,8 @@ int mbedtls_aes_xts_setkey_enc( * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_aes_xts_setkey_dec( - mbedtls_aes_xts_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context* ctx, const unsigned char* key, + unsigned int keybits); #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** @@ -248,8 +248,8 @@ int mbedtls_aes_xts_setkey_dec( * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_aes_crypt_ecb( - mbedtls_aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16]); +int mbedtls_aes_crypt_ecb(mbedtls_aes_context* ctx, int mode, const unsigned char input[16], + unsigned char output[16]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** @@ -567,8 +567,8 @@ int mbedtls_aes_crypt_ctr(mbedtls_aes_context* ctx, size_t length, size_t* nc_of * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_internal_aes_encrypt( - mbedtls_aes_context* ctx, const unsigned char input[16], unsigned char output[16]); +int mbedtls_internal_aes_encrypt(mbedtls_aes_context* ctx, const unsigned char input[16], + unsigned char output[16]); /** * \brief Internal AES block decryption function. This is only @@ -582,8 +582,8 @@ int mbedtls_internal_aes_encrypt( * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_internal_aes_decrypt( - mbedtls_aes_context* ctx, const unsigned char input[16], unsigned char output[16]); +int mbedtls_internal_aes_decrypt(mbedtls_aes_context* ctx, const unsigned char input[16], + unsigned char output[16]); #if defined(MBEDTLS_SELF_TEST) /** diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/aria.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/aria.h index c1bed14d24e..93b62ab30ea 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/aria.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/aria.h @@ -103,8 +103,8 @@ void mbedtls_aria_free(mbedtls_aria_context* ctx); * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_aria_setkey_enc( - mbedtls_aria_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_aria_setkey_enc(mbedtls_aria_context* ctx, const unsigned char* key, + unsigned int keybits); /** * \brief This function sets the decryption key. @@ -121,8 +121,8 @@ int mbedtls_aria_setkey_enc( * \return \c 0 on success. * \return A negative error code on failure. */ -int mbedtls_aria_setkey_dec( - mbedtls_aria_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_aria_setkey_dec(mbedtls_aria_context* ctx, const unsigned char* key, + unsigned int keybits); /** * \brief This function performs an ARIA single-block encryption or diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/asn1.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/asn1.h index 4d0ec240956..69f0c0cc2b5 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/asn1.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/asn1.h @@ -317,8 +317,8 @@ int mbedtls_asn1_get_enum(unsigned char** p, const unsigned char* end, int* val) * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BIT STRING. */ -int mbedtls_asn1_get_bitstring( - unsigned char** p, const unsigned char* end, mbedtls_asn1_bitstring* bs); +int mbedtls_asn1_get_bitstring(unsigned char** p, const unsigned char* end, + mbedtls_asn1_bitstring* bs); /** * \brief Retrieve a bitstring ASN.1 tag without unused bits and its @@ -387,8 +387,8 @@ int mbedtls_asn1_get_bitstring_null(unsigned char** p, const unsigned char* end, * \return An ASN.1 error code if the input does not start with * a valid ASN.1 SEQUENCE. */ -int mbedtls_asn1_get_sequence_of( - unsigned char** p, const unsigned char* end, mbedtls_asn1_sequence* cur, int tag); +int mbedtls_asn1_get_sequence_of(unsigned char** p, const unsigned char* end, + mbedtls_asn1_sequence* cur, int tag); /** * \brief Free a heap-allocated linked list presentation of * an ASN.1 sequence, including the first element. @@ -540,8 +540,8 @@ int mbedtls_asn1_get_mpi(unsigned char** p, const unsigned char* end, mbedtls_mp * * \return 0 if successful or a specific ASN.1 or MPI error code. */ -int mbedtls_asn1_get_alg( - unsigned char** p, const unsigned char* end, mbedtls_asn1_buf* alg, mbedtls_asn1_buf* params); +int mbedtls_asn1_get_alg(unsigned char** p, const unsigned char* end, mbedtls_asn1_buf* alg, + mbedtls_asn1_buf* params); /** * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no @@ -570,8 +570,8 @@ int mbedtls_asn1_get_alg_null(unsigned char** p, const unsigned char* end, mbedt * * \return NULL if not found, or a pointer to the existing entry. */ -const mbedtls_asn1_named_data* mbedtls_asn1_find_named_data( - const mbedtls_asn1_named_data* list, const char* oid, size_t len); +const mbedtls_asn1_named_data* mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data* list, + const char* oid, size_t len); /** * \brief Free a mbedtls_asn1_named_data entry diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/base64.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/base64.h index 7fca8a8f4d6..89c5ff25526 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/base64.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/base64.h @@ -54,8 +54,8 @@ extern "C" { * \note Call this function with dlen = 0 to obtain the * required buffer size in *olen */ -int mbedtls_base64_encode( - unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, size_t slen); +int mbedtls_base64_encode(unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, + size_t slen); /** * \brief Decode a base64-formatted buffer @@ -74,8 +74,8 @@ int mbedtls_base64_encode( * \note Call this function with *dst = NULL or dlen = 0 to obtain * the required buffer size in *olen */ -int mbedtls_base64_decode( - unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, size_t slen); +int mbedtls_base64_decode(unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, + size_t slen); #if defined(MBEDTLS_SELF_TEST) /** diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/bignum.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/bignum.h index 630dd0c6f08..8c87780e175 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/bignum.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/bignum.h @@ -434,8 +434,8 @@ int mbedtls_mpi_read_string(mbedtls_mpi* X, int radix, const char* s); * size of \p buf required for a successful call. * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_write_string( - const mbedtls_mpi* X, int radix, char* buf, size_t buflen, size_t* olen); +int mbedtls_mpi_write_string(const mbedtls_mpi* X, int radix, char* buf, size_t buflen, + size_t* olen); #if defined(MBEDTLS_FS_IO) /** @@ -850,8 +850,8 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi* X, const mbedtls_mpi* A, const mbedtls_mpi* * as a big-endian representation of an MPI; this can * be relevant in applications like deterministic ECDSA. */ -int mbedtls_mpi_fill_random( - mbedtls_mpi* X, size_t size, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); +int mbedtls_mpi_fill_random(mbedtls_mpi* X, size_t size, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); /** Generate a random number uniformly in a range. * @@ -946,8 +946,8 @@ int mbedtls_mpi_inv_mod(mbedtls_mpi* X, const mbedtls_mpi* A, const mbedtls_mpi* * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. * \return Another negative error code on other kinds of failure. */ -int mbedtls_mpi_is_prime_ext( - const mbedtls_mpi* X, int rounds, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); +int mbedtls_mpi_is_prime_ext(const mbedtls_mpi* X, int rounds, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); /** * \brief Flags for mbedtls_mpi_gen_prime() * diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/camellia.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/camellia.h index 30e7f25672b..f409c12374b 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/camellia.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/camellia.h @@ -86,8 +86,8 @@ void mbedtls_camellia_free(mbedtls_camellia_context* ctx); * \return \c 0 if successful. * \return A negative error code on failure. */ -int mbedtls_camellia_setkey_enc( - mbedtls_camellia_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_camellia_setkey_enc(mbedtls_camellia_context* ctx, const unsigned char* key, + unsigned int keybits); /** * \brief Perform a CAMELLIA key schedule operation for decryption. @@ -101,8 +101,8 @@ int mbedtls_camellia_setkey_enc( * \return \c 0 if successful. * \return A negative error code on failure. */ -int mbedtls_camellia_setkey_dec( - mbedtls_camellia_context* ctx, const unsigned char* key, unsigned int keybits); +int mbedtls_camellia_setkey_dec(mbedtls_camellia_context* ctx, const unsigned char* key, + unsigned int keybits); /** * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/ccm.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/ccm.h index d51849b1352..c8880f6883b 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/ccm.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/ccm.h @@ -357,8 +357,8 @@ int mbedtls_ccm_starts(mbedtls_ccm_context* ctx, int mode, const unsigned char* * \p ctx is in an invalid state, * \p total_ad_len is greater than \c 0xFF00. */ -int mbedtls_ccm_set_lengths( - mbedtls_ccm_context* ctx, size_t total_ad_len, size_t plaintext_len, size_t tag_len); +int mbedtls_ccm_set_lengths(mbedtls_ccm_context* ctx, size_t total_ad_len, size_t plaintext_len, + size_t tag_len); /** * \brief This function feeds an input buffer as associated data diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/cipher.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/cipher.h index ff68fce6b71..27bbd307a8f 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/cipher.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/cipher.h @@ -428,8 +428,8 @@ const mbedtls_cipher_info_t* mbedtls_cipher_info_from_type(const mbedtls_cipher_ * given \p cipher_id. * \return \c NULL if the associated cipher information is not found. */ -const mbedtls_cipher_info_t* mbedtls_cipher_info_from_values( - const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode); +const mbedtls_cipher_info_t* mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, + int key_bitlen, const mbedtls_cipher_mode_t mode); /** * \brief Retrieve the identifier for a cipher info structure. @@ -649,8 +649,8 @@ int mbedtls_cipher_setup(mbedtls_cipher_context_t* ctx, const mbedtls_cipher_inf * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. */ -int mbedtls_cipher_setup_psa( - mbedtls_cipher_context_t* ctx, const mbedtls_cipher_info_t* cipher_info, size_t taglen); +int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t* ctx, + const mbedtls_cipher_info_t* cipher_info, size_t taglen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /** @@ -987,8 +987,8 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t* ctx, unsigned char* tag, * \return \c 0 on success. * \return A specific error code on failure. */ -int mbedtls_cipher_check_tag( - mbedtls_cipher_context_t* ctx, const unsigned char* tag, size_t tag_len); +int mbedtls_cipher_check_tag(mbedtls_cipher_context_t* ctx, const unsigned char* tag, + size_t tag_len); #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/des.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/des.h index e5734d05852..656af738ba1 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/des.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/des.h @@ -191,8 +191,8 @@ int mbedtls_des_setkey_dec(mbedtls_des_context* ctx, const unsigned char key[MBE * \return 0 */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_des3_set2key_enc( - mbedtls_des3_context* ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); +int mbedtls_des3_set2key_enc(mbedtls_des3_context* ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (112-bit, decryption) @@ -203,8 +203,8 @@ int mbedtls_des3_set2key_enc( * \return 0 */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_des3_set2key_dec( - mbedtls_des3_context* ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); +int mbedtls_des3_set2key_dec(mbedtls_des3_context* ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (168-bit, encryption) @@ -215,8 +215,8 @@ int mbedtls_des3_set2key_dec( * \return 0 */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_des3_set3key_enc( - mbedtls_des3_context* ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); +int mbedtls_des3_set3key_enc(mbedtls_des3_context* ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief Triple-DES key schedule (168-bit, decryption) @@ -227,8 +227,8 @@ int mbedtls_des3_set3key_enc( * \return 0 */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_des3_set3key_dec( - mbedtls_des3_context* ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); +int mbedtls_des3_set3key_dec(mbedtls_des3_context* ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief DES-ECB block encryption/decryption @@ -244,8 +244,8 @@ int mbedtls_des3_set3key_dec( * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_des_crypt_ecb( - mbedtls_des_context* ctx, const unsigned char input[8], unsigned char output[8]); +int mbedtls_des_crypt_ecb(mbedtls_des_context* ctx, const unsigned char input[8], + unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** @@ -285,8 +285,8 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context* ctx, int mode, size_t length, uns * \return 0 if successful */ MBEDTLS_CHECK_RETURN_TYPICAL -int mbedtls_des3_crypt_ecb( - mbedtls_des3_context* ctx, const unsigned char input[8], unsigned char output[8]); +int mbedtls_des3_crypt_ecb(mbedtls_des3_context* ctx, const unsigned char input[8], + unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/entropy.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/entropy.h index e440444c00d..a1cc701fd6e 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/entropy.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/entropy.h @@ -96,8 +96,8 @@ extern "C" { * \return 0 if no critical failures occurred, * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise */ -typedef int (*mbedtls_entropy_f_source_ptr)( - void* data, unsigned char* output, size_t len, size_t* olen); +typedef int ( + *mbedtls_entropy_f_source_ptr)(void* data, unsigned char* output, size_t len, size_t* olen); /** * \brief Entropy source state @@ -206,8 +206,8 @@ int mbedtls_entropy_func(void* data, unsigned char* output, size_t len); * * \return 0 if successful */ -int mbedtls_entropy_update_manual( - mbedtls_entropy_context* ctx, const unsigned char* data, size_t len); +int mbedtls_entropy_update_manual(mbedtls_entropy_context* ctx, const unsigned char* data, + size_t len); #if defined(MBEDTLS_ENTROPY_NV_SEED) /** diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/oid.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/oid.h index 7bcd50f2099..de20988a156 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/oid.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/oid.h @@ -677,8 +677,8 @@ int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, const char** oid, * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_sig_alg( - const mbedtls_asn1_buf* oid, mbedtls_md_type_t* md_alg, mbedtls_pk_type_t* pk_alg); +int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf* oid, mbedtls_md_type_t* md_alg, + mbedtls_pk_type_t* pk_alg); /** * \brief Translate SignatureAlgorithm OID into description @@ -700,8 +700,8 @@ int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf* oid, const char** desc) * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_oid_by_sig_alg( - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const char** oid, size_t* olen); +int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char** oid, size_t* olen); /** * \brief Translate hash algorithm OID into md_type @@ -780,8 +780,8 @@ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf* oid, mbedtls_cipher_type_ * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_pkcs12_pbe_alg( - const mbedtls_asn1_buf* oid, mbedtls_md_type_t* md_alg, mbedtls_cipher_type_t* cipher_alg); +int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf* oid, mbedtls_md_type_t* md_alg, + mbedtls_cipher_type_t* cipher_alg); #endif /* MBEDTLS_PKCS12_C */ #ifdef __cplusplus diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/platform.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/platform.h index 15d22ab92c1..3f4a5650b52 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/platform.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/platform.h @@ -143,8 +143,8 @@ extern void mbedtls_free(void* ptr); * * \return \c 0. */ -int mbedtls_platform_set_calloc_free( - void* (*calloc_func)(size_t, size_t), void (*free_func)(void*)); +int mbedtls_platform_set_calloc_free(void* (*calloc_func)(size_t, size_t), + void (*free_func)(void*)); #endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ #else /* !MBEDTLS_PLATFORM_MEMORY */ #define mbedtls_free free diff --git a/extension/httpfs/third_party/mbedtls/include/mbedtls/rsa.h b/extension/httpfs/third_party/mbedtls/include/mbedtls/rsa.h index a9669d5447d..e2fa3e7db74 100644 --- a/extension/httpfs/third_party/mbedtls/include/mbedtls/rsa.h +++ b/extension/httpfs/third_party/mbedtls/include/mbedtls/rsa.h @@ -394,8 +394,8 @@ int mbedtls_rsa_export_raw(const mbedtls_rsa_context* ctx, unsigned char* N, siz * \return A non-zero error code on failure. * */ -int mbedtls_rsa_export_crt( - const mbedtls_rsa_context* ctx, mbedtls_mpi* DP, mbedtls_mpi* DQ, mbedtls_mpi* QP); +int mbedtls_rsa_export_crt(const mbedtls_rsa_context* ctx, mbedtls_mpi* DP, mbedtls_mpi* DQ, + mbedtls_mpi* QP); /** * \brief This function retrieves the length of RSA modulus in Bytes. diff --git a/extension/httpfs/third_party/mbedtls/library/aes.cpp b/extension/httpfs/third_party/mbedtls/library/aes.cpp index 677594d6bda..f5879491401 100644 --- a/extension/httpfs/third_party/mbedtls/library/aes.cpp +++ b/extension/httpfs/third_party/mbedtls/library/aes.cpp @@ -41,12 +41,12 @@ #endif #if defined(MBEDTLS_SELF_TEST) -//#if defined(MBEDTLS_PLATFORM_C) -//#include "mbedtls/platform.h" -//#else -//#include -//#define mbedtls_printf printf -//#endif /* MBEDTLS_PLATFORM_C */ +// #if defined(MBEDTLS_PLATFORM_C) +// #include "mbedtls/platform.h" +// #else +// #include +// #define mbedtls_printf printf +// #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_AES_ALT) @@ -325,7 +325,7 @@ static uint32_t RCON[10]; * Tables generation code */ #define ROTL8(x) (((x) << 8) & 0xFFFFFFFF) | ((x) >> 24) -#define XTIME(x) (((x) << 1) ^ (((x)&0x80) ? 0x1B : 0x00)) +#define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00)) #define MUL(x, y) (((x) && (y)) ? pow[(log[(x)] + log[(y)]) % 255] : 0) static int aes_init_done = 0; @@ -472,8 +472,8 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context* ctx) { * AES key schedule (encryption) */ #if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) -int mbedtls_aes_setkey_enc( - mbedtls_aes_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_aes_setkey_enc(mbedtls_aes_context* ctx, const unsigned char* key, + unsigned int keybits) { unsigned int i; uint32_t* RK; @@ -583,8 +583,8 @@ int mbedtls_aes_setkey_enc( * AES key schedule (decryption) */ #if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) -int mbedtls_aes_setkey_dec( - mbedtls_aes_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_aes_setkey_dec(mbedtls_aes_context* ctx, const unsigned char* key, + unsigned int keybits) { int i, j, ret; mbedtls_aes_context cty; uint32_t* RK; @@ -668,8 +668,8 @@ static int mbedtls_aes_xts_decode_keys(const unsigned char* key, unsigned int ke return 0; } -int mbedtls_aes_xts_setkey_enc( - mbedtls_aes_xts_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context* ctx, const unsigned char* key, + unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *key1, *key2; unsigned int key1bits, key2bits; @@ -690,8 +690,8 @@ int mbedtls_aes_xts_setkey_enc( return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits); } -int mbedtls_aes_xts_setkey_dec( - mbedtls_aes_xts_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context* ctx, const unsigned char* key, + unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *key1, *key2; unsigned int key1bits, key2bits; @@ -747,8 +747,8 @@ int mbedtls_aes_xts_setkey_dec( * AES-ECB block encryption */ #if !defined(MBEDTLS_AES_ENCRYPT_ALT) -int mbedtls_internal_aes_encrypt( - mbedtls_aes_context* ctx, const unsigned char input[16], unsigned char output[16]) { +int mbedtls_internal_aes_encrypt(mbedtls_aes_context* ctx, const unsigned char input[16], + unsigned char output[16]) { int i; uint32_t* RK = ctx->rk; struct { @@ -807,8 +807,8 @@ int mbedtls_internal_aes_encrypt( * AES-ECB block decryption */ #if !defined(MBEDTLS_AES_DECRYPT_ALT) -int mbedtls_internal_aes_decrypt( - mbedtls_aes_context* ctx, const unsigned char input[16], unsigned char output[16]) { +int mbedtls_internal_aes_decrypt(mbedtls_aes_context* ctx, const unsigned char input[16], + unsigned char output[16]) { int i; uint32_t* RK = ctx->rk; struct { @@ -866,8 +866,8 @@ int mbedtls_internal_aes_decrypt( /* * AES-ECB block encryption/decryption */ -int mbedtls_aes_crypt_ecb( - mbedtls_aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16]) { +int mbedtls_aes_crypt_ecb(mbedtls_aes_context* ctx, int mode, const unsigned char input[16], + unsigned char output[16]) { AES_VALIDATE_RET(ctx != NULL); AES_VALIDATE_RET(input != NULL); AES_VALIDATE_RET(output != NULL); @@ -1274,34 +1274,34 @@ int mbedtls_aes_crypt_ctr(mbedtls_aes_context* ctx, size_t length, size_t* nc_of * * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip */ -static const unsigned char aes_test_ecb_dec[3][16] = { - {0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, - 0xE0}, +static const unsigned char aes_test_ecb_dec[3][16] = {{0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, + 0x58, 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, + 0xEB, 0xE0}, {0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4}, {0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE}}; -static const unsigned char aes_test_ecb_enc[3][16] = { - {0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, - 0x7F}, +static const unsigned char aes_test_ecb_enc[3][16] = {{0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, + 0x73, 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, + 0x29, 0x7F}, {0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14}, {0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4}}; #if defined(MBEDTLS_CIPHER_MODE_CBC) -static const unsigned char aes_test_cbc_dec[3][16] = { - {0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, - 0x86}, +static const unsigned char aes_test_cbc_dec[3][16] = {{0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, + 0x73, 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, + 0xAF, 0x86}, {0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B}, {0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13}}; -static const unsigned char aes_test_cbc_enc[3][16] = { - {0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, - 0x3D}, +static const unsigned char aes_test_cbc_enc[3][16] = {{0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, + 0x84, 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, + 0x8E, 0x3D}, {0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04}, {0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, @@ -1314,17 +1314,17 @@ static const unsigned char aes_test_cbc_enc[3][16] = { * * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ -static const unsigned char aes_test_cfb128_key[3][32] = { - {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, - 0x3C}, +static const unsigned char aes_test_cfb128_key[3][32] = {{0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, + 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, + 0xCF, 0x4F, 0x3C}, {0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B}, {0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4}}; -static const unsigned char aes_test_cfb128_iv[16] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; +static const unsigned char aes_test_cfb128_iv[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; static const unsigned char aes_test_cfb128_pt[64] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, @@ -1356,17 +1356,17 @@ static const unsigned char aes_test_cfb128_ct[3][64] = { * * https://csrc.nist.gov/publications/detail/sp/800-38a/final */ -static const unsigned char aes_test_ofb_key[3][32] = { - {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, - 0x3C}, +static const unsigned char aes_test_ofb_key[3][32] = {{0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, + 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, + 0x4F, 0x3C}, {0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B}, {0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4}}; -static const unsigned char aes_test_ofb_iv[16] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; +static const unsigned char aes_test_ofb_iv[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; static const unsigned char aes_test_ofb_pt[64] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, @@ -1399,25 +1399,25 @@ static const unsigned char aes_test_ofb_ct[3][64] = { * http://www.faqs.org/rfcs/rfc3686.html */ -static const unsigned char aes_test_ctr_key[3][16] = { - {0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, - 0x9E}, +static const unsigned char aes_test_ctr_key[3][16] = {{0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, + 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, + 0xF3, 0x9E}, {0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63}, {0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC}}; -static const unsigned char aes_test_ctr_nonce_counter[3][16] = { - {0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01}, +static const unsigned char aes_test_ctr_nonce_counter[3][16] = {{0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01}, {0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01}, {0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01}}; -static const unsigned char aes_test_ctr_pt[3][48] = { - {0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, - 0x67}, +static const unsigned char aes_test_ctr_pt[3][48] = {{0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, + 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, + 0x73, 0x67}, {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, @@ -1427,9 +1427,9 @@ static const unsigned char aes_test_ctr_pt[3][48] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23}}; -static const unsigned char aes_test_ctr_ct[3][48] = { - {0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, - 0xB8}, +static const unsigned char aes_test_ctr_ct[3][48] = {{0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, + 0x79, 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, + 0x11, 0xB8}, {0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28}, @@ -1535,8 +1535,8 @@ int mbedtls_aes_self_test(int verbose) { mode = i & 1; if (verbose != 0) - mbedtls_printf( - " AES-ECB-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + mbedtls_printf(" AES-ECB-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); memset(buf, 0, 16); @@ -1588,8 +1588,8 @@ int mbedtls_aes_self_test(int verbose) { mode = i & 1; if (verbose != 0) - mbedtls_printf( - " AES-CBC-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + mbedtls_printf(" AES-CBC-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); memset(iv, 0, 16); memset(prv, 0, 16); @@ -1652,8 +1652,8 @@ int mbedtls_aes_self_test(int verbose) { mode = i & 1; if (verbose != 0) - mbedtls_printf( - " AES-CFB128-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + mbedtls_printf(" AES-CFB128-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); memcpy(iv, aes_test_cfb128_iv, 16); memcpy(key, aes_test_cfb128_key[u], keybits / 8); @@ -1707,8 +1707,8 @@ int mbedtls_aes_self_test(int verbose) { mode = i & 1; if (verbose != 0) - mbedtls_printf( - " AES-OFB-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + mbedtls_printf(" AES-OFB-%3u (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); memcpy(iv, aes_test_ofb_iv, 16); memcpy(key, aes_test_ofb_key[u], keybits / 8); @@ -1813,8 +1813,8 @@ int mbedtls_aes_self_test(int verbose) { mode = i & 1; if (verbose != 0) - mbedtls_printf( - " AES-XTS-128 (%s): ", (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + mbedtls_printf(" AES-XTS-128 (%s): ", + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); memset(key, 0, sizeof(key)); memcpy(key, aes_test_xts_key[u], 32); diff --git a/extension/httpfs/third_party/mbedtls/library/aria.cpp b/extension/httpfs/third_party/mbedtls/library/aria.cpp index bfc460fd4ad..678c298516f 100644 --- a/extension/httpfs/third_party/mbedtls/library/aria.cpp +++ b/extension/httpfs/third_party/mbedtls/library/aria.cpp @@ -87,7 +87,7 @@ static inline uint32_t aria_p1(uint32_t x) { #endif /* x86 gnuc */ #endif /* MBEDTLS_HAVE_ASM && GNUC */ #if !defined(ARIA_P1) -#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x)&0x00FF00FF) << 8)) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) #endif /* @@ -283,8 +283,8 @@ static const uint8_t aria_is2[256] = {0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, /* * Helper for key schedule: r = FO( p, k ) ^ x */ -static void aria_fo_xor( - uint32_t r[4], const uint32_t p[4], const uint32_t k[4], const uint32_t x[4]) { +static void aria_fo_xor(uint32_t r[4], const uint32_t p[4], const uint32_t k[4], + const uint32_t x[4]) { uint32_t a, b, c, d; a = p[0] ^ k[0]; @@ -304,8 +304,8 @@ static void aria_fo_xor( /* * Helper for key schedule: r = FE( p, k ) ^ x */ -static void aria_fe_xor( - uint32_t r[4], const uint32_t p[4], const uint32_t k[4], const uint32_t x[4]) { +static void aria_fe_xor(uint32_t r[4], const uint32_t p[4], const uint32_t k[4], + const uint32_t x[4]) { uint32_t a, b, c, d; a = p[0] ^ k[0]; @@ -352,8 +352,8 @@ static void aria_rot128(uint32_t r[4], const uint32_t a[4], const uint32_t b[4], /* * Set encryption key */ -int mbedtls_aria_setkey_enc( - mbedtls_aria_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_aria_setkey_enc(mbedtls_aria_context* ctx, const unsigned char* key, + unsigned int keybits) { /* round constant masks */ const uint32_t rc[3][4] = {{0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA}, {0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF}, @@ -411,8 +411,8 @@ int mbedtls_aria_setkey_enc( /* * Set decryption key */ -int mbedtls_aria_setkey_dec( - mbedtls_aria_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_aria_setkey_dec(mbedtls_aria_context* ctx, const unsigned char* key, + unsigned int keybits) { int i, j, k, ret; ARIA_VALIDATE_RET(ctx != NULL); ARIA_VALIDATE_RET(key != NULL); @@ -906,8 +906,8 @@ int mbedtls_aria_self_test(int verbose) { memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0xAA, sizeof(buf)); j = 0; - mbedtls_aria_crypt_cfb128( - &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, iv, aria_test2_cfb_ct[i], buf); + mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, iv, aria_test2_cfb_ct[i], + buf); if (memcmp(buf, aria_test2_pt, 48) != 0) ARIA_SELF_TEST_IF_FAIL; } diff --git a/extension/httpfs/third_party/mbedtls/library/asn1parse.cpp b/extension/httpfs/third_party/mbedtls/library/asn1parse.cpp index be18c6b07c3..f1d4af27c66 100644 --- a/extension/httpfs/third_party/mbedtls/library/asn1parse.cpp +++ b/extension/httpfs/third_party/mbedtls/library/asn1parse.cpp @@ -185,8 +185,8 @@ int mbedtls_asn1_get_mpi(unsigned char** p, const unsigned char* end, mbedtls_mp } #endif /* MBEDTLS_BIGNUM_C */ -int mbedtls_asn1_get_bitstring( - unsigned char** p, const unsigned char* end, mbedtls_asn1_bitstring* bs) { +int mbedtls_asn1_get_bitstring(unsigned char** p, const unsigned char* end, + mbedtls_asn1_bitstring* bs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Certificate type is a single byte bitstring */ @@ -226,8 +226,8 @@ int mbedtls_asn1_traverse_sequence_of(unsigned char** p, const unsigned char* en size_t len; /* Get main sequence tag */ - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return (ret); } @@ -315,21 +315,21 @@ static int asn1_get_sequence_of_cb(void* ctx, int tag, unsigned char* start, siz /* * Parses and splits an ASN.1 "SEQUENCE OF " */ -int mbedtls_asn1_get_sequence_of( - unsigned char** p, const unsigned char* end, mbedtls_asn1_sequence* cur, int tag) { +int mbedtls_asn1_get_sequence_of(unsigned char** p, const unsigned char* end, + mbedtls_asn1_sequence* cur, int tag) { asn1_get_sequence_of_cb_ctx_t cb_ctx = {tag, cur}; memset(cur, 0, sizeof(mbedtls_asn1_sequence)); - return (mbedtls_asn1_traverse_sequence_of( - p, end, 0xFF, tag, 0, 0, asn1_get_sequence_of_cb, &cb_ctx)); + return (mbedtls_asn1_traverse_sequence_of(p, end, 0xFF, tag, 0, 0, asn1_get_sequence_of_cb, + &cb_ctx)); } -int mbedtls_asn1_get_alg( - unsigned char** p, const unsigned char* end, mbedtls_asn1_buf* alg, mbedtls_asn1_buf* params) { +int mbedtls_asn1_get_alg(unsigned char** p, const unsigned char* end, mbedtls_asn1_buf* alg, + mbedtls_asn1_buf* params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) return (ret); if ((end - *p) < 1) @@ -399,8 +399,8 @@ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data** head) { } } -const mbedtls_asn1_named_data* mbedtls_asn1_find_named_data( - const mbedtls_asn1_named_data* list, const char* oid, size_t len) { +const mbedtls_asn1_named_data* mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data* list, + const char* oid, size_t len) { while (list != NULL) { if (list->oid.len == len && memcmp(list->oid.p, oid, len) == 0) { break; diff --git a/extension/httpfs/third_party/mbedtls/library/base64.cpp b/extension/httpfs/third_party/mbedtls/library/base64.cpp index 31870bcd7de..cea5cedebc0 100644 --- a/extension/httpfs/third_party/mbedtls/library/base64.cpp +++ b/extension/httpfs/third_party/mbedtls/library/base64.cpp @@ -36,13 +36,13 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ -#define BASE64_SIZE_T_MAX ((size_t)-1) /* SIZE_T_MAX is not standard */ +#define BASE64_SIZE_T_MAX ((size_t) - 1) /* SIZE_T_MAX is not standard */ /* * Encode a buffer into base64 format */ -int mbedtls_base64_encode( - unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, size_t slen) { +int mbedtls_base64_encode(unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, + size_t slen) { size_t i, n; int C1, C2, C3; unsigned char* p; @@ -103,8 +103,8 @@ int mbedtls_base64_encode( /* * Decode a base64-formatted buffer */ -int mbedtls_base64_decode( - unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, size_t slen) { +int mbedtls_base64_decode(unsigned char* dst, size_t dlen, size_t* olen, const unsigned char* src, + size_t slen) { size_t i; /* index in source */ size_t n; /* number of digits or trailing = in source */ uint32_t x; /* value accumulator */ diff --git a/extension/httpfs/third_party/mbedtls/library/bignum.cpp b/extension/httpfs/third_party/mbedtls/library/bignum.cpp index 13fb1d1a9e8..39b733381db 100644 --- a/extension/httpfs/third_party/mbedtls/library/bignum.cpp +++ b/extension/httpfs/third_party/mbedtls/library/bignum.cpp @@ -63,7 +63,7 @@ #define biL (ciL << 3) /* bits in limb */ #define biH (ciL << 2) /* half limb size */ -#define MPI_SIZE_T_MAX ((size_t)-1) /* SIZE_T_MAX is not standard */ +#define MPI_SIZE_T_MAX ((size_t) - 1) /* SIZE_T_MAX is not standard */ /* * Convert between bits/chars and number of limbs @@ -482,8 +482,8 @@ static int mpi_write_hlp(mbedtls_mpi* X, int radix, char** p, const size_t bufle /* * Export into an ASCII string */ -int mbedtls_mpi_write_string( - const mbedtls_mpi* X, int radix, char* buf, size_t buflen, size_t* olen) { +int mbedtls_mpi_write_string(const mbedtls_mpi* X, int radix, char* buf, size_t buflen, + size_t* olen) { int ret = 0; size_t n; char* p; @@ -1113,8 +1113,8 @@ int mbedtls_mpi_add_abs(mbedtls_mpi* X, const mbedtls_mpi* A, const mbedtls_mpi* * \return 1 if `l < r`. * 0 if `l >= r`. */ -static mbedtls_mpi_uint mpi_sub_hlp( - size_t n, mbedtls_mpi_uint* d, const mbedtls_mpi_uint* l, const mbedtls_mpi_uint* r) { +static mbedtls_mpi_uint mpi_sub_hlp(size_t n, mbedtls_mpi_uint* d, const mbedtls_mpi_uint* l, + const mbedtls_mpi_uint* r) { size_t i; mbedtls_mpi_uint c = 0, t, z; @@ -1439,8 +1439,8 @@ int mbedtls_mpi_mul_int(mbedtls_mpi* X, const mbedtls_mpi* A, mbedtls_mpi_uint b * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and * mbedtls_mpi_uint divisor, d */ -static mbedtls_mpi_uint mbedtls_int_div_int( - mbedtls_mpi_uint u1, mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint* r) { +static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1, mbedtls_mpi_uint u0, + mbedtls_mpi_uint d, mbedtls_mpi_uint* r) { #if defined(MBEDTLS_HAVE_UDBL) mbedtls_t_udbl dividend, quotient; #else @@ -1533,8 +1533,8 @@ static mbedtls_mpi_uint mbedtls_int_div_int( /* * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) */ -int mbedtls_mpi_div_mpi( - mbedtls_mpi* Q, mbedtls_mpi* R, const mbedtls_mpi* A, const mbedtls_mpi* B) { +int mbedtls_mpi_div_mpi(mbedtls_mpi* Q, mbedtls_mpi* R, const mbedtls_mpi* A, + const mbedtls_mpi* B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; @@ -1837,8 +1837,8 @@ static void mpi_montmul(mbedtls_mpi* A, const mbedtls_mpi* B, const mbedtls_mpi* * * See mpi_montmul() regarding constraints and guarantees on the parameters. */ -static void mpi_montred( - mbedtls_mpi* A, const mbedtls_mpi* N, mbedtls_mpi_uint mm, const mbedtls_mpi* T) { +static void mpi_montred(mbedtls_mpi* A, const mbedtls_mpi* N, mbedtls_mpi_uint mm, + const mbedtls_mpi* T) { mbedtls_mpi_uint z = 1; mbedtls_mpi U; @@ -2216,8 +2216,8 @@ int mbedtls_mpi_gcd(mbedtls_mpi* G, const mbedtls_mpi* A, const mbedtls_mpi* B) * The size and sign of X are unchanged. * n_bytes must not be 0. */ -static int mpi_fill_random_internal( - mbedtls_mpi* X, size_t n_bytes, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +static int mpi_fill_random_internal(mbedtls_mpi* X, size_t n_bytes, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(n_bytes); const size_t overhead = (limbs * ciL) - n_bytes; @@ -2241,8 +2241,8 @@ static int mpi_fill_random_internal( * regardless of the platform endianness (useful when f_rng is actually * deterministic, eg for tests). */ -int mbedtls_mpi_fill_random( - mbedtls_mpi* X, size_t size, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +int mbedtls_mpi_fill_random(mbedtls_mpi* X, size_t size, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t const limbs = CHARS_TO_LIMBS(size); @@ -2473,8 +2473,8 @@ static int mpi_check_small_factors(const mbedtls_mpi* X) { /* * Miller-Rabin pseudo-primality test (HAC 4.24) */ -static int mpi_miller_rabin( - const mbedtls_mpi* X, size_t rounds, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +static int mpi_miller_rabin(const mbedtls_mpi* X, size_t rounds, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { int ret, count; size_t i, j, k, s; mbedtls_mpi W, R, T, A, RR; @@ -2562,8 +2562,8 @@ static int mpi_miller_rabin( /* * Pseudo-primality test: small factors, then Miller-Rabin */ -int mbedtls_mpi_is_prime_ext( - const mbedtls_mpi* X, int rounds, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +int mbedtls_mpi_is_prime_ext(const mbedtls_mpi* X, int rounds, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi XX; MPI_VALIDATE_RET(X != NULL); @@ -2722,8 +2722,8 @@ int mbedtls_mpi_gen_prime(mbedtls_mpi* X, size_t nbits, int flags, #define GCD_PAIR_COUNT 3 -static const int gcd_pairs[GCD_PAIR_COUNT][3] = { - {693, 609, 21}, {1764, 868, 28}, {768454923, 542167814, 1}}; +static const int gcd_pairs[GCD_PAIR_COUNT][3] = {{693, 609, 21}, {1764, 868, 28}, + {768454923, 542167814, 1}}; /* * Checkup routine diff --git a/extension/httpfs/third_party/mbedtls/library/camellia.cpp b/extension/httpfs/third_party/mbedtls/library/camellia.cpp index 15ebd26ec8a..3827792d937 100644 --- a/extension/httpfs/third_party/mbedtls/library/camellia.cpp +++ b/extension/httpfs/third_party/mbedtls/library/camellia.cpp @@ -199,10 +199,10 @@ static const signed char transposes[2][20] = { #define SHIFT_AND_PLACE(INDEX, OFFSET) \ { \ - TK[0] = KC[(OFFSET)*4 + 0]; \ - TK[1] = KC[(OFFSET)*4 + 1]; \ - TK[2] = KC[(OFFSET)*4 + 2]; \ - TK[3] = KC[(OFFSET)*4 + 3]; \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ \ for (i = 1; i <= 4; i++) \ if (shifts[(INDEX)][(OFFSET)][i - 1]) \ @@ -248,8 +248,8 @@ void mbedtls_camellia_free(mbedtls_camellia_context* ctx) { /* * Camellia key schedule (encryption) */ -int mbedtls_camellia_setkey_enc( - mbedtls_camellia_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_camellia_setkey_enc(mbedtls_camellia_context* ctx, const unsigned char* key, + unsigned int keybits) { int idx; size_t i; uint32_t* RK; @@ -361,8 +361,8 @@ int mbedtls_camellia_setkey_enc( /* * Camellia key schedule (decryption) */ -int mbedtls_camellia_setkey_dec( - mbedtls_camellia_context* ctx, const unsigned char* key, unsigned int keybits) { +int mbedtls_camellia_setkey_dec(mbedtls_camellia_context* ctx, const unsigned char* key, + unsigned int keybits) { int idx, ret; size_t i; mbedtls_camellia_context cty; @@ -658,9 +658,9 @@ static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = #if defined(MBEDTLS_CIPHER_MODE_CBC) #define CAMELLIA_TESTS_CBC 3 -static const unsigned char camellia_test_cbc_key[3][32] = { - {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, - 0x3C}, +static const unsigned char camellia_test_cbc_key[3][32] = {{0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, + 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, + 0x09, 0xCF, 0x4F, 0x3C}, {0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B}, {0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, @@ -709,9 +709,9 @@ static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = * http://www.faqs.org/rfcs/rfc5528.html */ -static const unsigned char camellia_test_ctr_key[3][16] = { - {0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, - 0x9E}, +static const unsigned char camellia_test_ctr_key[3][16] = {{0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, + 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, + 0x55, 0x77, 0xF3, 0x9E}, {0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63}, {0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, @@ -725,9 +725,9 @@ static const unsigned char camellia_test_ctr_nonce_counter[3][16] = { {0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01}}; -static const unsigned char camellia_test_ctr_pt[3][48] = { - {0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, - 0x67}, +static const unsigned char camellia_test_ctr_pt[3][48] = {{0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, + 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, + 0x6D, 0x73, 0x67}, {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, @@ -737,9 +737,9 @@ static const unsigned char camellia_test_ctr_pt[3][48] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23}}; -static const unsigned char camellia_test_ctr_ct[3][48] = { - {0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, - 0x3F}, +static const unsigned char camellia_test_ctr_ct[3][48] = {{0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, + 0x9A, 0x20, 0x87, 0x7C, 0x76, 0xDB, + 0x1F, 0x0B, 0x3F}, {0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48}, @@ -871,8 +871,8 @@ int mbedtls_camellia_self_test(int verbose) { v = i & 1; if (verbose != 0) - mbedtls_printf( - " CAMELLIA-CTR-128 (%s): ", (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + mbedtls_printf(" CAMELLIA-CTR-128 (%s): ", + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); memcpy(nonce_counter, camellia_test_ctr_nonce_counter[u], 16); memcpy(key, camellia_test_ctr_key[u], 16); diff --git a/extension/httpfs/third_party/mbedtls/library/cipher.cpp b/extension/httpfs/third_party/mbedtls/library/cipher.cpp index ecf3b1d1f28..22a9b08c7f3 100644 --- a/extension/httpfs/third_party/mbedtls/library/cipher.cpp +++ b/extension/httpfs/third_party/mbedtls/library/cipher.cpp @@ -119,8 +119,8 @@ const mbedtls_cipher_info_t* mbedtls_cipher_info_from_string(const char* cipher_ return (NULL); } -const mbedtls_cipher_info_t* mbedtls_cipher_info_from_values( - const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode) { +const mbedtls_cipher_info_t* mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, + int key_bitlen, const mbedtls_cipher_mode_t mode) { const mbedtls_cipher_definition_t* def; for (def = mbedtls_cipher_definitions; def->info != NULL; def++) @@ -200,8 +200,8 @@ int mbedtls_cipher_setup(mbedtls_cipher_context_t* ctx, const mbedtls_cipher_inf } #if defined(MBEDTLS_USE_PSA_CRYPTO) -int mbedtls_cipher_setup_psa( - mbedtls_cipher_context_t* ctx, const mbedtls_cipher_info_t* cipher_info, size_t taglen) { +int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t* ctx, + const mbedtls_cipher_info_t* cipher_info, size_t taglen) { psa_algorithm_t alg; mbedtls_cipher_context_psa* cipher_psa; @@ -408,8 +408,8 @@ int mbedtls_cipher_reset(mbedtls_cipher_context_t* ctx) { } #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) -int mbedtls_cipher_update_ad( - mbedtls_cipher_context_t* ctx, const unsigned char* ad, size_t ad_len) { +int mbedtls_cipher_update_ad(mbedtls_cipher_context_t* ctx, const unsigned char* ad, + size_t ad_len) { CIPHER_VALIDATE_RET(ctx != NULL); CIPHER_VALIDATE_RET(ad_len == 0 || ad != NULL); if (ctx->cipher_info == NULL) @@ -443,8 +443,8 @@ int mbedtls_cipher_update_ad( if (result != 0) return (result); - return (mbedtls_chachapoly_update_aad( - (mbedtls_chachapoly_context*)ctx->cipher_ctx, ad, ad_len)); + return (mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context*)ctx->cipher_ctx, ad, + ad_len)); } #endif @@ -485,8 +485,8 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t* ctx, const unsigned char* in *olen = ilen; - if (0 != (ret = ctx->cipher_info->base->ecb_func( - ctx->cipher_ctx, ctx->operation, input, output))) { + if (0 != (ret = ctx->cipher_info->base->ecb_func(ctx->cipher_ctx, ctx->operation, input, + output))) { return (ret); } @@ -495,23 +495,23 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t* ctx, const unsigned char* in #if defined(MBEDTLS_GCM_C) if (ctx->cipher_info->mode == MBEDTLS_MODE_GCM) { - return (mbedtls_gcm_update( - (mbedtls_gcm_context*)ctx->cipher_ctx, input, ilen, output, ilen, olen)); + return (mbedtls_gcm_update((mbedtls_gcm_context*)ctx->cipher_ctx, input, ilen, output, ilen, + olen)); } #endif #if defined(MBEDTLS_CCM_C) if (ctx->cipher_info->mode == MBEDTLS_MODE_CCM_STAR_NO_TAG) { - return (mbedtls_ccm_update( - (mbedtls_ccm_context*)ctx->cipher_ctx, input, ilen, output, ilen, olen)); + return (mbedtls_ccm_update((mbedtls_ccm_context*)ctx->cipher_ctx, input, ilen, output, ilen, + olen)); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) { *olen = ilen; - return (mbedtls_chachapoly_update( - (mbedtls_chachapoly_context*)ctx->cipher_ctx, ilen, input, output)); + return (mbedtls_chachapoly_update((mbedtls_chachapoly_context*)ctx->cipher_ctx, ilen, input, + output)); } #endif @@ -581,8 +581,8 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t* ctx, const unsigned char* in * Process remaining full blocks */ if (ilen) { - if (0 != (ret = ctx->cipher_info->base->cbc_func( - ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output))) { + if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx, ctx->operation, ilen, + ctx->iv, input, output))) { return (ret); } @@ -608,8 +608,8 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t* ctx, const unsigned char* in #if defined(MBEDTLS_CIPHER_MODE_OFB) if (ctx->cipher_info->mode == MBEDTLS_MODE_OFB) { - if (0 != (ret = ctx->cipher_info->base->ofb_func( - ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, input, output))) { + if (0 != (ret = ctx->cipher_info->base->ofb_func(ctx->cipher_ctx, ilen, + &ctx->unprocessed_len, ctx->iv, input, output))) { return (ret); } @@ -639,8 +639,8 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t* ctx, const unsigned char* in return (MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE); } - ret = ctx->cipher_info->base->xts_func( - ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output); + ret = ctx->cipher_info->base->xts_func(ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, + input, output); if (ret != 0) { return (ret); } @@ -869,8 +869,8 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t* ctx, unsigned char* output, return (0); } - ctx->add_padding( - ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx), ctx->unprocessed_len); + ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx), + ctx->unprocessed_len); } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) { /* * For decrypt operations, expect a full block, @@ -986,8 +986,8 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t* ctx, unsigned char* tag, size_t output_length; /* The code here doesn't yet support alternative implementations * that can delay up to a block of output. */ - return (mbedtls_gcm_finish( - (mbedtls_gcm_context*)ctx->cipher_ctx, NULL, 0, &output_length, tag, tag_len)); + return (mbedtls_gcm_finish((mbedtls_gcm_context*)ctx->cipher_ctx, NULL, 0, &output_length, + tag, tag_len)); } #endif @@ -1004,8 +1004,8 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t* ctx, unsigned char* tag, return (0); } -int mbedtls_cipher_check_tag( - mbedtls_cipher_context_t* ctx, const unsigned char* tag, size_t tag_len) { +int mbedtls_cipher_check_tag(mbedtls_cipher_context_t* ctx, const unsigned char* tag, + size_t tag_len) { unsigned char check_tag[16]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -1201,8 +1201,8 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t* ctx, const unsi #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) { *olen = ilen; - return (mbedtls_ccm_encrypt_and_tag( - ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, tag, tag_len)); + return (mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, + output, tag, tag_len)); } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) @@ -1213,8 +1213,8 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t* ctx, const unsi } *olen = ilen; - return (mbedtls_chachapoly_encrypt_and_tag( - ctx->cipher_ctx, ilen, iv, ad, ad_len, input, output, tag)); + return (mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, ad, ad_len, input, + output, tag)); } #endif /* MBEDTLS_CHACHAPOLY_C */ @@ -1274,8 +1274,8 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t* ctx, const unsi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; - ret = mbedtls_ccm_auth_decrypt( - ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, tag, tag_len); + ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, + tag, tag_len); if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; @@ -1293,8 +1293,8 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t* ctx, const unsi } *olen = ilen; - ret = mbedtls_chachapoly_auth_decrypt( - ctx->cipher_ctx, ilen, iv, ad, ad_len, tag, input, output); + ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen, iv, ad, ad_len, tag, input, + output); if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; @@ -1347,8 +1347,8 @@ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t* ctx, const unsigne if (output_len < ilen + tag_len) return (MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA); - int ret = mbedtls_cipher_aead_encrypt( - ctx, iv, iv_len, ad, ad_len, input, ilen, output, olen, output + ilen, tag_len); + int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len, input, ilen, output, olen, + output + ilen, tag_len); *olen += tag_len; return (ret); #else diff --git a/extension/httpfs/third_party/mbedtls/library/cipher_wrap.cpp b/extension/httpfs/third_party/mbedtls/library/cipher_wrap.cpp index 3b7b86399ea..7de01cc3ac6 100644 --- a/extension/httpfs/third_party/mbedtls/library/cipher_wrap.cpp +++ b/extension/httpfs/third_party/mbedtls/library/cipher_wrap.cpp @@ -112,8 +112,8 @@ static void ccm_ctx_free(void* ctx) { #if defined(MBEDTLS_AES_C) -static int aes_crypt_ecb_wrap( - void* ctx, mbedtls_operation_t operation, const unsigned char* input, unsigned char* output) { +static int aes_crypt_ecb_wrap(void* ctx, mbedtls_operation_t operation, const unsigned char* input, + unsigned char* output) { return mbedtls_aes_crypt_ecb((mbedtls_aes_context*)ctx, operation, input, output); } @@ -127,8 +127,8 @@ static int aes_crypt_cbc_wrap(void* ctx, mbedtls_operation_t operation, size_t l #if defined(MBEDTLS_CIPHER_MODE_CFB) static int aes_crypt_cfb128_wrap(void* ctx, mbedtls_operation_t operation, size_t length, size_t* iv_off, unsigned char* iv, const unsigned char* input, unsigned char* output) { - return mbedtls_aes_crypt_cfb128( - (mbedtls_aes_context*)ctx, operation, length, iv_off, iv, input, output); + return mbedtls_aes_crypt_cfb128((mbedtls_aes_context*)ctx, operation, length, iv_off, iv, input, + output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ @@ -143,8 +143,8 @@ static int aes_crypt_ofb_wrap(void* ctx, size_t length, size_t* iv_off, unsigned static int aes_crypt_ctr_wrap(void* ctx, size_t length, size_t* nc_off, unsigned char* nonce_counter, unsigned char* stream_block, const unsigned char* input, unsigned char* output) { - return mbedtls_aes_crypt_ctr( - (mbedtls_aes_context*)ctx, length, nc_off, nonce_counter, stream_block, input, output); + return mbedtls_aes_crypt_ctr((mbedtls_aes_context*)ctx, length, nc_off, nonce_counter, + stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ @@ -214,57 +214,57 @@ static const mbedtls_cipher_base_t aes_info = {MBEDTLS_CIPHER_ID_AES, aes_crypt_ #endif aes_setkey_enc_wrap, aes_setkey_dec_wrap, aes_ctx_alloc, aes_ctx_free}; -static const mbedtls_cipher_info_t aes_128_ecb_info = { - MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_MODE_ECB, 128, "AES-128-ECB", 0, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_128_ecb_info = {MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_MODE_ECB, + 128, "AES-128-ECB", 0, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_192_ecb_info = { - MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_MODE_ECB, 192, "AES-192-ECB", 0, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_192_ecb_info = {MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_MODE_ECB, + 192, "AES-192-ECB", 0, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_256_ecb_info = { - MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_MODE_ECB, 256, "AES-256-ECB", 0, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_256_ecb_info = {MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_MODE_ECB, + 256, "AES-256-ECB", 0, 0, 16, &aes_info}; #if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t aes_128_cbc_info = { - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MODE_CBC, 128, "AES-128-CBC", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_128_cbc_info = {MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MODE_CBC, + 128, "AES-128-CBC", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_192_cbc_info = { - MBEDTLS_CIPHER_AES_192_CBC, MBEDTLS_MODE_CBC, 192, "AES-192-CBC", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_192_cbc_info = {MBEDTLS_CIPHER_AES_192_CBC, MBEDTLS_MODE_CBC, + 192, "AES-192-CBC", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_256_cbc_info = { - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MODE_CBC, 256, "AES-256-CBC", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_256_cbc_info = {MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MODE_CBC, + 256, "AES-256-CBC", 16, 0, 16, &aes_info}; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t aes_128_cfb128_info = { - MBEDTLS_CIPHER_AES_128_CFB128, MBEDTLS_MODE_CFB, 128, "AES-128-CFB128", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_128_cfb128_info = {MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, 128, "AES-128-CFB128", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_192_cfb128_info = { - MBEDTLS_CIPHER_AES_192_CFB128, MBEDTLS_MODE_CFB, 192, "AES-192-CFB128", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_192_cfb128_info = {MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, 192, "AES-192-CFB128", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_256_cfb128_info = { - MBEDTLS_CIPHER_AES_256_CFB128, MBEDTLS_MODE_CFB, 256, "AES-256-CFB128", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_256_cfb128_info = {MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, 256, "AES-256-CFB128", 16, 0, 16, &aes_info}; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) -static const mbedtls_cipher_info_t aes_128_ofb_info = { - MBEDTLS_CIPHER_AES_128_OFB, MBEDTLS_MODE_OFB, 128, "AES-128-OFB", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_128_ofb_info = {MBEDTLS_CIPHER_AES_128_OFB, MBEDTLS_MODE_OFB, + 128, "AES-128-OFB", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_192_ofb_info = { - MBEDTLS_CIPHER_AES_192_OFB, MBEDTLS_MODE_OFB, 192, "AES-192-OFB", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_192_ofb_info = {MBEDTLS_CIPHER_AES_192_OFB, MBEDTLS_MODE_OFB, + 192, "AES-192-OFB", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_256_ofb_info = { - MBEDTLS_CIPHER_AES_256_OFB, MBEDTLS_MODE_OFB, 256, "AES-256-OFB", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_256_ofb_info = {MBEDTLS_CIPHER_AES_256_OFB, MBEDTLS_MODE_OFB, + 256, "AES-256-OFB", 16, 0, 16, &aes_info}; #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t aes_128_ctr_info = { - MBEDTLS_CIPHER_AES_128_CTR, MBEDTLS_MODE_CTR, 128, "AES-128-CTR", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_128_ctr_info = {MBEDTLS_CIPHER_AES_128_CTR, MBEDTLS_MODE_CTR, + 128, "AES-128-CTR", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_192_ctr_info = { - MBEDTLS_CIPHER_AES_192_CTR, MBEDTLS_MODE_CTR, 192, "AES-192-CTR", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_192_ctr_info = {MBEDTLS_CIPHER_AES_192_CTR, MBEDTLS_MODE_CTR, + 192, "AES-192-CTR", 16, 0, 16, &aes_info}; -static const mbedtls_cipher_info_t aes_256_ctr_info = { - MBEDTLS_CIPHER_AES_256_CTR, MBEDTLS_MODE_CTR, 256, "AES-256-CTR", 16, 0, 16, &aes_info}; +static const mbedtls_cipher_info_t aes_256_ctr_info = {MBEDTLS_CIPHER_AES_256_CTR, MBEDTLS_MODE_CTR, + 256, "AES-256-CTR", 16, 0, 16, &aes_info}; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) @@ -318,11 +318,11 @@ static const mbedtls_cipher_base_t xts_aes_info = {MBEDTLS_CIPHER_ID_AES, NULL, #endif xts_aes_setkey_enc_wrap, xts_aes_setkey_dec_wrap, xts_aes_ctx_alloc, xts_aes_ctx_free}; -static const mbedtls_cipher_info_t aes_128_xts_info = { - MBEDTLS_CIPHER_AES_128_XTS, MBEDTLS_MODE_XTS, 256, "AES-128-XTS", 16, 0, 16, &xts_aes_info}; +static const mbedtls_cipher_info_t aes_128_xts_info = {MBEDTLS_CIPHER_AES_128_XTS, MBEDTLS_MODE_XTS, + 256, "AES-128-XTS", 16, 0, 16, &xts_aes_info}; -static const mbedtls_cipher_info_t aes_256_xts_info = { - MBEDTLS_CIPHER_AES_256_XTS, MBEDTLS_MODE_XTS, 512, "AES-256-XTS", 16, 0, 16, &xts_aes_info}; +static const mbedtls_cipher_info_t aes_256_xts_info = {MBEDTLS_CIPHER_AES_256_XTS, MBEDTLS_MODE_XTS, + 512, "AES-256-XTS", 16, 0, 16, &xts_aes_info}; #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_GCM_C) @@ -425,24 +425,24 @@ static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = { #if defined(MBEDTLS_CAMELLIA_C) -static int camellia_crypt_ecb_wrap( - void* ctx, mbedtls_operation_t operation, const unsigned char* input, unsigned char* output) { +static int camellia_crypt_ecb_wrap(void* ctx, mbedtls_operation_t operation, + const unsigned char* input, unsigned char* output) { return mbedtls_camellia_crypt_ecb((mbedtls_camellia_context*)ctx, operation, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int camellia_crypt_cbc_wrap(void* ctx, mbedtls_operation_t operation, size_t length, unsigned char* iv, const unsigned char* input, unsigned char* output) { - return mbedtls_camellia_crypt_cbc( - (mbedtls_camellia_context*)ctx, operation, length, iv, input, output); + return mbedtls_camellia_crypt_cbc((mbedtls_camellia_context*)ctx, operation, length, iv, input, + output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int camellia_crypt_cfb128_wrap(void* ctx, mbedtls_operation_t operation, size_t length, size_t* iv_off, unsigned char* iv, const unsigned char* input, unsigned char* output) { - return mbedtls_camellia_crypt_cfb128( - (mbedtls_camellia_context*)ctx, operation, length, iv_off, iv, input, output); + return mbedtls_camellia_crypt_cfb128((mbedtls_camellia_context*)ctx, operation, length, iv_off, + iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ @@ -450,8 +450,8 @@ static int camellia_crypt_cfb128_wrap(void* ctx, mbedtls_operation_t operation, static int camellia_crypt_ctr_wrap(void* ctx, size_t length, size_t* nc_off, unsigned char* nonce_counter, unsigned char* stream_block, const unsigned char* input, unsigned char* output) { - return mbedtls_camellia_crypt_ctr( - (mbedtls_camellia_context*)ctx, length, nc_off, nonce_counter, stream_block, input, output); + return mbedtls_camellia_crypt_ctr((mbedtls_camellia_context*)ctx, length, nc_off, nonce_counter, + stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ @@ -546,8 +546,8 @@ static const mbedtls_cipher_info_t camellia_256_ctr_info = {MBEDTLS_CIPHER_CAMEL #if defined(MBEDTLS_GCM_C) static int gcm_camellia_setkey_wrap(void* ctx, const unsigned char* key, unsigned int key_bitlen) { - return mbedtls_gcm_setkey( - (mbedtls_gcm_context*)ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, key_bitlen); + return mbedtls_gcm_setkey((mbedtls_gcm_context*)ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, + key_bitlen); } static const mbedtls_cipher_base_t gcm_camellia_info = { @@ -592,8 +592,8 @@ static const mbedtls_cipher_info_t camellia_256_gcm_info = {MBEDTLS_CIPHER_CAMEL #if defined(MBEDTLS_CCM_C) static int ccm_camellia_setkey_wrap(void* ctx, const unsigned char* key, unsigned int key_bitlen) { - return mbedtls_ccm_setkey( - (mbedtls_ccm_context*)ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, key_bitlen); + return mbedtls_ccm_setkey((mbedtls_ccm_context*)ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, + key_bitlen); } static const mbedtls_cipher_base_t ccm_camellia_info = { @@ -652,8 +652,8 @@ static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = { #if defined(MBEDTLS_ARIA_C) -static int aria_crypt_ecb_wrap( - void* ctx, mbedtls_operation_t operation, const unsigned char* input, unsigned char* output) { +static int aria_crypt_ecb_wrap(void* ctx, mbedtls_operation_t operation, const unsigned char* input, + unsigned char* output) { (void)operation; return mbedtls_aria_crypt_ecb((mbedtls_aria_context*)ctx, input, output); } @@ -668,8 +668,8 @@ static int aria_crypt_cbc_wrap(void* ctx, mbedtls_operation_t operation, size_t #if defined(MBEDTLS_CIPHER_MODE_CFB) static int aria_crypt_cfb128_wrap(void* ctx, mbedtls_operation_t operation, size_t length, size_t* iv_off, unsigned char* iv, const unsigned char* input, unsigned char* output) { - return mbedtls_aria_crypt_cfb128( - (mbedtls_aria_context*)ctx, operation, length, iv_off, iv, input, output); + return mbedtls_aria_crypt_cfb128((mbedtls_aria_context*)ctx, operation, length, iv_off, iv, + input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ @@ -677,8 +677,8 @@ static int aria_crypt_cfb128_wrap(void* ctx, mbedtls_operation_t operation, size static int aria_crypt_ctr_wrap(void* ctx, size_t length, size_t* nc_off, unsigned char* nonce_counter, unsigned char* stream_block, const unsigned char* input, unsigned char* output) { - return mbedtls_aria_crypt_ctr( - (mbedtls_aria_context*)ctx, length, nc_off, nonce_counter, stream_block, input, output); + return mbedtls_aria_crypt_ctr((mbedtls_aria_context*)ctx, length, nc_off, nonce_counter, + stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ @@ -728,24 +728,24 @@ static const mbedtls_cipher_base_t aria_info = {MBEDTLS_CIPHER_ID_ARIA, aria_cry #endif aria_setkey_enc_wrap, aria_setkey_dec_wrap, aria_ctx_alloc, aria_ctx_free}; -static const mbedtls_cipher_info_t aria_128_ecb_info = { - MBEDTLS_CIPHER_ARIA_128_ECB, MBEDTLS_MODE_ECB, 128, "ARIA-128-ECB", 0, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_128_ecb_info = {MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, 128, "ARIA-128-ECB", 0, 0, 16, &aria_info}; -static const mbedtls_cipher_info_t aria_192_ecb_info = { - MBEDTLS_CIPHER_ARIA_192_ECB, MBEDTLS_MODE_ECB, 192, "ARIA-192-ECB", 0, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_192_ecb_info = {MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, 192, "ARIA-192-ECB", 0, 0, 16, &aria_info}; -static const mbedtls_cipher_info_t aria_256_ecb_info = { - MBEDTLS_CIPHER_ARIA_256_ECB, MBEDTLS_MODE_ECB, 256, "ARIA-256-ECB", 0, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_256_ecb_info = {MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, 256, "ARIA-256-ECB", 0, 0, 16, &aria_info}; #if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t aria_128_cbc_info = { - MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MODE_CBC, 128, "ARIA-128-CBC", 16, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_128_cbc_info = {MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, 128, "ARIA-128-CBC", 16, 0, 16, &aria_info}; -static const mbedtls_cipher_info_t aria_192_cbc_info = { - MBEDTLS_CIPHER_ARIA_192_CBC, MBEDTLS_MODE_CBC, 192, "ARIA-192-CBC", 16, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_192_cbc_info = {MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, 192, "ARIA-192-CBC", 16, 0, 16, &aria_info}; -static const mbedtls_cipher_info_t aria_256_cbc_info = { - MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MODE_CBC, 256, "ARIA-256-CBC", 16, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_256_cbc_info = {MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, 256, "ARIA-256-CBC", 16, 0, 16, &aria_info}; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) @@ -760,14 +760,14 @@ static const mbedtls_cipher_info_t aria_256_cfb128_info = {MBEDTLS_CIPHER_ARIA_2 #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t aria_128_ctr_info = { - MBEDTLS_CIPHER_ARIA_128_CTR, MBEDTLS_MODE_CTR, 128, "ARIA-128-CTR", 16, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_128_ctr_info = {MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, 128, "ARIA-128-CTR", 16, 0, 16, &aria_info}; -static const mbedtls_cipher_info_t aria_192_ctr_info = { - MBEDTLS_CIPHER_ARIA_192_CTR, MBEDTLS_MODE_CTR, 192, "ARIA-192-CTR", 16, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_192_ctr_info = {MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, 192, "ARIA-192-CTR", 16, 0, 16, &aria_info}; -static const mbedtls_cipher_info_t aria_256_ctr_info = { - MBEDTLS_CIPHER_ARIA_256_CTR, MBEDTLS_MODE_CTR, 256, "ARIA-256-CTR", 16, 0, 16, &aria_info}; +static const mbedtls_cipher_info_t aria_256_ctr_info = {MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, 256, "ARIA-256-CTR", 16, 0, 16, &aria_info}; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_GCM_C) @@ -870,14 +870,14 @@ static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = { #if defined(MBEDTLS_DES_C) -static int des_crypt_ecb_wrap( - void* ctx, mbedtls_operation_t operation, const unsigned char* input, unsigned char* output) { +static int des_crypt_ecb_wrap(void* ctx, mbedtls_operation_t operation, const unsigned char* input, + unsigned char* output) { ((void)operation); return mbedtls_des_crypt_ecb((mbedtls_des_context*)ctx, input, output); } -static int des3_crypt_ecb_wrap( - void* ctx, mbedtls_operation_t operation, const unsigned char* input, unsigned char* output) { +static int des3_crypt_ecb_wrap(void* ctx, mbedtls_operation_t operation, const unsigned char* input, + unsigned char* output) { ((void)operation); return mbedtls_des3_crypt_ecb((mbedtls_des3_context*)ctx, input, output); } @@ -1064,8 +1064,8 @@ static int chacha20_setkey_wrap(void* ctx, const unsigned char* key, unsigned in return (0); } -static int chacha20_stream_wrap( - void* ctx, size_t length, const unsigned char* input, unsigned char* output) { +static int chacha20_stream_wrap(void* ctx, size_t length, const unsigned char* input, + unsigned char* output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chacha20_update(ctx, length, input, output); @@ -1112,8 +1112,8 @@ static const mbedtls_cipher_base_t chacha20_base_info = {MBEDTLS_CIPHER_ID_CHACH chacha20_stream_wrap, #endif chacha20_setkey_wrap, chacha20_setkey_wrap, chacha20_ctx_alloc, chacha20_ctx_free}; -static const mbedtls_cipher_info_t chacha20_info = { - MBEDTLS_CIPHER_CHACHA20, MBEDTLS_MODE_STREAM, 256, "CHACHA20", 12, 0, 1, &chacha20_base_info}; +static const mbedtls_cipher_info_t chacha20_info = {MBEDTLS_CIPHER_CHACHA20, MBEDTLS_MODE_STREAM, + 256, "CHACHA20", 12, 0, 1, &chacha20_base_info}; #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) @@ -1170,8 +1170,8 @@ static const mbedtls_cipher_info_t chachapoly_info = {MBEDTLS_CIPHER_CHACHA20_PO #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) -static int null_crypt_stream( - void* ctx, size_t length, const unsigned char* input, unsigned char* output) { +static int null_crypt_stream(void* ctx, size_t length, const unsigned char* input, + unsigned char* output) { ((void)ctx); memmove(output, input, length); return (0); @@ -1214,8 +1214,8 @@ static const mbedtls_cipher_base_t null_base_info = {MBEDTLS_CIPHER_ID_NULL, NUL #endif null_setkey, null_setkey, null_ctx_alloc, null_ctx_free}; -static const mbedtls_cipher_info_t null_cipher_info = { - MBEDTLS_CIPHER_NULL, MBEDTLS_MODE_STREAM, 0, "NULL", 0, 0, 1, &null_base_info}; +static const mbedtls_cipher_info_t null_cipher_info = {MBEDTLS_CIPHER_NULL, MBEDTLS_MODE_STREAM, 0, + "NULL", 0, 0, 1, &null_base_info}; #endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ #if defined(MBEDTLS_NIST_KW_C) @@ -1234,13 +1234,13 @@ static void kw_ctx_free(void* ctx) { } static int kw_aes_setkey_wrap(void* ctx, const unsigned char* key, unsigned int key_bitlen) { - return mbedtls_nist_kw_setkey( - (mbedtls_nist_kw_context*)ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1); + return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context*)ctx, MBEDTLS_CIPHER_ID_AES, key, + key_bitlen, 1); } static int kw_aes_setkey_unwrap(void* ctx, const unsigned char* key, unsigned int key_bitlen) { - return mbedtls_nist_kw_setkey( - (mbedtls_nist_kw_context*)ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0); + return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context*)ctx, MBEDTLS_CIPHER_ID_AES, key, + key_bitlen, 0); } static const mbedtls_cipher_base_t kw_aes_info = { @@ -1270,23 +1270,23 @@ static const mbedtls_cipher_base_t kw_aes_info = { kw_ctx_free, }; -static const mbedtls_cipher_info_t aes_128_nist_kw_info = { - MBEDTLS_CIPHER_AES_128_KW, MBEDTLS_MODE_KW, 128, "AES-128-KW", 0, 0, 16, &kw_aes_info}; +static const mbedtls_cipher_info_t aes_128_nist_kw_info = {MBEDTLS_CIPHER_AES_128_KW, + MBEDTLS_MODE_KW, 128, "AES-128-KW", 0, 0, 16, &kw_aes_info}; -static const mbedtls_cipher_info_t aes_192_nist_kw_info = { - MBEDTLS_CIPHER_AES_192_KW, MBEDTLS_MODE_KW, 192, "AES-192-KW", 0, 0, 16, &kw_aes_info}; +static const mbedtls_cipher_info_t aes_192_nist_kw_info = {MBEDTLS_CIPHER_AES_192_KW, + MBEDTLS_MODE_KW, 192, "AES-192-KW", 0, 0, 16, &kw_aes_info}; -static const mbedtls_cipher_info_t aes_256_nist_kw_info = { - MBEDTLS_CIPHER_AES_256_KW, MBEDTLS_MODE_KW, 256, "AES-256-KW", 0, 0, 16, &kw_aes_info}; +static const mbedtls_cipher_info_t aes_256_nist_kw_info = {MBEDTLS_CIPHER_AES_256_KW, + MBEDTLS_MODE_KW, 256, "AES-256-KW", 0, 0, 16, &kw_aes_info}; -static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { - MBEDTLS_CIPHER_AES_128_KWP, MBEDTLS_MODE_KWP, 128, "AES-128-KWP", 0, 0, 16, &kw_aes_info}; +static const mbedtls_cipher_info_t aes_128_nist_kwp_info = {MBEDTLS_CIPHER_AES_128_KWP, + MBEDTLS_MODE_KWP, 128, "AES-128-KWP", 0, 0, 16, &kw_aes_info}; -static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { - MBEDTLS_CIPHER_AES_192_KWP, MBEDTLS_MODE_KWP, 192, "AES-192-KWP", 0, 0, 16, &kw_aes_info}; +static const mbedtls_cipher_info_t aes_192_nist_kwp_info = {MBEDTLS_CIPHER_AES_192_KWP, + MBEDTLS_MODE_KWP, 192, "AES-192-KWP", 0, 0, 16, &kw_aes_info}; -static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { - MBEDTLS_CIPHER_AES_256_KWP, MBEDTLS_MODE_KWP, 256, "AES-256-KWP", 0, 0, 16, &kw_aes_info}; +static const mbedtls_cipher_info_t aes_256_nist_kwp_info = {MBEDTLS_CIPHER_AES_256_KWP, + MBEDTLS_MODE_KWP, 256, "AES-256-KWP", 0, 0, 16, &kw_aes_info}; #endif /* MBEDTLS_NIST_KW_C */ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { diff --git a/extension/httpfs/third_party/mbedtls/library/cipher_wrap.h b/extension/httpfs/third_party/mbedtls/library/cipher_wrap.h index ce7a08f0505..5da60eba5c0 100644 --- a/extension/httpfs/third_party/mbedtls/library/cipher_wrap.h +++ b/extension/httpfs/third_party/mbedtls/library/cipher_wrap.h @@ -43,8 +43,8 @@ struct mbedtls_cipher_base_t { mbedtls_cipher_id_t cipher; /** Encrypt using ECB */ - int (*ecb_func)( - void* ctx, mbedtls_operation_t mode, const unsigned char* input, unsigned char* output); + int (*ecb_func)(void* ctx, mbedtls_operation_t mode, const unsigned char* input, + unsigned char* output); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** Encrypt using CBC */ diff --git a/extension/httpfs/third_party/mbedtls/library/common.h b/extension/httpfs/third_party/mbedtls/library/common.h index bf39453a222..1fe2fe6af06 100644 --- a/extension/httpfs/third_party/mbedtls/library/common.h +++ b/extension/httpfs/third_party/mbedtls/library/common.h @@ -72,7 +72,7 @@ extern void (*mbedtls_test_hook_test_fail)(const char* test, int line, const cha * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th * byte from x, where byte 0 is the least significant byte. */ -#define MBEDTLS_BYTE_0(x) ((uint8_t)((x)&0xff)) +#define MBEDTLS_BYTE_0(x) ((uint8_t)((x) & 0xff)) #define MBEDTLS_BYTE_1(x) ((uint8_t)(((x) >> 8) & 0xff)) #define MBEDTLS_BYTE_2(x) ((uint8_t)(((x) >> 16) & 0xff)) #define MBEDTLS_BYTE_3(x) ((uint8_t)(((x) >> 24) & 0xff)) diff --git a/extension/httpfs/third_party/mbedtls/library/constant_time.cpp b/extension/httpfs/third_party/mbedtls/library/constant_time.cpp index ede6c964764..d554e3e657e 100644 --- a/extension/httpfs/third_party/mbedtls/library/constant_time.cpp +++ b/extension/httpfs/third_party/mbedtls/library/constant_time.cpp @@ -154,8 +154,8 @@ size_t mbedtls_ct_size_mask_ge(size_t x, size_t y) { * Constant flow with respect to c. */ MBEDTLS_STATIC_TESTABLE -unsigned char mbedtls_ct_uchar_mask_of_range( - unsigned char low, unsigned char high, unsigned char c) { +unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low, unsigned char high, + unsigned char c) { /* low_mask is: 0 if low <= c, 0x...ff if low > c */ unsigned low_mask = ((unsigned)c - low) >> 8; /* high_mask is: 0 if c <= high, 0x...ff if c > high */ @@ -276,8 +276,8 @@ static int mbedtls_ct_cond_select_sign(unsigned char condition, int if1, int if0 return ((int)ur - 1); } -void mbedtls_ct_mpi_uint_cond_assign( - size_t n, mbedtls_mpi_uint* dest, const mbedtls_mpi_uint* src, unsigned char condition) { +void mbedtls_ct_mpi_uint_cond_assign(size_t n, mbedtls_mpi_uint* dest, const mbedtls_mpi_uint* src, + unsigned char condition) { size_t i; /* MSVC has a warning about unary minus on unsigned integer types, @@ -374,8 +374,8 @@ static void mbedtls_ct_mem_move_to_left(void* start, size_t total, size_t offset #if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) -void mbedtls_ct_memcpy_if_eq( - unsigned char* dest, const unsigned char* src, size_t len, size_t c1, size_t c2) { +void mbedtls_ct_memcpy_if_eq(unsigned char* dest, const unsigned char* src, size_t len, size_t c1, + size_t c2) { /* mask = c1 == c2 ? 0xff : 0x00 */ const size_t equal = mbedtls_ct_size_bool_eq(c1, c2); const unsigned char mask = (unsigned char)mbedtls_ct_size_mask(equal); @@ -609,8 +609,8 @@ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi* X, const mbedtls_mpi* Y, unsigned* #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) -int mbedtls_ct_rsaes_pkcs1_v15_unpadding( - unsigned char* input, size_t ilen, unsigned char* output, size_t output_max_len, size_t* olen) { +int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char* input, size_t ilen, unsigned char* output, + size_t output_max_len, size_t* olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, plaintext_max_size; @@ -689,8 +689,8 @@ int mbedtls_ct_rsaes_pkcs1_v15_unpadding( * Copy anyway to avoid revealing the length through timing, because * revealing the length is as bad as revealing the padding validity * for a Bleichenbacher attack. */ - plaintext_size = mbedtls_ct_uint_if( - output_too_large, (unsigned)plaintext_max_size, (unsigned)plaintext_size); + plaintext_size = mbedtls_ct_uint_if(output_too_large, (unsigned)plaintext_max_size, + (unsigned)plaintext_size); /* Move the plaintext to the leftmost position where it can start in * the working buffer, i.e. make it start plaintext_max_size from @@ -698,8 +698,8 @@ int mbedtls_ct_rsaes_pkcs1_v15_unpadding( * does not depend on the plaintext size. After this move, the * starting location of the plaintext is no longer sensitive * information. */ - mbedtls_ct_mem_move_to_left( - input + ilen - plaintext_max_size, plaintext_max_size, plaintext_max_size - plaintext_size); + mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size, plaintext_max_size, + plaintext_max_size - plaintext_size); /* Finally copy the decrypted plaintext plus trailing zeros into the output * buffer. If output_max_len is 0, then output may be an invalid pointer diff --git a/extension/httpfs/third_party/mbedtls/library/constant_time_internal.h b/extension/httpfs/third_party/mbedtls/library/constant_time_internal.h index 17d7d4ddf88..30eeccb6d19 100644 --- a/extension/httpfs/third_party/mbedtls/library/constant_time_internal.h +++ b/extension/httpfs/third_party/mbedtls/library/constant_time_internal.h @@ -154,8 +154,8 @@ unsigned mbedtls_ct_uint_if(unsigned condition, unsigned if1, unsigned if0); * initialized MPI. * \param condition Condition to test, must be 0 or 1. */ -void mbedtls_ct_mpi_uint_cond_assign( - size_t n, mbedtls_mpi_uint* dest, const mbedtls_mpi_uint* src, unsigned char condition); +void mbedtls_ct_mpi_uint_cond_assign(size_t n, mbedtls_mpi_uint* dest, const mbedtls_mpi_uint* src, + unsigned char condition); #endif /* MBEDTLS_BIGNUM_C */ @@ -201,8 +201,8 @@ signed char mbedtls_ct_base64_dec_value(unsigned char c); * \param c1 The first value to analyze in the condition. * \param c2 The second value to analyze in the condition. */ -void mbedtls_ct_memcpy_if_eq( - unsigned char* dest, const unsigned char* src, size_t len, size_t c1, size_t c2); +void mbedtls_ct_memcpy_if_eq(unsigned char* dest, const unsigned char* src, size_t len, size_t c1, + size_t c2); /** Copy data from a secret position with constant flow. * @@ -296,8 +296,8 @@ int mbedtls_ct_hmac(mbedtls_md_context_t* ctx, const unsigned char* add_data, si * \return #MBEDTLS_ERR_RSA_INVALID_PADDING * The input doesn't contain properly formatted padding. */ -int mbedtls_ct_rsaes_pkcs1_v15_unpadding( - unsigned char* input, size_t ilen, unsigned char* output, size_t output_max_len, size_t* olen); +int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char* input, size_t ilen, unsigned char* output, + size_t output_max_len, size_t* olen); #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ diff --git a/extension/httpfs/third_party/mbedtls/library/constant_time_invasive.h b/extension/httpfs/third_party/mbedtls/library/constant_time_invasive.h index fdb4c285db4..9dcd31bb45e 100644 --- a/extension/httpfs/third_party/mbedtls/library/constant_time_invasive.h +++ b/extension/httpfs/third_party/mbedtls/library/constant_time_invasive.h @@ -42,8 +42,8 @@ * * \return All-bits-one if \p low <= \p c <= \p high, otherwise zero. */ -unsigned char mbedtls_ct_uchar_mask_of_range( - unsigned char low, unsigned char high, unsigned char c); +unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low, unsigned char high, + unsigned char c); #endif /* MBEDTLS_TEST_HOOKS */ diff --git a/extension/httpfs/third_party/mbedtls/library/entropy.cpp b/extension/httpfs/third_party/mbedtls/library/entropy.cpp index b3a1b52bfa0..533c2935462 100644 --- a/extension/httpfs/third_party/mbedtls/library/entropy.cpp +++ b/extension/httpfs/third_party/mbedtls/library/entropy.cpp @@ -37,12 +37,12 @@ #endif #if defined(MBEDTLS_SELF_TEST) -//#if defined(MBEDTLS_PLATFORM_C) -//#include "mbedtls/platform.h" -//#else -//#include -//#define mbedtls_printf printf -//#endif /* MBEDTLS_PLATFORM_C */ +// #if defined(MBEDTLS_PLATFORM_C) +// #include "mbedtls/platform.h" +// #else +// #include +// #define mbedtls_printf printf +// #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ @@ -75,8 +75,8 @@ void mbedtls_entropy_init(mbedtls_entropy_context* ctx) { MBEDTLS_ENTROPY_SOURCE_STRONG); #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) - mbedtls_entropy_add_source( - ctx, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG); + mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG); ctx->initial_entropy_run = 0; #endif #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ @@ -138,8 +138,8 @@ int mbedtls_entropy_add_source(mbedtls_entropy_context* ctx, mbedtls_entropy_f_s /* * Entropy accumulator update */ -static int entropy_update( - mbedtls_entropy_context* ctx, unsigned char source_id, const unsigned char* data, size_t len) { +static int entropy_update(mbedtls_entropy_context* ctx, unsigned char source_id, + const unsigned char* data, size_t len) { unsigned char header[2]; unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = len; @@ -190,8 +190,8 @@ static int entropy_update( return (ret); } -int mbedtls_entropy_update_manual( - mbedtls_entropy_context* ctx, const unsigned char* data, size_t len) { +int mbedtls_entropy_update_manual(mbedtls_entropy_context* ctx, const unsigned char* data, + size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) @@ -230,8 +230,8 @@ static int entropy_gather_internal(mbedtls_entropy_context* ctx) { have_one_strong = 1; olen = 0; - if ((ret = ctx->source[i].f_source( - ctx->source[i].p_source, buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) { + if ((ret = ctx->source[i].f_source(ctx->source[i].p_source, buf, MBEDTLS_ENTROPY_MAX_GATHER, + &olen)) != 0) { goto cleanup; } @@ -594,8 +594,8 @@ int mbedtls_entropy_self_test(int verbose) { if ((ret = mbedtls_entropy_gather(&ctx)) != 0) goto cleanup; - ret = mbedtls_entropy_add_source( - &ctx, entropy_dummy_source, NULL, 16, MBEDTLS_ENTROPY_SOURCE_WEAK); + ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK); if (ret != 0) goto cleanup; diff --git a/extension/httpfs/third_party/mbedtls/library/gcm.cpp b/extension/httpfs/third_party/mbedtls/library/gcm.cpp index d7cf192d13a..cccba00af15 100644 --- a/extension/httpfs/third_party/mbedtls/library/gcm.cpp +++ b/extension/httpfs/third_party/mbedtls/library/gcm.cpp @@ -171,8 +171,8 @@ static const uint64_t last4[16] = {0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca * Sets output to x times H using the precomputed tables. * x and output are seen as elements of GF(2^128) as in [MGV]. */ -static void gcm_mult( - mbedtls_gcm_context* ctx, const unsigned char x[16], unsigned char output[16]) { +static void gcm_mult(mbedtls_gcm_context* ctx, const unsigned char x[16], + unsigned char output[16]) { int i = 0; unsigned char lo, hi, rem; uint64_t zh, zl; @@ -831,15 +831,15 @@ int mbedtls_gcm_self_test(int verbose) { if (ret != 0) goto exit; - ret = mbedtls_gcm_update_ad( - &ctx, additional_test_data[add_index_test_data[i]], add_len_test_data[i]); + ret = mbedtls_gcm_update_ad(&ctx, additional_test_data[add_index_test_data[i]], + add_len_test_data[i]); if (ret != 0) goto exit; if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; - ret = mbedtls_gcm_update( - &ctx, pt_test_data[pt_index_test_data[i]], 32, buf, sizeof(buf), &olen); + ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], 32, buf, + sizeof(buf), &olen); if (ret != 0) goto exit; if (olen != 32) @@ -888,8 +888,8 @@ int mbedtls_gcm_self_test(int verbose) { iv_len_test_data[i]); if (ret != 0) goto exit; - ret = mbedtls_gcm_update_ad( - &ctx, additional_test_data[add_index_test_data[i]], add_len_test_data[i]); + ret = mbedtls_gcm_update_ad(&ctx, additional_test_data[add_index_test_data[i]], + add_len_test_data[i]); if (ret != 0) goto exit; @@ -909,8 +909,8 @@ int mbedtls_gcm_self_test(int verbose) { if (olen != rest_len) goto exit; } else { - ret = mbedtls_gcm_update( - &ctx, ct_test_data[j * 6 + i], pt_len_test_data[i], buf, sizeof(buf), &olen); + ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], pt_len_test_data[i], buf, + sizeof(buf), &olen); if (ret != 0) goto exit; if (olen != pt_len_test_data[i]) diff --git a/extension/httpfs/third_party/mbedtls/library/md.cpp b/extension/httpfs/third_party/mbedtls/library/md.cpp index b8381bd6085..ee05ad9f7e0 100644 --- a/extension/httpfs/third_party/mbedtls/library/md.cpp +++ b/extension/httpfs/third_party/mbedtls/library/md.cpp @@ -316,14 +316,14 @@ int mbedtls_md_clone(mbedtls_md_context_t* dst, const mbedtls_md_context_t* src) #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: - mbedtls_sha256_clone( - (mbedtls_sha256_context*)dst->md_ctx, (mbedtls_sha256_context*)src->md_ctx); + mbedtls_sha256_clone((mbedtls_sha256_context*)dst->md_ctx, + (mbedtls_sha256_context*)src->md_ctx); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: - mbedtls_sha256_clone( - (mbedtls_sha256_context*)dst->md_ctx, (mbedtls_sha256_context*)src->md_ctx); + mbedtls_sha256_clone((mbedtls_sha256_context*)dst->md_ctx, + (mbedtls_sha256_context*)src->md_ctx); break; #endif #if defined(MBEDTLS_SHA384_C) @@ -511,8 +511,8 @@ int mbedtls_md_finish(mbedtls_md_context_t* ctx, unsigned char* output) { #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: - return (mbedtls_sha256_finish( - (mbedtls_sha256_context*)(mbedtls_sha256_context*)ctx->md_ctx, output)); + return (mbedtls_sha256_finish((mbedtls_sha256_context*)(mbedtls_sha256_context*)ctx->md_ctx, + output)); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: diff --git a/extension/httpfs/third_party/mbedtls/library/oid.cpp b/extension/httpfs/third_party/mbedtls/library/oid.cpp index 948d82e1240..1782225d719 100644 --- a/extension/httpfs/third_party/mbedtls/library/oid.cpp +++ b/extension/httpfs/third_party/mbedtls/library/oid.cpp @@ -225,8 +225,8 @@ static const oid_x520_attr_t oid_x520_attr_type[] = { "title", }, { - OID_DESCRIPTOR( - MBEDTLS_OID_AT_DN_QUALIFIER, "id-at-dnQualifier", "Distinguished Name qualifier"), + OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, "id-at-dnQualifier", + "Distinguished Name qualifier"), "dnQualifier", }, { @@ -242,8 +242,8 @@ static const oid_x520_attr_t oid_x520_attr_type[] = { "DC", }, { - OID_DESCRIPTOR( - MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, "id-at-uniqueIdentifier", "Unique Identifier"), + OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, "id-at-uniqueIdentifier", + "Unique Identifier"), "uniqueIdentifier", }, { @@ -252,8 +252,8 @@ static const oid_x520_attr_t oid_x520_attr_type[] = { }}; FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) -FN_OID_GET_ATTR1( - mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char*, short_name) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char*, + short_name) /* * For X509 extensions @@ -265,8 +265,8 @@ typedef struct { static const oid_x509_ext_t oid_x509_ext[] = { { - OID_DESCRIPTOR( - MBEDTLS_OID_BASIC_CONSTRAINTS, "id-ce-basicConstraints", "Basic Constraints"), + OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, "id-ce-basicConstraints", + "Basic Constraints"), MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, }, { @@ -282,13 +282,13 @@ static const oid_x509_ext_t oid_x509_ext[] = { MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, }, { - OID_DESCRIPTOR( - MBEDTLS_OID_NS_CERT_TYPE, "id-netscape-certtype", "Netscape Certificate Type"), + OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, "id-netscape-certtype", + "Netscape Certificate Type"), MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, }, { - OID_DESCRIPTOR( - MBEDTLS_OID_CERTIFICATE_POLICIES, "id-ce-certificatePolicies", "Certificate Policies"), + OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, "id-ce-certificatePolicies", + "Certificate Policies"), MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, }, { @@ -443,8 +443,8 @@ static const oid_sig_alg_t oid_sig_alg[] = { FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) #if !defined(MBEDTLS_X509_REMOVE_INFO) -FN_OID_GET_DESCRIPTOR_ATTR1( - mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char*, description) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char*, + description) #endif FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, @@ -482,8 +482,8 @@ static const oid_pk_alg_t oid_pk_alg[] = { FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR1( - mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, + pk_alg) #if defined(MBEDTLS_ECP_C) /* @@ -569,8 +569,8 @@ static const oid_ecp_grp_t oid_ecp_grp[] = { FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) -FN_OID_GET_OID_BY_ATTR1( - mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, + mbedtls_ecp_group_id, grp_id) #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_CIPHER_C) @@ -598,8 +598,8 @@ static const oid_cipher_alg_t oid_cipher_alg[] = { }; FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) -FN_OID_GET_ATTR1( - mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, + cipher_alg) #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_MD_C) @@ -662,8 +662,8 @@ static const oid_md_alg_t oid_md_alg[] = { FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) -FN_OID_GET_OID_BY_ATTR1( - mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, + md_alg) /* * For HMAC digestAlgorithm diff --git a/extension/httpfs/third_party/mbedtls/library/pem.cpp b/extension/httpfs/third_party/mbedtls/library/pem.cpp index c55fbd29f67..ea6532b6122 100644 --- a/extension/httpfs/third_party/mbedtls/library/pem.cpp +++ b/extension/httpfs/third_party/mbedtls/library/pem.cpp @@ -77,8 +77,8 @@ static int pem_get_iv(const unsigned char* s, unsigned char* iv, size_t iv_len) return (0); } -static int pem_pbkdf1( - unsigned char* key, size_t keylen, unsigned char* iv, const unsigned char* pwd, size_t pwdlen) { +static int pem_pbkdf1(unsigned char* key, size_t keylen, unsigned char* iv, + const unsigned char* pwd, size_t pwdlen) { mbedtls_md5_context md5_ctx; unsigned char md5sum[16]; size_t use_len; diff --git a/extension/httpfs/third_party/mbedtls/library/pk.cpp b/extension/httpfs/third_party/mbedtls/library/pk.cpp index 96f8d8149ad..a4c862862f8 100644 --- a/extension/httpfs/third_party/mbedtls/library/pk.cpp +++ b/extension/httpfs/third_party/mbedtls/library/pk.cpp @@ -272,8 +272,8 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context* ctx, mbedtls_md_type_t md_ if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) return (ret); - ret = ctx->pk_info->verify_rs_func( - ctx->pk_ctx, md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx); + ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx, md_alg, hash, hash_len, sig, sig_len, + rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) mbedtls_pk_restart_free(rs_ctx); @@ -390,8 +390,8 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context* ctx, mbedtls_md_type_t md_al if (ctx->pk_info->sign_func == NULL) return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - return (ctx->pk_info->sign_func( - ctx->pk_ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng)); + return (ctx->pk_info->sign_func(ctx->pk_ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, + f_rng, p_rng)); } /* @@ -400,8 +400,8 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context* ctx, mbedtls_md_type_t md_al int mbedtls_pk_sign(mbedtls_pk_context* ctx, mbedtls_md_type_t md_alg, const unsigned char* hash, size_t hash_len, unsigned char* sig, size_t sig_size, size_t* sig_len, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { - return (mbedtls_pk_sign_restartable( - ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, NULL)); + return (mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, + p_rng, NULL)); } /* diff --git a/extension/httpfs/third_party/mbedtls/library/pk_wrap.cpp b/extension/httpfs/third_party/mbedtls/library/pk_wrap.cpp index b5eb7edd9e6..ce2499a4fb5 100644 --- a/extension/httpfs/third_party/mbedtls/library/pk_wrap.cpp +++ b/extension/httpfs/third_party/mbedtls/library/pk_wrap.cpp @@ -139,12 +139,12 @@ static int rsa_encrypt_wrap(void* ctx, const unsigned char* input, size_t ilen, return (mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, ilen, input, output)); } -static int rsa_check_pair_wrap( - const void* pub, const void* prv, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +static int rsa_check_pair_wrap(const void* pub, const void* prv, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { (void)f_rng; (void)p_rng; - return (mbedtls_rsa_check_pub_priv( - (const mbedtls_rsa_context*)pub, (const mbedtls_rsa_context*)prv)); + return (mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context*)pub, + (const mbedtls_rsa_context*)prv)); } static void* rsa_alloc_wrap(void) { @@ -345,10 +345,10 @@ static int eckey_sign_rs_wrap(void* ctx, mbedtls_md_type_t md_alg, const unsigne #endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDSA_C */ -static int eckey_check_pair( - const void* pub, const void* prv, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { - return (mbedtls_ecp_check_pub_priv( - (const mbedtls_ecp_keypair*)pub, (const mbedtls_ecp_keypair*)prv, f_rng, p_rng)); +static int eckey_check_pair(const void* pub, const void* prv, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { + return (mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair*)pub, + (const mbedtls_ecp_keypair*)prv, f_rng, p_rng)); } static void* eckey_alloc_wrap(void) { @@ -431,8 +431,8 @@ static int ecdsa_can_do(mbedtls_pk_type_t type) { * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of * those integers and convert it to the fixed-length encoding expected by PSA. */ -static int extract_ecdsa_sig_int( - unsigned char** from, const unsigned char* end, unsigned char* to, size_t to_len) { +static int extract_ecdsa_sig_int(unsigned char** from, const unsigned char* end, unsigned char* to, + size_t to_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t unpadded_len, padding_len; @@ -461,13 +461,13 @@ static int extract_ecdsa_sig_int( * to a raw {r,s} buffer. Note: the provided sig buffer must be at least * twice as big as int_size. */ -static int extract_ecdsa_sig( - unsigned char** p, const unsigned char* end, unsigned char* sig, size_t int_size) { +static int extract_ecdsa_sig(unsigned char** p, const unsigned char* end, unsigned char* sig, + size_t int_size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t tmp_size; - if ((ret = mbedtls_asn1_get_tag( - p, end, &tmp_size, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) + if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) return (ret); /* Extract r */ @@ -567,8 +567,8 @@ static int ecdsa_verify_wrap(void* ctx, mbedtls_md_type_t md_alg, const unsigned static int ecdsa_sign_wrap(void* ctx, mbedtls_md_type_t md_alg, const unsigned char* hash, size_t hash_len, unsigned char* sig, size_t sig_size, size_t* sig_len, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { - return (mbedtls_ecdsa_write_signature( - (mbedtls_ecdsa_context*)ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng)); + return (mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context*)ctx, md_alg, hash, hash_len, sig, + sig_size, sig_len, f_rng, p_rng)); } #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -689,8 +689,8 @@ static int rsa_alt_decrypt_wrap(void* ctx, const unsigned char* input, size_t il } #if defined(MBEDTLS_RSA_C) -static int rsa_alt_check_pair( - const void* pub, const void* prv, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +static int rsa_alt_check_pair(const void* pub, const void* prv, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; unsigned char hash[32]; size_t sig_len = 0; @@ -860,8 +860,8 @@ static int pk_ecdsa_sig_asn1_from_psa(unsigned char* sig, size_t* sig_len, size_ MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len)); - MBEDTLS_ASN1_CHK_ADD( - len, mbedtls_asn1_write_tag(&p, sig, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag(&p, sig, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); memmove(sig, p, len); *sig_len = len; diff --git a/extension/httpfs/third_party/mbedtls/library/pk_wrap.h b/extension/httpfs/third_party/mbedtls/library/pk_wrap.h index 24d5355e11d..9e9b27d199d 100644 --- a/extension/httpfs/third_party/mbedtls/library/pk_wrap.h +++ b/extension/httpfs/third_party/mbedtls/library/pk_wrap.h @@ -68,8 +68,8 @@ struct mbedtls_pk_info_t { size_t* olen, size_t osize, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); /** Check public-private key pair */ - int (*check_pair_func)( - const void* pub, const void* prv, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); + int (*check_pair_func)(const void* pub, const void* prv, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng); /** Allocate a new context */ void* (*ctx_alloc_func)(void); diff --git a/extension/httpfs/third_party/mbedtls/library/pkparse.cpp b/extension/httpfs/third_party/mbedtls/library/pkparse.cpp index 249bca6c062..055d693cd22 100644 --- a/extension/httpfs/third_party/mbedtls/library/pkparse.cpp +++ b/extension/httpfs/third_party/mbedtls/library/pkparse.cpp @@ -243,8 +243,8 @@ static int pk_group_from_specified(const mbedtls_asn1_buf* params, mbedtls_ecp_g * parameters FIELD-ID.&Type({IOSet}{@fieldType}) * } */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) return (ret); end_field = p + len; @@ -286,8 +286,8 @@ static int pk_group_from_specified(const mbedtls_asn1_buf* params, mbedtls_ecp_g * -- with version equal to ecdpVer2 or ecdpVer3 * } */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) return (ret); end_curve = p + len; @@ -398,8 +398,8 @@ static int pk_group_id_from_group(const mbedtls_ecp_group* grp, mbedtls_ecp_grou /* * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID */ -static int pk_group_id_from_specified( - const mbedtls_asn1_buf* params, mbedtls_ecp_group_id* grp_id) { +static int pk_group_id_from_specified(const mbedtls_asn1_buf* params, + mbedtls_ecp_group_id* grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; @@ -463,8 +463,8 @@ static int pk_use_ecparams(const mbedtls_asn1_buf* params, mbedtls_ecp_group* gr static int pk_get_ecpubkey(unsigned char** p, const unsigned char* end, mbedtls_ecp_keypair* key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if ((ret = mbedtls_ecp_point_read_binary( - &key->grp, &key->Q, (const unsigned char*)*p, end - *p)) == 0) { + if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q, (const unsigned char*)*p, + end - *p)) == 0) { ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q); } @@ -488,8 +488,8 @@ static int pk_get_rsapubkey(unsigned char** p, const unsigned char* end, mbedtls int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret)); if (*p + len != end) @@ -559,8 +559,8 @@ static int pk_get_pk_alg(unsigned char** p, const unsigned char* end, mbedtls_pk * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ -int mbedtls_pk_parse_subpubkey( - unsigned char** p, const unsigned char* end, mbedtls_pk_context* pk) { +int mbedtls_pk_parse_subpubkey(unsigned char** p, const unsigned char* end, + mbedtls_pk_context* pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; mbedtls_asn1_buf alg_params; @@ -572,8 +572,8 @@ int mbedtls_pk_parse_subpubkey( PK_VALIDATE_RET(end != NULL); PK_VALIDATE_RET(pk != NULL); - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); } @@ -644,8 +644,8 @@ static int asn1_get_nonzero_mpi(unsigned char** p, const unsigned char* end, mbe /* * Parse a PKCS#1 encoded private RSA key */ -static int pk_parse_key_pkcs1_der( - mbedtls_rsa_context* rsa, const unsigned char* key, size_t keylen) { +static int pk_parse_key_pkcs1_der(mbedtls_rsa_context* rsa, const unsigned char* key, + size_t keylen) { int ret, version; size_t len; unsigned char *p, *end; @@ -672,8 +672,8 @@ static int pk_parse_key_pkcs1_der( * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); } @@ -807,8 +807,8 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair* eck, const unsigned char* * publicKey [1] BIT STRING OPTIONAL * } */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); } @@ -861,8 +861,8 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair* eck, const unsigned char* return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); if (p + len != end2) - return (MBEDTLS_ERROR_ADD( - MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); + return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) pubkey_done = 1; @@ -939,8 +939,8 @@ static int pk_parse_key_pkcs8_unencrypted_der(mbedtls_pk_context* pk, const unsi * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); } @@ -1034,8 +1034,8 @@ static int pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context* pk, unsigned cha * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo * */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); } @@ -1067,8 +1067,8 @@ static int pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context* pk, unsigned cha #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PKCS5_C) if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { - if ((ret = mbedtls_pkcs5_pbes2( - &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, p, len, buf)) != 0) { + if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, p, len, + buf)) != 0) { if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); @@ -1165,8 +1165,8 @@ int mbedtls_pk_parse_key(mbedtls_pk_context* pk, const unsigned char* key, size_ if (key[keylen - 1] != '\0') ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else - ret = mbedtls_pem_read_buffer( - &pem, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----", key, NULL, 0, &len); + ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", key, NULL, 0, &len); if (ret == 0) { if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, pem.buf, pem.buflen, f_rng, p_rng)) != 0) { @@ -1186,8 +1186,8 @@ int mbedtls_pk_parse_key(mbedtls_pk_context* pk, const unsigned char* key, size_ ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----END ENCRYPTED PRIVATE KEY-----", key, NULL, 0, &len); if (ret == 0) { - if ((ret = pk_parse_key_pkcs8_encrypted_der( - pk, pem.buf, pem.buflen, pwd, pwdlen, f_rng, p_rng)) != 0) { + if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, pwd, pwdlen, f_rng, + p_rng)) != 0) { mbedtls_pk_free(pk); } @@ -1328,8 +1328,8 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context* ctx, const unsigned char* ke if (key[keylen - 1] != '\0') ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else - ret = mbedtls_pem_read_buffer( - &pem, "-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----", key, NULL, 0, &len); + ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", key, NULL, 0, &len); if (ret == 0) { /* diff --git a/extension/httpfs/third_party/mbedtls/library/rsa.cpp b/extension/httpfs/third_party/mbedtls/library/rsa.cpp index 641694ba623..9301e52271b 100644 --- a/extension/httpfs/third_party/mbedtls/library/rsa.cpp +++ b/extension/httpfs/third_party/mbedtls/library/rsa.cpp @@ -366,8 +366,8 @@ int mbedtls_rsa_export(const mbedtls_rsa_context* ctx, mbedtls_mpi* N, mbedtls_m * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt * can be used in this case. */ -int mbedtls_rsa_export_crt( - const mbedtls_rsa_context* ctx, mbedtls_mpi* DP, mbedtls_mpi* DQ, mbedtls_mpi* QP) { +int mbedtls_rsa_export_crt(const mbedtls_rsa_context* ctx, mbedtls_mpi* DP, mbedtls_mpi* DQ, + mbedtls_mpi* QP) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; RSA_VALIDATE_RET(ctx != NULL); @@ -639,8 +639,8 @@ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context* pub, const mbedtls_rsa /* * Do an RSA public key operation */ -int mbedtls_rsa_public( - mbedtls_rsa_context* ctx, const unsigned char* input, unsigned char* output) { +int mbedtls_rsa_public(mbedtls_rsa_context* ctx, const unsigned char* input, + unsigned char* output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; mbedtls_mpi T; @@ -689,8 +689,8 @@ int mbedtls_rsa_public( * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ -static int rsa_prepare_blinding( - mbedtls_rsa_context* ctx, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { +static int rsa_prepare_blinding(mbedtls_rsa_context* ctx, + int (*f_rng)(void*, unsigned char*, size_t), void* p_rng) { int ret, count = 0; mbedtls_mpi R; @@ -1363,14 +1363,14 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context* ctx, int (*f_rng)(void*, unsi switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( - ctx, f_rng, p_rng, olen, input, output, output_max_len); + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen, input, output, + output_max_len); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_decrypt( - ctx, f_rng, p_rng, NULL, 0, olen, input, output, output_max_len); + return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0, olen, input, output, + output_max_len); #endif default: @@ -1508,8 +1508,8 @@ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context* ctx, int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context* ctx, int (*f_rng)(void*, unsigned char*, size_t), void* p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char* hash, unsigned char* sig) { - return rsa_rsassa_pss_sign( - ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); + return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, + sig); } #endif /* MBEDTLS_PKCS1_V21 */ @@ -1867,8 +1867,8 @@ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context* ctx, mbedtls_md_type_t md mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE) ? (mbedtls_md_type_t)ctx->hash_id : md_alg; - return (mbedtls_rsa_rsassa_pss_verify_ext( - ctx, md_alg, hashlen, hash, mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, sig)); + return (mbedtls_rsa_rsassa_pss_verify_ext(ctx, md_alg, hashlen, hash, mgf1_hash_id, + MBEDTLS_RSA_SALT_LEN_ANY, sig)); } #endif /* MBEDTLS_PKCS1_V21 */ @@ -2163,8 +2163,8 @@ int mbedtls_rsa_self_test(int verbose) { if (verbose != 0) mbedtls_printf("passed\n PKCS#1 decryption : "); - if (mbedtls_rsa_pkcs1_decrypt( - &rsa, myrand, NULL, &len, rsa_ciphertext, rsa_decrypted, sizeof(rsa_decrypted)) != 0) { + if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL, &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted)) != 0) { if (verbose != 0) mbedtls_printf("failed\n"); diff --git a/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.cpp b/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.cpp index 72bed6b306c..baa3a058de5 100644 --- a/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.cpp +++ b/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.cpp @@ -177,8 +177,8 @@ int mbedtls_rsa_deduce_primes(mbedtls_mpi const* N, mbedtls_mpi const* E, mbedtl * Given P, Q and the public exponent E, deduce D. * This is essentially a modular inversion. */ -int mbedtls_rsa_deduce_private_exponent( - mbedtls_mpi const* P, mbedtls_mpi const* Q, mbedtls_mpi const* E, mbedtls_mpi* D) { +int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const* P, mbedtls_mpi const* Q, + mbedtls_mpi const* E, mbedtls_mpi* D) { int ret = 0; mbedtls_mpi K, L; diff --git a/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.h b/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.h index f449213d613..e801fb12f82 100644 --- a/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.h +++ b/extension/httpfs/third_party/mbedtls/library/rsa_alt_helpers.h @@ -110,8 +110,8 @@ int mbedtls_rsa_deduce_primes(mbedtls_mpi const* N, mbedtls_mpi const* E, mbedtl * \note This function does not check whether P and Q are primes. * */ -int mbedtls_rsa_deduce_private_exponent( - mbedtls_mpi const* P, mbedtls_mpi const* Q, mbedtls_mpi const* E, mbedtls_mpi* D); +int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const* P, mbedtls_mpi const* Q, + mbedtls_mpi const* E, mbedtls_mpi* D); /** * \brief Generate RSA-CRT parameters diff --git a/extension/httpfs/third_party/mbedtls/library/sha1.cpp b/extension/httpfs/third_party/mbedtls/library/sha1.cpp index 01e66959383..3bdbe695f98 100644 --- a/extension/httpfs/third_party/mbedtls/library/sha1.cpp +++ b/extension/httpfs/third_party/mbedtls/library/sha1.cpp @@ -111,12 +111,12 @@ int mbedtls_internal_sha1_process(mbedtls_sha1_context* ctx, const unsigned char local.W[14] = MBEDTLS_GET_UINT32_BE(data, 56); local.W[15] = MBEDTLS_GET_UINT32_BE(data, 60); -#define S(x, n) (((x) << (n)) | (((x)&0xFFFFFFFF) >> (32 - (n)))) +#define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) #define R(t) \ - (local.temp = local.W[((t)-3) & 0x0F] ^ local.W[((t)-8) & 0x0F] ^ local.W[((t)-14) & 0x0F] ^ \ - local.W[(t)&0x0F], \ - (local.W[(t)&0x0F] = S(local.temp, 1))) + (local.temp = local.W[((t) - 3) & 0x0F] ^ local.W[((t) - 8) & 0x0F] ^ \ + local.W[((t) - 14) & 0x0F] ^ local.W[(t) & 0x0F], \ + (local.W[(t) & 0x0F] = S(local.temp, 1))) #define P(a, b, c, d, e, x) \ do { \ @@ -388,14 +388,14 @@ int mbedtls_sha1(const unsigned char* input, size_t ilen, unsigned char output[2 /* * FIPS-180-1 test vectors */ -static const unsigned char sha1_test_buf[3][57] = { - {"abc"}, {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, {""}}; +static const unsigned char sha1_test_buf[3][57] = {{"abc"}, + {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, {""}}; static const size_t sha1_test_buflen[3] = {3, 56, 1000}; -static const unsigned char sha1_test_sum[3][20] = { - {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, - 0x9C, 0xD0, 0xD8, 0x9D}, +static const unsigned char sha1_test_sum[3][20] = {{0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, + 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, + 0x6C, 0x9C, 0xD0, 0xD8, 0x9D}, {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1}, {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, diff --git a/extension/httpfs/third_party/mbedtls/library/sha256.cpp b/extension/httpfs/third_party/mbedtls/library/sha256.cpp index 5105caca4dd..7f6c74aefec 100644 --- a/extension/httpfs/third_party/mbedtls/library/sha256.cpp +++ b/extension/httpfs/third_party/mbedtls/library/sha256.cpp @@ -182,7 +182,7 @@ static const uint32_t K[] = { 0xC67178F2, }; -#define SHR(x, n) (((x)&0xFFFFFFFF) >> (n)) +#define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n)) #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n)))) #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) @@ -195,7 +195,8 @@ static const uint32_t K[] = { #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define R(t) \ - (local.W[t] = S1(local.W[(t)-2]) + local.W[(t)-7] + S0(local.W[(t)-15]) + local.W[(t)-16]) + (local.W[t] = \ + S1(local.W[(t) - 2]) + local.W[(t) - 7] + S0(local.W[(t) - 15]) + local.W[(t) - 16]) #define P(a, b, c, d, e, f, g, h, x, K) \ do { \ @@ -442,8 +443,8 @@ int mbedtls_sha256(const unsigned char* input, size_t ilen, unsigned char* outpu /* * FIPS-180-2 test vectors */ -static const unsigned char sha256_test_buf[3][57] = { - {"abc"}, {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, {""}}; +static const unsigned char sha256_test_buf[3][57] = {{"abc"}, + {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, {""}}; static const size_t sha256_test_buflen[3] = {3, 56, 1000}; diff --git a/extension/postgres_scanner/CMakeLists.txt b/extension/postgres_scanner/CMakeLists.txt new file mode 100644 index 00000000000..a8d3e658755 --- /dev/null +++ b/extension/postgres_scanner/CMakeLists.txt @@ -0,0 +1,58 @@ +find_package(DuckDB REQUIRED) + +add_library(postgres_scanner + SHARED + ../duckdb_scanner/src/duckdb_scan.cpp + ../duckdb_scanner/src/duckdb_catalog.cpp + ../duckdb_scanner/src/duckdb_table_catalog_entry.cpp + ../duckdb_scanner/src/duckdb_type_converter.cpp + src/postgres_scanner_extension.cpp + src/postgres_storage.cpp + src/postgres_catalog.cpp) + +include_directories( + src/include + ../duckdb_scanner/src/include + ${DuckDB_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR}/src/include) + +set_target_properties(postgres_scanner PROPERTIES + OUTPUT_NAME postgres_scanner + PREFIX "lib" + SUFFIX ".kuzu_extension" +) + +set_target_properties(postgres_scanner + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" +) + +target_link_libraries(postgres_scanner + PRIVATE + ${DuckDB_LIBRARIES}) + +if (WIN32) + # On windows, there is no dynamic lookup available, so it's not + # possible to generically look for symbols on library load. There are + # two main alternatives to statically linking kuzu, neither of which is + # appealing: + # 1. Link against the shared library. This works well assuming + # the DLL is locatable, but this assumption isn't valid for users + # of kuzu_shell.exe. + # 2. Link against the executable (kuzu_shell.exe). This is + # strange but works well for kuzu_shell.exe. However, it forces + # users who are embedding kuzu in their application to recompile + # the extension _and_ export the symbols for the extension to + # locate on load. + # We choose the simplest option. Windows isn't known + # for its small libraries anyways... + # Future work could make it possible to embed extension into kuzu, + # which would help fix this problem. + target_link_libraries(postgres_scanner PRIVATE kuzu) +endif() + +if (APPLE) + set_target_properties(postgres_scanner PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") +endif () diff --git a/extension/postgres_scanner/src/include/postgres_catalog.h b/extension/postgres_scanner/src/include/postgres_catalog.h new file mode 100644 index 00000000000..a1e137dec90 --- /dev/null +++ b/extension/postgres_scanner/src/include/postgres_catalog.h @@ -0,0 +1,51 @@ +#pragma once + +#include "duckdb_catalog.h" + +namespace kuzu { +namespace postgres_scanner { + +struct BoundExtraCreatePostgresTableInfo final + : public duckdb_scanner::BoundExtraCreateDuckDBTableInfo { + std::string pgConnectionStr; + + BoundExtraCreatePostgresTableInfo(std::string pgConnectionStr, std::string dbPath, + std::string catalogName, std::string schemaName, + std::vector propertyInfos) + : BoundExtraCreateDuckDBTableInfo{std::move(dbPath), std::move(catalogName), + std::move(schemaName), std::move(propertyInfos)}, + pgConnectionStr{std::move(pgConnectionStr)} {} + BoundExtraCreatePostgresTableInfo(const BoundExtraCreatePostgresTableInfo& other) + : BoundExtraCreateDuckDBTableInfo{other.dbPath, other.catalogName, other.schemaName, + copyVector(other.propertyInfos)}, + pgConnectionStr{other.pgConnectionStr} {} + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } +}; + +class PostgresCatalogContent final : public duckdb_scanner::DuckDBCatalogContent { +public: + PostgresCatalogContent() : duckdb_scanner::DuckDBCatalogContent{} {} + + void init(const std::string& dbPath, const std::string& catalogName, + main::ClientContext* context) override; + +private: + std::unique_ptr bindCreateTableInfo(duckdb::Connection& con, + const std::string& tableName, const std::string& dbPath, + const std::string& /*catalogName*/) override; + + std::string getDefaultSchemaName() const override; + + std::pair getConnection( + const std::string& dbPath) const override; + +private: + static constexpr char DEFAULT_CATALOG_NAME[] = "pg"; + static constexpr char DEFAULT_SCHEMA_NAME[] = "public"; +}; + +} // namespace postgres_scanner +} // namespace kuzu diff --git a/extension/postgres_scanner/src/include/postgres_scanner_extension.h b/extension/postgres_scanner/src/include/postgres_scanner_extension.h new file mode 100644 index 00000000000..aae2733d5ed --- /dev/null +++ b/extension/postgres_scanner/src/include/postgres_scanner_extension.h @@ -0,0 +1,15 @@ +#pragma once + +#include "extension/extension.h" +#include "main/database.h" + +namespace kuzu { +namespace postgres_scanner { + +class PostgresScannerExtension final : public extension::Extension { +public: + static void load(main::ClientContext* context); +}; + +} // namespace postgres_scanner +} // namespace kuzu diff --git a/extension/postgres_scanner/src/include/postgres_storage.h b/extension/postgres_scanner/src/include/postgres_storage.h new file mode 100644 index 00000000000..bf0f14b0556 --- /dev/null +++ b/extension/postgres_scanner/src/include/postgres_storage.h @@ -0,0 +1,17 @@ +#pragma once + +#include "common/string_utils.h" +#include "storage/storage_extension.h" + +namespace kuzu { +namespace postgres_scanner { + +class PostgresStorageExtension final : public storage::StorageExtension { +public: + PostgresStorageExtension(); + + bool canHandleDB(std::string dbType) const override; +}; + +} // namespace postgres_scanner +} // namespace kuzu diff --git a/extension/postgres_scanner/src/postgres_catalog.cpp b/extension/postgres_scanner/src/postgres_catalog.cpp new file mode 100644 index 00000000000..713fcf40836 --- /dev/null +++ b/extension/postgres_scanner/src/postgres_catalog.cpp @@ -0,0 +1,51 @@ +#include "postgres_catalog.h" + +#include "common/exception/binder.h" +#include "postgres_storage.h" + +namespace kuzu { +namespace postgres_scanner { + +void PostgresCatalogContent::init(const std::string& dbPath, const std::string& /*catalogName*/, + main::ClientContext* context) { + duckdb_scanner::DuckDBCatalogContent::init(dbPath, DEFAULT_CATALOG_NAME, context); +} + +std::string PostgresCatalogContent::getDefaultSchemaName() const { + return DEFAULT_SCHEMA_NAME; +} + +std::unique_ptr PostgresCatalogContent::bindCreateTableInfo( + duckdb::Connection& con, const std::string& tableName, const std::string& dbPath, + const std::string& /*catalogName*/) { + std::vector propertyInfos; + if (!bindPropertyInfos(con, tableName, DEFAULT_CATALOG_NAME, propertyInfos)) { + return nullptr; + } + auto extraCreatePostgresTableInfo = std::make_unique(dbPath, + "" /* dbPath */, DEFAULT_CATALOG_NAME, getDefaultSchemaName(), std::move(propertyInfos)); + return std::make_unique(common::TableType::FOREIGN, tableName, + std::move(extraCreatePostgresTableInfo)); +} + +static void executeQueryAndCheckErrMsg(duckdb::Connection& con, std::string query) { + auto result = con.Query(query); + if (result->HasError()) { + throw common::RuntimeException(common::stringFormat( + "Failed to execute query {}, due to: {}", query, result->GetError())); + } +} + +std::pair PostgresCatalogContent::getConnection( + const std::string& dbPath) const { + duckdb::DuckDB db(nullptr); + duckdb::Connection con(db); + executeQueryAndCheckErrMsg(con, "install postgres;"); + executeQueryAndCheckErrMsg(con, "load postgres;"); + executeQueryAndCheckErrMsg(con, + common::stringFormat("attach '{}' as {} (TYPE postgres);", dbPath, DEFAULT_CATALOG_NAME)); + return std::make_pair(std::move(db), std::move(con)); +} + +} // namespace postgres_scanner +} // namespace kuzu diff --git a/extension/postgres_scanner/src/postgres_scanner_extension.cpp b/extension/postgres_scanner/src/postgres_scanner_extension.cpp new file mode 100644 index 00000000000..d5ac7337075 --- /dev/null +++ b/extension/postgres_scanner/src/postgres_scanner_extension.cpp @@ -0,0 +1,27 @@ +#include "postgres_scanner_extension.h" + +#include "postgres_storage.h" + +namespace kuzu { +namespace postgres_scanner { + +void PostgresScannerExtension::load(main::ClientContext* context) { + auto db = context->getDatabase(); + db->registerStorageExtension("postgres", std::make_unique()); +} + +} // namespace postgres_scanner +} // namespace kuzu + +extern "C" { +// Because we link against the static library on windows, we implicitly inherit KUZU_STATIC_DEFINE, +// which cancels out any exporting, so we can't use KUZU_API. +#if defined(_WIN32) +#define INIT_EXPORT __declspec(dllexport) +#else +#define INIT_EXPORT __attribute__((visibility("default"))) +#endif +INIT_EXPORT void init(kuzu::main::ClientContext* context) { + kuzu::postgres_scanner::PostgresScannerExtension::load(context); +} +} diff --git a/extension/postgres_scanner/src/postgres_storage.cpp b/extension/postgres_scanner/src/postgres_storage.cpp new file mode 100644 index 00000000000..7ba98b14484 --- /dev/null +++ b/extension/postgres_scanner/src/postgres_storage.cpp @@ -0,0 +1,40 @@ +#include "postgres_storage.h" + +#include + +#include "catalog/catalog_entry/table_catalog_entry.h" +#include "duckdb_type_converter.h" +#include "postgres_catalog.h" + +namespace kuzu { +namespace postgres_scanner { + +std::string extractDBName(const std::string& connectionInfo) { + std::regex pattern("dbname=([^ ]+)"); + std::smatch match; + if (std::regex_search(connectionInfo, match, pattern)) { + return match.str(1); + } + throw common::RuntimeException{"Invalid postgresql connection string."}; +} + +std::unique_ptr attachPostgres(std::string dbName, std::string dbPath, + main::ClientContext* clientContext) { + auto catalogName = extractDBName(dbPath); + if (dbName == "") { + dbName = catalogName; + } + auto postgresCatalog = std::make_unique(); + postgresCatalog->init(dbPath, catalogName, clientContext); + return std::make_unique(dbName, std::move(postgresCatalog)); +} + +PostgresStorageExtension::PostgresStorageExtension() : StorageExtension{attachPostgres} {} + +bool PostgresStorageExtension::canHandleDB(std::string dbType) const { + common::StringUtils::toUpper(dbType); + return dbType == "POSTGRES"; +} + +} // namespace postgres_scanner +} // namespace kuzu diff --git a/extension/postgres_scanner/test/test_files/create_test_db.sql b/extension/postgres_scanner/test/test_files/create_test_db.sql new file mode 100644 index 00000000000..e2ecbc11aff --- /dev/null +++ b/extension/postgres_scanner/test/test_files/create_test_db.sql @@ -0,0 +1,241 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 14.10 (Homebrew) +-- Dumped by pg_dump version 14.10 (Homebrew) + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: audience_type; Type: TYPE; Schema: public; Owner: ci +-- + +CREATE TYPE public.audience_type AS ( + key character varying, + value bigint +); + + +ALTER TYPE public.audience_type OWNER TO ci; + +-- +-- Name: description_type; Type: TYPE; Schema: public; Owner: ci +-- + +CREATE TYPE public.description_type AS ( + rating double precision, + stars bigint, + views bigint, + release timestamp without time zone, + release_ns timestamp without time zone, + release_ms timestamp without time zone, + release_sec timestamp without time zone, + release_tz timestamp with time zone, + film date, + u8 smallint, + u16 smallint, + u32 integer, + u64 bigint, + hugedata numeric +); + + +ALTER TYPE public.description_type OWNER TO ci; + +-- +-- Name: mood; Type: TYPE; Schema: public; Owner: ci +-- + +CREATE TYPE public.mood AS ENUM ( + 'sad', + 'ok', + 'happy' +); + + +ALTER TYPE public.mood OWNER TO ci; + +-- +-- Name: state_type; Type: TYPE; Schema: public; Owner: ci +-- + +CREATE TYPE public.state_type AS ( + revenue smallint, + location character varying[] +); + + +ALTER TYPE public.state_type OWNER TO ci; + +-- +-- Name: stock_type; Type: TYPE; Schema: public; Owner: ci +-- + +CREATE TYPE public.stock_type AS ( + price bigint[], + volume bigint +); + + +ALTER TYPE public.stock_type OWNER TO ci; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: movies; Type: TABLE; Schema: public; Owner: ci +-- + +CREATE TABLE public.movies ( + name character varying NOT NULL, + length integer, + note character varying, + description public.description_type, + content bytea, + audience public.audience_type[] +); + + +ALTER TABLE public.movies OWNER TO ci; + +-- +-- Name: organisation; Type: TABLE; Schema: public; Owner: ci +-- + +CREATE TABLE public.organisation ( + id bigint NOT NULL, + name character varying, + orgcode bigint, + mark double precision, + score bigint, + history interval, + licensevalidinterval interval, + rating double precision, + state public.state_type, + stock public.stock_type, + info character varying +); + + +ALTER TABLE public.organisation OWNER TO ci; + +-- +-- Name: person; Type: TABLE; Schema: public; Owner: ci +-- + +CREATE TABLE public.person ( + id bigint NOT NULL, + fname character varying, + gender bigint, + isstudent boolean, + isworker boolean, + age bigint, + eyesight double precision, + birthdate date, + registertime timestamp without time zone, + lastjobduration interval, + workedhours bigint[], + usednames character varying[], + height double precision, + u uuid +); + + +ALTER TABLE public.person OWNER TO ci; + +-- +-- Name: persontest; Type: TABLE; Schema: public; Owner: ci +-- + +CREATE TABLE public.persontest ( + id integer +); + + +ALTER TABLE public.persontest OWNER TO ci; + +-- +-- Data for Name: movies; Type: TABLE DATA; Schema: public; Owner: ci +-- + +COPY public.movies (name, length, note, description, content, audience) FROM stdin; +Sóló cón tu párejâ 126 this is a very very good movie (5.3,2,152,"2011-08-20 11:25:30","2011-08-20 11:25:30","2011-08-20 11:25:30","2011-08-20 11:25:30","2011-08-20 11:25:30+08",2012-05-11,220,20,1,180,1844674407370955161811111111) \\x5c7841415c784142696e746572657374696e675c783042 {"(audience1,52)","(audience53,42)"} +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie 2544 the movie is very very good (7,10,982,"2018-11-13 13:33:11","2018-11-13 13:33:11","2018-11-13 13:33:11","2018-11-13 13:33:11","2018-11-13 13:33:11+08",2014-09-12,12,120,55,1,-1844674407370955161511) \\x5c7841425c784344 {"(audience1,33)"} +Roma 298 the movie is very interesting and funny (1223,100,10003,"2011-02-11 16:44:22","2011-02-11 16:44:22","2011-02-11 16:44:22","2011-02-11 16:44:22","2011-02-11 16:44:22+08",2013-02-22,1,15,200,4,-15) \\x707572652061736369692063686172616374657273 {} +\. + + +-- +-- Data for Name: organisation; Type: TABLE DATA; Schema: public; Owner: ci +-- + +COPY public.organisation (id, name, orgcode, mark, score, history, licensevalidinterval, rating, state, stock, info) FROM stdin; +1 ABFsUni 325 3.7 -2 10 years 5 mons 13:00:00.000024 3 years 5 days 1 (138,"{toronto,""montr,eal""}") ("{96,56}",1000) 3.12 +4 CsWork 934 4.1 -100 2 years 4 days 10:00:00 26 years 52 days 48:00:00 0.78 (152,"{""vanco,uver north area""}") ("{15,78,671}",432) abcd +6 DEsWork 824 4.1 7 2 years 04:34:00.000022 82:00:00.1 0.52 (558,"{""very long city name"",""new york""}") ({22},99) 2023-12-15 +\. + + +-- +-- Data for Name: person; Type: TABLE DATA; Schema: public; Owner: ci +-- + +COPY public.person (id, fname, gender, isstudent, isworker, age, eyesight, birthdate, registertime, lastjobduration, workedhours, usednames, height, u) FROM stdin; +0 Alice 1 t f 35 5 1900-01-01 2011-08-20 11:25:30 3 years 2 days 13:02:00 {10,5} {Aida} 1.731 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 +2 Bob 2 t f 30 5.1 1900-01-01 2008-11-03 15:25:30.000526 10 years 5 mons 13:00:00.000024 {12,8} {Bobby} 0.99 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12 +3 Carol 1 f t 45 5 1940-06-22 1911-08-20 02:32:21 48:24:11 {4,5} {Carmen,Fred} 1 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13 +5 Dan 2 f t 20 4.8 1950-07-23 2031-11-30 12:25:30 10 years 5 mons 13:00:00.000024 {1,9} {Wolfeschlegelstein,Daniel} 1.3 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14 +7 Elizabeth 1 f t 20 4.7 1980-10-26 1976-12-23 11:21:42 48:24:11 {2} {Ein} 1.463 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15 +8 Farooq 2 t f 25 4.5 1980-10-26 1972-07-31 13:22:30.678559 00:18:00.024 {3,4,5,6,7} {Fesdwe} 1.51 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16 +9 Greg 2 f f 40 4.9 1980-10-26 1976-12-23 11:21:42 10 years 5 mons 13:00:00.000024 {1} {Grad} 1.6 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17 +10 Hubert Blaine Wolfeschlegelsteinhausenbergerdorff 2 f t 83 4.9 1990-11-27 2023-02-21 13:25:30 3 years 2 days 13:02:00 {10,11,12,3,4,5,6,7} {Ad,De,Hi,Kye,Orlan} 1.323 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18 +\. + + +-- +-- Data for Name: persontest; Type: TABLE DATA; Schema: public; Owner: ci +-- + +COPY public.persontest (id) FROM stdin; +\. + + +-- +-- Name: movies movies_pkey; Type: CONSTRAINT; Schema: public; Owner: ci +-- + +ALTER TABLE ONLY public.movies + ADD CONSTRAINT movies_pkey PRIMARY KEY (name); + + +-- +-- Name: organisation organisation_pkey; Type: CONSTRAINT; Schema: public; Owner: ci +-- + +ALTER TABLE ONLY public.organisation + ADD CONSTRAINT organisation_pkey PRIMARY KEY (id); + + +-- +-- Name: person person_pkey; Type: CONSTRAINT; Schema: public; Owner: ci +-- + +ALTER TABLE ONLY public.person + ADD CONSTRAINT person_pkey PRIMARY KEY (id); + + +-- +-- PostgreSQL database dump complete +-- + diff --git a/extension/postgres_scanner/test/test_files/postgres_scanner.test b/extension/postgres_scanner/test/test_files/postgres_scanner.test new file mode 100644 index 00000000000..76ee4b0dc64 --- /dev/null +++ b/extension/postgres_scanner/test/test_files/postgres_scanner.test @@ -0,0 +1,50 @@ +-GROUP PostgresScanner +-DATASET CSV empty + +-- + +-CASE ScanPostgresTable +-STATEMENT load extension "${KUZU_ROOT_DIRECTORY}/extension/postgres_scanner/build/libpostgres_scanner.kuzu_extension" +---- ok +-STATEMENT ATTACH 'dbname=pgscan user=ci host=localhost' as tinysnb (dbtype 'POSTGRES'); +---- ok +-STATEMENT LOAD FROM tinysnb_person RETURN *; +---- 8 +0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|1.731000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 +10|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|2|False|True|83|4.900000|1990-11-27|2023-02-21 13:25:30|3 years 2 days 13:02:00|[10,11,12,3,4,5,6,7]|[Ad,De,Hi,Kye,Orlan]|1.323000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18 +2|Bob|2|True|False|30|5.100000|1900-01-01|2008-11-03 15:25:30.000526|10 years 5 months 13:00:00.000024|[12,8]|[Bobby]|0.990000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12 +3|Carol|1|False|True|45|5.000000|1940-06-22|1911-08-20 02:32:21|48:24:11|[4,5]|[Carmen,Fred]|1.000000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13 +5|Dan|2|False|True|20|4.800000|1950-07-23|2031-11-30 12:25:30|10 years 5 months 13:00:00.000024|[1,9]|[Wolfeschlegelstein,Daniel]|1.300000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14 +7|Elizabeth|1|False|True|20|4.700000|1980-10-26|1976-12-23 11:21:42|48:24:11|[2]|[Ein]|1.463000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15 +8|Farooq|2|True|False|25|4.500000|1980-10-26|1972-07-31 13:22:30.678559|00:18:00.024|[3,4,5,6,7]|[Fesdwe]|1.510000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16 +9|Greg|2|False|False|40|4.900000|1980-10-26|1976-12-23 11:21:42|10 years 5 months 13:00:00.000024|[1]|[Grad]|1.600000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17 +-STATEMENT LOAD FROM tinysnb_organisation RETURN *; +---- 3 +1|ABFsUni|325|3.700000|-2|10 years 5 months 13:00:00.000024|3 years 5 days|1.000000|{revenue: 138, "location": [toronto,montr,eal]}|{price: [96,56], volume: 1000}|3.12 +4|CsWork|934|4.100000|-100|2 years 4 days 10:00:00|26 years 52 days 48:00:00|0.780000|{revenue: 152, "location": [vanco,uver north area]}|{price: [15,78,671], volume: 432}|abcd +6|DEsWork|824|4.100000|7|2 years 04:34:00.000022|82:00:00.1|0.520000|{revenue: 558, "location": [very long city name,new york]}|{price: [22], volume: 99}|2023-12-15 +-STATEMENT LOAD FROM tinysnb_movies RETURN *; +---- 3 +Roma|298|the movie is very interesting and funny|{rating: 1223.000000, stars: 100, "views": 10003, "release": 2011-02-11 16:44:22, release_ns: 2011-02-11 16:44:22, release_ms: 2011-02-11 16:44:22, release_sec: 2011-02-11 16:44:22, release_tz: 2011-02-11 08:44:22+00, film: 2013-02-22, u8: 1, u16: 15, u32: 200, u64: 4, hugedata: -15.000000}|pure ascii characters|[] +Sóló cón tu párejâ|126|this is a very very good movie|{rating: 5.300000, stars: 2, "views": 152, "release": 2011-08-20 11:25:30, release_ns: 2011-08-20 11:25:30, release_ms: 2011-08-20 11:25:30, release_sec: 2011-08-20 11:25:30, release_tz: 2011-08-20 03:25:30+00, film: 2012-05-11, u8: 220, u16: 20, u32: 1, u64: 180, hugedata: 1844674407370955161600000000.000000}|\x5CxAA\x5CxABinteresting\x5Cx0B|[{"key": audience1, "value": 52},{"key": audience53, "value": 42}] +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie|2544|the movie is very very good|{rating: 7.000000, stars: 10, "views": 982, "release": 2018-11-13 13:33:11, release_ns: 2018-11-13 13:33:11, release_ms: 2018-11-13 13:33:11, release_sec: 2018-11-13 13:33:11, release_tz: 2018-11-13 05:33:11+00, film: 2014-09-12, u8: 12, u16: 120, u32: 55, u64: 1, hugedata: -1844674407370954899456.000000}|\x5CxAB\x5CxCD|[{"key": audience1, "value": 33}] +-STATEMENT LOAD FROM tinysnb_person1 RETURN *; +---- error +Catalog exception: Table: person1 does not exist. +-STATEMENT LOAD FROM tinysnb1_person RETURN *; +---- error +Binder exception: No database named tinysnb1 has been attached. +-STATEMENT ATTACH 'dbname=pgscan user=ci host=localhost' (dbtype 'POSTGRES'); +---- ok +-STATEMENT LOAD FROM pgscan_movies RETURN count(*); +---- 1 +3 +-STATEMENT LOAD FROM pgscan_movies where length > 2500 RETURN name; +---- 1 +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie +# TODO(Ziyi): the error message is dependent on platforms. We have to implement regex in testing framework to handle this. +#-LOG IncorrectConnectionStr +#-STATEMENT ATTACH 'dbname=test2132131 user=ci host=127.0.0.1' as tinysnb (dbtype 'POSTGRES'); +#---- error +#Binder exception: Failed to attach postgres database due to: IO Error: Unable to connect to Postgres at dbname=test2132131 user=ci host=127.0.0.1: connection to server at "127.0.0.1", port 5432 failed: Connection refused +# Is the server running on that host and accepting TCP/IP connections? diff --git a/scripts/antlr4/Cypher.g4.copy b/scripts/antlr4/Cypher.g4.copy index 763bb33a916..d3491a5ad84 100644 --- a/scripts/antlr4/Cypher.g4.copy +++ b/scripts/antlr4/Cypher.g4.copy @@ -31,26 +31,44 @@ oC_Statement | kU_Transaction | kU_Extension | kU_ExportDatabase - | kU_ImportDatabase; + | kU_ImportDatabase + | kU_AttachDatabase + | kU_DetachDatabase; kU_CopyFrom - : COPY SP oC_SchemaName ( ( SP? '(' SP? kU_ColumnNames SP? ')' SP? ) | SP ) FROM SP (kU_FilePaths | oC_Variable) ( SP? '(' SP? kU_ParsingOptions SP? ')' )? ; + : COPY SP oC_SchemaName ( ( SP? kU_ColumnNames SP? ) | SP ) FROM SP kU_ScanSource ( SP? kU_ParsingOptions )? ; kU_ColumnNames - : oC_SchemaName ( SP? ',' SP? oC_SchemaName )* ; + : '(' SP? oC_SchemaName ( SP? ',' SP? oC_SchemaName )* SP? ')'; + +kU_ScanSource + : kU_FilePaths + | '(' SP? oC_Query SP? ')' + | oC_Variable ; kU_CopyFromByColumn : COPY SP oC_SchemaName SP FROM SP '(' SP? StringLiteral ( SP? ',' SP? StringLiteral )* ')' SP BY SP COLUMN ; kU_CopyTO - : COPY SP '(' SP? oC_Query SP? ')' SP TO SP StringLiteral ( SP? '(' SP? kU_ParsingOptions SP? ')' )? ; + : COPY SP '(' SP? oC_Query SP? ')' SP TO SP StringLiteral ( SP? kU_ParsingOptions )? ; kU_ExportDatabase - : EXPORT SP DATABASE SP StringLiteral ( SP? '(' SP? kU_ParsingOptions SP? ')' )? ; + : EXPORT SP DATABASE SP StringLiteral ( SP? kU_ParsingOptions )? ; kU_ImportDatabase : IMPORT SP DATABASE SP StringLiteral; +kU_AttachDatabase + : ATTACH SP StringLiteral (SP AS SP oC_SchemaName SP)? (SP? '(' SP? DBTYPE SP StringLiteral SP? ')')?; + +ATTACH: + ( 'A' | 'a') ( 'T' | 't') ( 'T' | 't') ( 'A' | 'a') ( 'C' | 'c') ( 'H' | 'h'); + +DBTYPE: + ( 'D' | 'd') ( 'B' | 'b') ( 'T' | 't') ( 'Y' | 'y') ( 'P' | 'p') ( 'E' | 'e'); + +kU_DetachDatabase + : DETACH SP oC_SchemaName; kU_StandaloneCall : CALL SP oC_SymbolicName SP? '=' SP? oC_Literal ; @@ -58,9 +76,9 @@ kU_StandaloneCall CALL : ( 'C' | 'c' ) ( 'A' | 'a' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ; kU_CommentOn - : COMMENT SP ON SP TABLE SP oC_SchemaName SP IS SP StringLiteral ; + : COMMENT_ SP ON SP TABLE SP oC_SchemaName SP IS SP StringLiteral ; -COMMENT : ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ( 'M' | 'm' ) ( 'E' | 'e' ) ( 'N' | 'n' ) ( 'T' | 't' ) ; +COMMENT_ : ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ( 'M' | 'm' ) ( 'E' | 'e' ) ( 'N' | 'n' ) ( 'T' | 't' ) ; kU_CreateMacro : CREATE SP MACRO SP oC_FunctionName SP? '(' SP? kU_PositionalArgs? SP? kU_DefaultArg? ( SP? ',' SP? kU_DefaultArg )* SP? ')' SP AS SP oC_Expression ; @@ -81,7 +99,7 @@ kU_FilePaths GLOB : ( 'G' | 'g' ) ( 'L' | 'l' ) ( 'O' | 'o' ) ( 'B' | 'b' ) ; kU_ParsingOptions - : kU_ParsingOption ( SP? ',' SP? kU_ParsingOption )* ; + : '(' SP? kU_ParsingOption ( SP? ',' SP? kU_ParsingOption )* SP? ')' ; kU_ParsingOption : oC_SymbolicName SP? '=' SP? oC_Literal; @@ -291,7 +309,7 @@ oC_ReadingClause ; kU_LoadFrom - : LOAD ( SP WITH SP HEADERS SP? '(' SP? kU_PropertyDefinitions SP? ')' )? SP FROM SP (kU_FilePaths ( SP? '(' SP? kU_ParsingOptions SP? ')' )? | oC_Variable) (SP? oC_Where)? ; + : LOAD ( SP WITH SP HEADERS SP? '(' SP? kU_PropertyDefinitions SP? ')' )? SP FROM SP kU_ScanSource (SP? kU_ParsingOptions)? (SP? oC_Where)? ; LOAD : ( 'L' | 'l' ) ( 'O' | 'o' ) ( 'A' | 'a' ) ( 'D' | 'd' ) ; @@ -754,7 +772,7 @@ oC_SymbolicName // example of BEGIN and END: TCKWith2.Scenario1 kU_NonReservedKeywords - : COMMENT + : COMMENT_ | COUNT | NODE | REL @@ -819,7 +837,9 @@ WHITESPACE ; Comment - : ( '/*' ( Comment_1 | ( '*' Comment_2 ) )* '*/' ) ; + : ( '/*' ( Comment_1 | ( '*' Comment_2 ) )* '*/' ) + | ( '//' ( Comment_3 )* CR? ( LF | EOF ) ) + ; oC_LeftArrowHead : '<' diff --git a/scripts/multiplatform-test-helper/collect-results.py b/scripts/multiplatform-test-helper/collect-results.py new file mode 100644 index 00000000000..968ed4a6b8b --- /dev/null +++ b/scripts/multiplatform-test-helper/collect-results.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +import os +import sys +import pandas as pd +import json + + +def main(): + if len(sys.argv) != 2: + print("Usage: collect-results.py ") + sys.exit(1) + if not os.path.isdir(sys.argv[1]): + print(f"Error: {sys.argv[1]} is not a directory") + sys.exit(1) + results_dir = sys.argv[1] + results_df_hash = {} + results_exit_codes_hash = {} + results_summary = {} + stages = [] + for root, _, files in os.walk(results_dir): + for csv_file in files: + if not csv_file.endswith(".csv"): + continue + platform = csv_file.split(".")[0] + df = pd.read_csv(os.path.join(root, csv_file), header=None) + df.columns = ["stage", "exit_code"] + results_df_hash[platform] = df + + for platform, df in results_df_hash.items(): + for stage, exit_code in df.values: + if stage not in stages: + stages.append(stage) + if platform not in results_exit_codes_hash: + results_exit_codes_hash[platform] = {} + results_exit_codes_hash[platform][stage] = int(exit_code) + + for platform in results_df_hash.keys(): + results_summary[platform] = [] + for stage in stages: + status = ( + "✅" + if stage in results_exit_codes_hash[platform] + and results_exit_codes_hash[platform][stage] == 0 + else "❌" + ) + results_summary[platform].append({"stage": stage, "status": status}) + + summary_df = {"stage": stages} + for platform, summary in results_summary.items(): + df = pd.DataFrame(summary) + status = df["status"] + summary_df[platform] = status + summary_df = pd.DataFrame(summary_df) + summary_df.index = summary_df["stage"] + del summary_df["stage"] + summary_df.index.name = None + + markdown = summary_df.to_markdown() + with open("results.md", "w") as f: + f.write(markdown) + + with open("results.json", "w") as f: + json.dump(results_summary, f, indent=4) + + +if __name__ == "__main__": + main() diff --git a/scripts/multiplatform-test-helper/notify-discord.py b/scripts/multiplatform-test-helper/notify-discord.py new file mode 100644 index 00000000000..a5046b044ed --- /dev/null +++ b/scripts/multiplatform-test-helper/notify-discord.py @@ -0,0 +1,55 @@ +import discord +import os +import json +import sys + +TOKEN = os.getenv("DISCORD_BOT_TOKEN") +CHANNEL_ID = os.getenv("DISCORD_CHANNEL_ID") +GITHUB_URL = os.getenv("GITHUB_URL") + +messages = [] + + +if __name__ == "__main__": + if not len(sys.argv) == 2: + print("Usage: python send-dicord-notification.py ") + sys.exit(1) + if not os.path.isfile(sys.argv[1]): + print(f"Error: {sys.argv[1]} is not a file") + sys.exit(1) + if not TOKEN: + print("Error: DISCORD_BOT_TOKEN is not set") + sys.exit(1) + + if not CHANNEL_ID: + print("Error: DISCORD_CHANNEL_ID is not set") + sys.exit(1) + client = discord.Client(intents=discord.Intents.default()) + + @client.event + async def on_ready(): + channel = client.get_channel(int(CHANNEL_ID)) + for message in messages: + try: + await channel.send(message) + except Exception as e: + print(f"Error: {e}") + sys.exit(1) + await client.close() + + message = "" + message += "## Multiplatform test result:\n" + with open(sys.argv[1], "r") as f: + result = json.load(f) + for platform in result: + if len(message) >= 1500: + messages.append(message) + message = "" + message += f"- **{platform}**:\n" + for r in result[platform]: + message += f" - {r['stage']}: {r['status']}\n" + if GITHUB_URL: + message += f" [Github]({GITHUB_URL})" + if message: + messages.append(message) + client.run(TOKEN) diff --git a/scripts/parquet/csv_to_parquet.py b/scripts/parquet/csv_to_parquet.py deleted file mode 100644 index af3779d38be..00000000000 --- a/scripts/parquet/csv_to_parquet.py +++ /dev/null @@ -1,14 +0,0 @@ -from pyarrow import csv -import pyarrow.parquet as pq - -csv_files = ['dummy.csv'] -has_header = True -# CSV: -# has header? autogenerate_column_names=False -# no header? autogenerate_column_names=True -read_options = csv.ReadOptions(autogenerate_column_names=not has_header) -parse_options = csv.ParseOptions(delimiter=",") -for csv_file in csv_files: - table = csv.read_csv(csv_file, read_options=read_options, - parse_options=parse_options) - pq.write_table(table, csv_file.replace('.csv', '.parquet')) diff --git a/scripts/pip-package/package_tar.py b/scripts/pip-package/package_tar.py index 3bb5771d17e..9baaf416dec 100755 --- a/scripts/pip-package/package_tar.py +++ b/scripts/pip-package/package_tar.py @@ -9,21 +9,23 @@ base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + def _get_kuzu_version(): - cmake_file = os.path.abspath(os.path.join(base_dir, '..', 'CMakeLists.txt')) + cmake_file = os.path.abspath(os.path.join(base_dir, "..", "CMakeLists.txt")) with open(cmake_file) as f: for line in f: - if line.startswith('project(Kuzu VERSION'): - raw_version = line.split(' ')[2].strip() - version_nums = raw_version.split('.') + if line.startswith("project(Kuzu VERSION"): + raw_version = line.split(" ")[2].strip() + version_nums = raw_version.split(".") if len(version_nums) <= 3: return raw_version else: dev_suffix = version_nums[3] - version = '.'.join(version_nums[:3]) + version = ".".join(version_nums[:3]) version += ".dev%s" % dev_suffix return version + if __name__ == "__main__": if len(sys.argv) == 2: file_name = sys.argv[1] @@ -50,11 +52,34 @@ def _get_kuzu_version(): os.remove(os.path.join(tempdir, "kuzu-source.tar")) + # Remove components that are not needed for the pip package + shutil.rmtree(os.path.join(tempdir, "kuzu-source/dataset")) + shutil.rmtree(os.path.join(tempdir, "kuzu-source/examples")) + shutil.rmtree(os.path.join(tempdir, "kuzu-source/benchmark")) + shutil.rmtree(os.path.join(tempdir, "kuzu-source/logo")) + shutil.rmtree(os.path.join(tempdir, "kuzu-source/extension")) + shutil.rmtree(os.path.join(tempdir, "kuzu-source/test")) + shutil.rmtree(os.path.join(tempdir, "kuzu-source/.github")) + os.makedirs(os.path.join(tempdir, "kuzu")) for path in ["setup.py", "setup.cfg", "MANIFEST.in"]: shutil.copy2(path, os.path.join(tempdir, path)) - shutil.copy2("../../LICENSE", os.path.join(tempdir, "LICENSE.txt")) + shutil.copy2("../../LICENSE", os.path.join(tempdir, "LICENSE")) shutil.copy2("../../README.md", os.path.join(tempdir, "README.md")) + + shutil.copy2( + "../../tools/python_api/pyproject.toml", + os.path.join(tempdir, "pyproject.toml"), + ) + # Update the version in pyproject.toml + with open(os.path.join(tempdir, "pyproject.toml"), "r") as f: + lines = f.readlines() + with open(os.path.join(tempdir, "pyproject.toml"), "w") as f: + for line in lines: + if line.startswith("version ="): + f.write('version = "%s"\n' % _get_kuzu_version()) + else: + f.write(line) shutil.copy2("README.md", os.path.join(tempdir, "README_PYTHON_BUILD.md")) subprocess.check_call([sys.executable, "setup.py", "egg_info"], cwd=tempdir) diff --git a/src/antlr4/Cypher.g4 b/src/antlr4/Cypher.g4 index 763bb33a916..d3491a5ad84 100644 --- a/src/antlr4/Cypher.g4 +++ b/src/antlr4/Cypher.g4 @@ -31,26 +31,44 @@ oC_Statement | kU_Transaction | kU_Extension | kU_ExportDatabase - | kU_ImportDatabase; + | kU_ImportDatabase + | kU_AttachDatabase + | kU_DetachDatabase; kU_CopyFrom - : COPY SP oC_SchemaName ( ( SP? '(' SP? kU_ColumnNames SP? ')' SP? ) | SP ) FROM SP (kU_FilePaths | oC_Variable) ( SP? '(' SP? kU_ParsingOptions SP? ')' )? ; + : COPY SP oC_SchemaName ( ( SP? kU_ColumnNames SP? ) | SP ) FROM SP kU_ScanSource ( SP? kU_ParsingOptions )? ; kU_ColumnNames - : oC_SchemaName ( SP? ',' SP? oC_SchemaName )* ; + : '(' SP? oC_SchemaName ( SP? ',' SP? oC_SchemaName )* SP? ')'; + +kU_ScanSource + : kU_FilePaths + | '(' SP? oC_Query SP? ')' + | oC_Variable ; kU_CopyFromByColumn : COPY SP oC_SchemaName SP FROM SP '(' SP? StringLiteral ( SP? ',' SP? StringLiteral )* ')' SP BY SP COLUMN ; kU_CopyTO - : COPY SP '(' SP? oC_Query SP? ')' SP TO SP StringLiteral ( SP? '(' SP? kU_ParsingOptions SP? ')' )? ; + : COPY SP '(' SP? oC_Query SP? ')' SP TO SP StringLiteral ( SP? kU_ParsingOptions )? ; kU_ExportDatabase - : EXPORT SP DATABASE SP StringLiteral ( SP? '(' SP? kU_ParsingOptions SP? ')' )? ; + : EXPORT SP DATABASE SP StringLiteral ( SP? kU_ParsingOptions )? ; kU_ImportDatabase : IMPORT SP DATABASE SP StringLiteral; +kU_AttachDatabase + : ATTACH SP StringLiteral (SP AS SP oC_SchemaName SP)? (SP? '(' SP? DBTYPE SP StringLiteral SP? ')')?; + +ATTACH: + ( 'A' | 'a') ( 'T' | 't') ( 'T' | 't') ( 'A' | 'a') ( 'C' | 'c') ( 'H' | 'h'); + +DBTYPE: + ( 'D' | 'd') ( 'B' | 'b') ( 'T' | 't') ( 'Y' | 'y') ( 'P' | 'p') ( 'E' | 'e'); + +kU_DetachDatabase + : DETACH SP oC_SchemaName; kU_StandaloneCall : CALL SP oC_SymbolicName SP? '=' SP? oC_Literal ; @@ -58,9 +76,9 @@ kU_StandaloneCall CALL : ( 'C' | 'c' ) ( 'A' | 'a' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ; kU_CommentOn - : COMMENT SP ON SP TABLE SP oC_SchemaName SP IS SP StringLiteral ; + : COMMENT_ SP ON SP TABLE SP oC_SchemaName SP IS SP StringLiteral ; -COMMENT : ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ( 'M' | 'm' ) ( 'E' | 'e' ) ( 'N' | 'n' ) ( 'T' | 't' ) ; +COMMENT_ : ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ( 'M' | 'm' ) ( 'E' | 'e' ) ( 'N' | 'n' ) ( 'T' | 't' ) ; kU_CreateMacro : CREATE SP MACRO SP oC_FunctionName SP? '(' SP? kU_PositionalArgs? SP? kU_DefaultArg? ( SP? ',' SP? kU_DefaultArg )* SP? ')' SP AS SP oC_Expression ; @@ -81,7 +99,7 @@ kU_FilePaths GLOB : ( 'G' | 'g' ) ( 'L' | 'l' ) ( 'O' | 'o' ) ( 'B' | 'b' ) ; kU_ParsingOptions - : kU_ParsingOption ( SP? ',' SP? kU_ParsingOption )* ; + : '(' SP? kU_ParsingOption ( SP? ',' SP? kU_ParsingOption )* SP? ')' ; kU_ParsingOption : oC_SymbolicName SP? '=' SP? oC_Literal; @@ -291,7 +309,7 @@ oC_ReadingClause ; kU_LoadFrom - : LOAD ( SP WITH SP HEADERS SP? '(' SP? kU_PropertyDefinitions SP? ')' )? SP FROM SP (kU_FilePaths ( SP? '(' SP? kU_ParsingOptions SP? ')' )? | oC_Variable) (SP? oC_Where)? ; + : LOAD ( SP WITH SP HEADERS SP? '(' SP? kU_PropertyDefinitions SP? ')' )? SP FROM SP kU_ScanSource (SP? kU_ParsingOptions)? (SP? oC_Where)? ; LOAD : ( 'L' | 'l' ) ( 'O' | 'o' ) ( 'A' | 'a' ) ( 'D' | 'd' ) ; @@ -754,7 +772,7 @@ oC_SymbolicName // example of BEGIN and END: TCKWith2.Scenario1 kU_NonReservedKeywords - : COMMENT + : COMMENT_ | COUNT | NODE | REL @@ -819,7 +837,9 @@ WHITESPACE ; Comment - : ( '/*' ( Comment_1 | ( '*' Comment_2 ) )* '*/' ) ; + : ( '/*' ( Comment_1 | ( '*' Comment_2 ) )* '*/' ) + | ( '//' ( Comment_3 )* CR? ( LF | EOF ) ) + ; oC_LeftArrowHead : '<' diff --git a/src/binder/CMakeLists.txt b/src/binder/CMakeLists.txt index 5cc5bd577e8..3b767103224 100644 --- a/src/binder/CMakeLists.txt +++ b/src/binder/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(visitor) add_library(kuzu_binder OBJECT binder.cpp + binder_scope.cpp bound_statement_result.cpp bound_statement_rewriter.cpp bound_statement_visitor.cpp diff --git a/src/binder/bind/CMakeLists.txt b/src/binder/bind/CMakeLists.txt index 90047fb71eb..6fa7ba366db 100644 --- a/src/binder/bind/CMakeLists.txt +++ b/src/binder/bind/CMakeLists.txt @@ -4,10 +4,12 @@ add_subdirectory(ddl) add_library( kuzu_binder_bind OBJECT + bind_attach_database.cpp bind_comment_on.cpp bind_copy.cpp bind_create_macro.cpp bind_ddl.cpp + bind_detach_database.cpp bind_explain.cpp bind_file_scan.cpp bind_graph_pattern.cpp diff --git a/src/binder/bind/bind_attach_database.cpp b/src/binder/bind/bind_attach_database.cpp new file mode 100644 index 00000000000..cad7a9b2bf6 --- /dev/null +++ b/src/binder/bind/bind_attach_database.cpp @@ -0,0 +1,16 @@ +#include "binder/binder.h" +#include "binder/bound_attach_database.h" +#include "common/cast.h" +#include "parser/attach_database.h" + +namespace kuzu { +namespace binder { + +std::unique_ptr Binder::bindAttachDatabase(const parser::Statement& statement) { + auto& attachDatabase = + common::ku_dynamic_cast(statement); + return std::make_unique(attachDatabase.getAttachInfo()); +} + +} // namespace binder +} // namespace kuzu diff --git a/src/binder/bind/bind_comment_on.cpp b/src/binder/bind/bind_comment_on.cpp index 1f1c845fd7f..5b8e5cf6136 100644 --- a/src/binder/bind/bind_comment_on.cpp +++ b/src/binder/bind/bind_comment_on.cpp @@ -1,5 +1,6 @@ #include "binder/binder.h" #include "binder/bound_comment_on.h" +#include "catalog/catalog.h" #include "main/client_context.h" #include "parser/comment_on.h" @@ -12,7 +13,7 @@ std::unique_ptr Binder::bindCommentOn(const parser::Statement& s auto tableName = commentOn.getTable(); auto comment = commentOn.getComment(); validateTableExist(tableName); - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); + auto tableID = clientContext->getCatalog()->getTableID(clientContext->getTx(), tableName); return std::make_unique(tableID, tableName, comment); } diff --git a/src/binder/bind/bind_copy.cpp b/src/binder/bind/bind_copy.cpp index 6fbc5fc17c1..a3ba5aefa99 100644 --- a/src/binder/bind/bind_copy.cpp +++ b/src/binder/bind/bind_copy.cpp @@ -1,12 +1,12 @@ #include "binder/binder.h" #include "binder/copy/bound_copy_from.h" #include "binder/copy/bound_copy_to.h" +#include "catalog/catalog.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "catalog/catalog_entry/rel_table_catalog_entry.h" #include "common/enums/table_type.h" #include "common/exception/binder.h" -#include "common/exception/message.h" #include "common/string_format.h" #include "function/table/bind_input.h" #include "main/client_context.h" @@ -16,6 +16,7 @@ using namespace kuzu::binder; using namespace kuzu::catalog; using namespace kuzu::common; using namespace kuzu::parser; +using namespace kuzu::function; namespace kuzu { namespace binder { @@ -36,33 +37,15 @@ std::unique_ptr Binder::bindCopyToClause(const Statement& statem columnTypes.push_back(column->getDataType()); } if (fileType != FileType::CSV && fileType != FileType::PARQUET) { - throw BinderException(ExceptionMessage::validateCopyToCSVParquetExtensionsException()); + throw BinderException("COPY TO currently only supports csv and parquet files."); } if (fileType != FileType::CSV && copyToStatement.getParsingOptionsRef().size() != 0) { throw BinderException{"Only copy to csv can have options."}; } auto csvConfig = CSVReaderConfig::construct(bindParsingOptions(copyToStatement.getParsingOptionsRef())); - return std::make_unique(boundFilePath, fileType, std::move(columnNames), - std::move(columnTypes), std::move(query), csvConfig.option.copy()); -} - -// As a temporary constraint, we require npy files loaded with COPY FROM BY COLUMN keyword. -// And csv and parquet files loaded with COPY FROM keyword. -static void validateByColumnKeyword(FileType fileType, bool byColumn) { - if (fileType == FileType::NPY && !byColumn) { - throw BinderException(ExceptionMessage::validateCopyNPYByColumnException()); - } - if (fileType != FileType::NPY && byColumn) { - throw BinderException(ExceptionMessage::validateCopyCSVParquetByColumnException()); - } -} - -static void validateCopyNpyNotForRelTables(TableCatalogEntry* tableEntry) { - if (tableEntry->getTableType() == TableType::REL) { - throw BinderException( - ExceptionMessage::validateCopyNpyNotForRelTablesException(tableEntry->getName())); - } + return std::make_unique(boundFilePath, fileType, std::move(query), + csvConfig.option.copy()); } std::unique_ptr Binder::bindCopyFromClause(const Statement& statement) { @@ -70,8 +53,9 @@ std::unique_ptr Binder::bindCopyFromClause(const Statement& stat auto tableName = copyStatement.getTableName(); validateTableExist(tableName); // Bind to table schema. - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); - auto tableEntry = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto catalog = clientContext->getCatalog(); + auto tableID = catalog->getTableID(clientContext->getTx(), tableName); + auto tableEntry = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); switch (tableEntry->getTableType()) { case TableType::REL_GROUP: { throw BinderException(stringFormat("Cannot copy into {} table with type {}.", tableName, @@ -80,84 +64,84 @@ std::unique_ptr Binder::bindCopyFromClause(const Statement& stat default: break; } - auto filePaths = bindFilePaths(copyStatement.getFilePaths()); - auto fileType = bindFileType(filePaths); - auto readerConfig = std::make_unique(fileType, std::move(filePaths)); - readerConfig->options = bindParsingOptions(copyStatement.getParsingOptionsRef()); - validateByColumnKeyword(readerConfig->fileType, copyStatement.byColumn()); - if (readerConfig->fileType == FileType::NPY) { - validateCopyNpyNotForRelTables(tableEntry); - } switch (tableEntry->getTableType()) { - case TableType::NODE: - return bindCopyNodeFrom(statement, std::move(readerConfig), - ku_dynamic_cast(tableEntry)); - case TableType::REL: - return bindCopyRelFrom(statement, std::move(readerConfig), - ku_dynamic_cast(tableEntry)); - case TableType::RDF: - return bindCopyRdfFrom(statement, std::move(readerConfig), - ku_dynamic_cast(tableEntry)); + case TableType::NODE: { + auto nodeTableEntry = + ku_dynamic_cast(tableEntry); + return bindCopyNodeFrom(statement, nodeTableEntry); + } + case TableType::REL: { + auto relTableEntry = ku_dynamic_cast(tableEntry); + return bindCopyRelFrom(statement, relTableEntry); + } + case TableType::RDF: { + auto rdfGraphEntry = ku_dynamic_cast(tableEntry); + return bindCopyRdfFrom(statement, rdfGraphEntry); + } default: { KU_UNREACHABLE; } } } +static void bindExpectedNodeColumns(NodeTableCatalogEntry* nodeTableEntry, + const std::vector& inputColumnNames, std::vector& columnNames, + std::vector& columnTypes); +static void bindExpectedRelColumns(RelTableCatalogEntry* relTableEntry, + const std::vector& inputColumnNames, std::vector& columnNames, + std::vector& columnTypes, main::ClientContext* context); + std::unique_ptr Binder::bindCopyNodeFrom(const Statement& statement, - std::unique_ptr config, NodeTableCatalogEntry* nodeTableEntry) { + NodeTableCatalogEntry* nodeTableEntry) { auto& copyStatement = ku_dynamic_cast(statement); - auto func = getScanFunction(config->fileType, *config); - // For table with SERIAL columns, we need to read in serial from files. - auto containsSerial = nodeTableEntry->containPropertyType(*LogicalType::SERIAL()); + // Bind expected columns based on catalog information. std::vector expectedColumnNames; - std::vector expectedColumnTypes; - bindExpectedNodeColumns( - nodeTableEntry, copyStatement.getColumnNames(), expectedColumnNames, expectedColumnTypes); - auto bindInput = std::make_unique(config->copy(), - std::move(expectedColumnNames), std::move(expectedColumnTypes), clientContext); - auto bindData = func->bindFunc(clientContext, bindInput.get()); - expression_vector columns; - for (auto i = 0u; i < bindData->columnTypes.size(); i++) { - columns.push_back(createVariable(bindData->columnNames[i], bindData->columnTypes[i])); + std::vector expectedColumnTypes; + bindExpectedNodeColumns(nodeTableEntry, copyStatement.getColumnNames(), expectedColumnNames, + expectedColumnTypes); + auto boundSource = bindScanSource(copyStatement.getSource(), + copyStatement.getParsingOptionsRef(), expectedColumnNames, expectedColumnTypes); + if (boundSource->type == ScanSourceType::FILE) { + auto fileSource = + ku_dynamic_cast(boundSource.get()); + auto bindData = ku_dynamic_cast( + fileSource->fileScanInfo.bindData.get()); + if (copyStatement.byColumn() && bindData->config.fileType != FileType::NPY) { + throw BinderException(stringFormat("Copy by column with {} file type is not supported.", + FileTypeUtils::toString(bindData->config.fileType))); + } } - auto offset = expressionBinder.createVariableExpression( - LogicalType(LogicalTypeID::INT64), std::string(InternalKeyword::ANONYMOUS)); - auto boundFileScanInfo = - std::make_unique(func, std::move(bindData), columns, std::move(offset)); - auto boundCopyFromInfo = BoundCopyFromInfo( - nodeTableEntry, std::move(boundFileScanInfo), containsSerial, nullptr /* extraInfo */); + auto offset = expressionBinder.createVariableExpression(*LogicalType::INT64(), + std::string(InternalKeyword::ANONYMOUS)); + auto boundCopyFromInfo = + BoundCopyFromInfo(nodeTableEntry, std::move(boundSource), offset, nullptr /* extraInfo */); return std::make_unique(std::move(boundCopyFromInfo)); } std::unique_ptr Binder::bindCopyRelFrom(const parser::Statement& statement, - std::unique_ptr config, RelTableCatalogEntry* relTableEntry) { + RelTableCatalogEntry* relTableEntry) { auto& copyStatement = ku_dynamic_cast(statement); - auto func = getScanFunction(config->fileType, *config); - // For table with SERIAL columns, we need to read in serial from files. - auto containsSerial = relTableEntry->containPropertyType(*LogicalType::SERIAL()); - KU_ASSERT(containsSerial == false); - std::vector expectedColumnNames; - std::vector expectedColumnTypes; - bindExpectedRelColumns( - relTableEntry, copyStatement.getColumnNames(), expectedColumnNames, expectedColumnTypes); - auto bindInput = std::make_unique(std::move(*config), - std::move(expectedColumnNames), std::move(expectedColumnTypes), clientContext); - auto bindData = func->bindFunc(clientContext, bindInput.get()); - expression_vector columns; - for (auto i = 0u; i < bindData->columnTypes.size(); i++) { - columns.push_back(createVariable(bindData->columnNames[i], bindData->columnTypes[i])); + if (copyStatement.byColumn()) { + throw BinderException( + stringFormat("Copy by column is not supported for relationship table.")); } - auto offset = expressionBinder.createVariableExpression( - *LogicalType::INT64(), std::string(InternalKeyword::ROW_OFFSET)); - auto boundFileScanInfo = - std::make_unique(func, std::move(bindData), columns, offset); + // Bind expected columns based on catalog information. + std::vector expectedColumnNames; + std::vector expectedColumnTypes; + bindExpectedRelColumns(relTableEntry, copyStatement.getColumnNames(), expectedColumnNames, + expectedColumnTypes, clientContext); + auto boundSource = bindScanSource(copyStatement.getSource(), + copyStatement.getParsingOptionsRef(), expectedColumnNames, expectedColumnTypes); + auto columns = boundSource->getColumns(); + auto offset = expressionBinder.createVariableExpression(*LogicalType::INT64(), + std::string(InternalKeyword::ROW_OFFSET)); auto srcTableID = relTableEntry->getSrcTableID(); auto dstTableID = relTableEntry->getDstTableID(); - auto srcSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(clientContext->getTx(), srcTableID)); - auto dstSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(clientContext->getTx(), dstTableID)); + auto catalog = clientContext->getCatalog(); + auto srcEntry = catalog->getTableCatalogEntry(clientContext->getTx(), srcTableID); + auto dstEntry = catalog->getTableCatalogEntry(clientContext->getTx(), dstTableID); + auto srcNodeEntry = ku_dynamic_cast(srcEntry); + auto dstNodeEntry = ku_dynamic_cast(dstEntry); auto srcKey = columns[0]; auto dstKey = columns[1]; expression_vector propertyColumns; @@ -166,8 +150,8 @@ std::unique_ptr Binder::bindCopyRelFrom(const parser::Statement& } auto srcOffset = createVariable(InternalKeyword::SRC_OFFSET, LogicalTypeID::INT64); auto dstOffset = createVariable(InternalKeyword::DST_OFFSET, LogicalTypeID::INT64); - auto srcPkType = srcSchema->getPrimaryKey()->getDataType(); - auto dstPkType = dstSchema->getPrimaryKey()->getDataType(); + auto srcPkType = srcNodeEntry->getPrimaryKey()->getDataType(); + auto dstPkType = dstNodeEntry->getPrimaryKey()->getDataType(); auto srcLookUpInfo = IndexLookupInfo(srcTableID, srcOffset, srcKey, *srcPkType); auto dstLookUpInfo = IndexLookupInfo(dstTableID, dstOffset, dstKey, *dstPkType); auto extraCopyRelInfo = std::make_unique(); @@ -176,8 +160,8 @@ std::unique_ptr Binder::bindCopyRelFrom(const parser::Statement& extraCopyRelInfo->propertyColumns = std::move(propertyColumns); extraCopyRelInfo->infos.push_back(std::move(srcLookUpInfo)); extraCopyRelInfo->infos.push_back(std::move(dstLookUpInfo)); - auto boundCopyFromInfo = BoundCopyFromInfo( - relTableEntry, std::move(boundFileScanInfo), containsSerial, std::move(extraCopyRelInfo)); + auto boundCopyFromInfo = + BoundCopyFromInfo(relTableEntry, boundSource->copy(), offset, std::move(extraCopyRelInfo)); return std::make_unique(std::move(boundCopyFromInfo)); } @@ -206,8 +190,8 @@ static void bindExpectedColumns(TableCatalogEntry* tableEntry, // Search column data type for each input column. for (auto& columnName : inputColumnNames) { if (!tableEntry->containProperty(columnName)) { - throw BinderException(stringFormat( - "Table {} does not contain column {}.", tableEntry->getName(), columnName)); + throw BinderException(stringFormat("Table {} does not contain column {}.", + tableEntry->getName(), columnName)); } auto propertyID = tableEntry->getPropertyID(columnName); auto property = tableEntry->getProperty(propertyID); @@ -229,21 +213,22 @@ static void bindExpectedColumns(TableCatalogEntry* tableEntry, } } -void Binder::bindExpectedNodeColumns(NodeTableCatalogEntry* nodeTableEntry, +void bindExpectedNodeColumns(NodeTableCatalogEntry* nodeTableEntry, const std::vector& inputColumnNames, std::vector& columnNames, - std::vector& columnTypes) { + std::vector& columnTypes) { KU_ASSERT(columnNames.empty() && columnTypes.empty()); bindExpectedColumns(nodeTableEntry, inputColumnNames, columnNames, columnTypes); } -void Binder::bindExpectedRelColumns(RelTableCatalogEntry* relTableEntry, +void bindExpectedRelColumns(RelTableCatalogEntry* relTableEntry, const std::vector& inputColumnNames, std::vector& columnNames, - std::vector& columnTypes) { + std::vector& columnTypes, main::ClientContext* context) { KU_ASSERT(columnNames.empty() && columnTypes.empty()); - auto srcTable = ku_dynamic_cast( - catalog.getTableCatalogEntry(clientContext->getTx(), relTableEntry->getSrcTableID())); - auto dstTable = ku_dynamic_cast( - catalog.getTableCatalogEntry(clientContext->getTx(), relTableEntry->getDstTableID())); + auto catalog = context->getCatalog(); + auto srcEntry = catalog->getTableCatalogEntry(context->getTx(), relTableEntry->getSrcTableID()); + auto srcTable = ku_dynamic_cast(srcEntry); + auto dstEntry = catalog->getTableCatalogEntry(context->getTx(), relTableEntry->getDstTableID()); + auto dstTable = ku_dynamic_cast(dstEntry); columnNames.push_back("from"); columnNames.push_back("to"); auto srcPKColumnType = *srcTable->getPrimaryKey()->getDataType(); diff --git a/src/binder/bind/bind_create_macro.cpp b/src/binder/bind/bind_create_macro.cpp index 5f1aca07ef9..c4d720dced3 100644 --- a/src/binder/bind/bind_create_macro.cpp +++ b/src/binder/bind/bind_create_macro.cpp @@ -1,5 +1,6 @@ #include "binder/binder.h" #include "binder/bound_create_macro.h" +#include "catalog/catalog.h" #include "common/exception/binder.h" #include "common/string_format.h" #include "common/string_utils.h" @@ -16,7 +17,7 @@ std::unique_ptr Binder::bindCreateMacro(const Statement& stateme auto& createMacro = ku_dynamic_cast(statement); auto macroName = createMacro.getMacroName(); StringUtils::toUpper(macroName); - if (catalog.containsMacro(clientContext->getTx(), macroName)) { + if (clientContext->getCatalog()->containsMacro(clientContext->getTx(), macroName)) { throw BinderException{stringFormat("Macro {} already exists.", macroName)}; } parser::default_macro_args defaultArgs; diff --git a/src/binder/bind/bind_ddl.cpp b/src/binder/bind/bind_ddl.cpp index bdb113d29a6..8bb0d0d1223 100644 --- a/src/binder/bind/bind_ddl.cpp +++ b/src/binder/bind/bind_ddl.cpp @@ -2,6 +2,7 @@ #include "binder/ddl/bound_alter.h" #include "binder/ddl/bound_create_table.h" #include "binder/ddl/bound_drop_table.h" +#include "catalog/catalog.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "catalog/catalog_entry/rel_group_catalog_entry.h" @@ -39,8 +40,8 @@ std::vector Binder::bindPropertyInfo( std::vector propertyInfos; propertyInfos.reserve(propertyNameDataTypes.size()); for (auto& propertyNameDataType : propertyNameDataTypes) { - propertyInfos.emplace_back( - propertyNameDataType.first, *bindDataType(propertyNameDataType.second)); + propertyInfos.emplace_back(propertyNameDataType.first, + *bindDataType(propertyNameDataType.second)); } validateUniquePropertyName(propertyInfos); for (auto& info : propertyInfos) { @@ -51,8 +52,8 @@ std::vector Binder::bindPropertyInfo( return propertyInfos; } -static uint32_t bindPrimaryKey( - const std::string& pkColName, const std::vector& infos) { +static uint32_t bindPrimaryKey(const std::string& pkColName, + const std::vector& infos) { uint32_t primaryKeyIdx = UINT32_MAX; for (auto i = 0u; i < infos.size(); i++) { if (infos[i].name == pkColName) { @@ -137,8 +138,8 @@ BoundCreateTableInfo Binder::bindCreateRelTableInfo(const CreateTableInfo* info) validateTableType(srcTableID, TableType::NODE); auto dstTableID = bindTableID(extraInfo->dstTableName); validateTableType(dstTableID, TableType::NODE); - auto boundExtraInfo = std::make_unique( - srcMultiplicity, dstMultiplicity, srcTableID, dstTableID, std::move(propertyInfos)); + auto boundExtraInfo = std::make_unique(srcMultiplicity, + dstMultiplicity, srcTableID, dstTableID, std::move(propertyInfos)); return BoundCreateTableInfo(TableType::REL, info->tableName, std::move(boundExtraInfo)); } @@ -167,7 +168,7 @@ BoundCreateTableInfo Binder::bindCreateRelTableGroupInfo(const CreateTableInfo* std::unique_ptr Binder::bindCreateTable(const Statement& statement) { auto& createTable = ku_dynamic_cast(statement); auto tableName = createTable.getInfo()->tableName; - if (catalog.containsTable(clientContext->getTx(), tableName)) { + if (clientContext->getCatalog()->containsTable(clientContext->getTx(), tableName)) { throw BinderException(tableName + " already exists in catalog."); } auto boundCreateInfo = bindCreateTableInfo(createTable.getInfo()); @@ -178,12 +179,13 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement auto& dropTable = ku_dynamic_cast(statement); auto tableName = dropTable.getTableName(); validateTableExist(tableName); - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); - auto tableEntry = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto catalog = clientContext->getCatalog(); + auto tableID = catalog->getTableID(clientContext->getTx(), tableName); + auto tableEntry = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); switch (tableEntry->getTableType()) { case TableType::NODE: { // Check node table is not referenced by rel table. - for (auto& relTableEntry : catalog.getRelTableEntries(clientContext->getTx())) { + for (auto& relTableEntry : catalog->getRelTableEntries(clientContext->getTx())) { if (relTableEntry->isParent(tableID)) { throw BinderException(stringFormat("Cannot delete node table {} because it is " "referenced by relationship table {}.", @@ -191,7 +193,7 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement } } // Check node table is not referenced by rdf graph - for (auto& rdfEntry : catalog.getRdfGraphEntries(clientContext->getTx())) { + for (auto& rdfEntry : catalog->getRdfGraphEntries(clientContext->getTx())) { if (rdfEntry->isParent(tableID)) { throw BinderException(stringFormat( "Cannot delete node table {} because it is referenced by rdfGraph {}.", @@ -201,7 +203,7 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement } break; case TableType::REL: { // Check rel table is not referenced by rel group. - for (auto& relTableGroupEntry : catalog.getRelTableGroupEntries(clientContext->getTx())) { + for (auto& relTableGroupEntry : catalog->getRelTableGroupEntries(clientContext->getTx())) { if (relTableGroupEntry->isParent(tableID)) { throw BinderException(stringFormat("Cannot delete relationship table {} because it " "is referenced by relationship group {}.", @@ -209,7 +211,7 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement } } // Check rel table is not referenced by rdf graph. - for (auto& rdfGraphEntry : catalog.getRdfGraphEntries(clientContext->getTx())) { + for (auto& rdfGraphEntry : catalog->getRdfGraphEntries(clientContext->getTx())) { if (rdfGraphEntry->isParent(tableID)) { throw BinderException(stringFormat( "Cannot delete relationship table {} because it is referenced by rdfGraph {}.", @@ -220,7 +222,7 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement case TableType::RDF: { auto rdfGraphEntry = ku_dynamic_cast(tableEntry); // Check resource table is not referenced by rel table other than its triple table. - for (auto& relTableEntry : catalog.getRelTableEntries(clientContext->getTx())) { + for (auto& relTableEntry : catalog->getRelTableEntries(clientContext->getTx())) { if (relTableEntry->getTableID() == rdfGraphEntry->getResourceTripleTableID() || relTableEntry->getTableID() == rdfGraphEntry->getLiteralTripleTableID()) { continue; @@ -232,7 +234,7 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement } } // Check literal table is not referenced by rel table other than its triple table. - for (auto& relTableEntry : catalog.getRelTableEntries(clientContext->getTx())) { + for (auto& relTableEntry : catalog->getRelTableEntries(clientContext->getTx())) { if (relTableEntry->getTableID() == rdfGraphEntry->getLiteralTripleTableID()) { continue; } @@ -251,8 +253,9 @@ std::unique_ptr Binder::bindDropTable(const Statement& statement std::unique_ptr Binder::bindAlter(const Statement& statement) { auto& alter = ku_dynamic_cast(statement); - auto tableID = catalog.getTableID(clientContext->getTx(), alter.getInfo()->tableName); - for (auto& schema : catalog.getRdfGraphEntries(clientContext->getTx())) { + auto catalog = clientContext->getCatalog(); + auto tableID = catalog->getTableID(clientContext->getTx(), alter.getInfo()->tableName); + for (auto& schema : catalog->getRdfGraphEntries(clientContext->getTx())) { if (schema->isParent(tableID)) { throw BinderException( stringFormat("Cannot alter table {} because it is referenced by rdfGraph {}.", @@ -285,10 +288,11 @@ std::unique_ptr Binder::bindRenameTable(const Statement& stateme auto tableName = info->tableName; auto newName = extraInfo->newName; validateTableExist(tableName); - if (catalog.containsTable(clientContext->getTx(), newName)) { + auto catalog = clientContext->getCatalog(); + if (catalog->containsTable(clientContext->getTx(), newName)) { throw BinderException("Table: " + newName + " already exists."); } - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); + auto tableID = catalog->getTableID(clientContext->getTx(), tableName); auto boundExtraInfo = std::make_unique(newName); auto boundInfo = BoundAlterInfo(AlterType::RENAME_TABLE, tableName, tableID, std::move(boundExtraInfo)); @@ -302,16 +306,16 @@ static void validatePropertyExist(TableCatalogEntry* tableEntry, const std::stri } } -static void validatePropertyNotExist( - TableCatalogEntry* tableEntry, const std::string& propertyName) { +static void validatePropertyNotExist(TableCatalogEntry* tableEntry, + const std::string& propertyName) { if (tableEntry->containProperty(propertyName)) { throw BinderException( tableEntry->getName() + " table already has property " + propertyName + "."); } } -static void validatePropertyDDLOnTable( - TableCatalogEntry* tableEntry, const std::string& ddlOperation) { +static void validatePropertyDDLOnTable(TableCatalogEntry* tableEntry, + const std::string& ddlOperation) { switch (tableEntry->getTableType()) { case TableType::REL_GROUP: case TableType::RDF: { @@ -332,8 +336,9 @@ std::unique_ptr Binder::bindAddProperty(const Statement& stateme auto dataType = bindDataType(extraInfo->dataType); auto propertyName = extraInfo->propertyName; validateTableExist(tableName); - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); - auto tableSchema = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto catalog = clientContext->getCatalog(); + auto tableID = catalog->getTableID(clientContext->getTx(), tableName); + auto tableSchema = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); validatePropertyDDLOnTable(tableSchema, "add"); validatePropertyNotExist(tableSchema, propertyName); if (dataType->getLogicalTypeID() == LogicalTypeID::SERIAL) { @@ -356,8 +361,9 @@ std::unique_ptr Binder::bindDropProperty(const Statement& statem auto tableName = info->tableName; auto propertyName = extraInfo->propertyName; validateTableExist(tableName); - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); - auto tableEntry = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto catalog = clientContext->getCatalog(); + auto tableID = catalog->getTableID(clientContext->getTx(), tableName); + auto tableEntry = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); validatePropertyDDLOnTable(tableEntry, "drop"); validatePropertyExist(tableEntry, propertyName); auto propertyID = tableEntry->getPropertyID(propertyName); @@ -381,8 +387,9 @@ std::unique_ptr Binder::bindRenameProperty(const Statement& stat auto propertyName = extraInfo->propertyName; auto newName = extraInfo->newName; validateTableExist(tableName); - auto tableID = catalog.getTableID(clientContext->getTx(), tableName); - auto tableSchema = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto catalog = clientContext->getCatalog(); + auto tableID = catalog->getTableID(clientContext->getTx(), tableName); + auto tableSchema = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); validatePropertyDDLOnTable(tableSchema, "rename"); validatePropertyExist(tableSchema, propertyName); auto propertyID = tableSchema->getPropertyID(propertyName); diff --git a/src/binder/bind/bind_detach_database.cpp b/src/binder/bind/bind_detach_database.cpp new file mode 100644 index 00000000000..849bd2311a6 --- /dev/null +++ b/src/binder/bind/bind_detach_database.cpp @@ -0,0 +1,16 @@ +#include "binder/binder.h" +#include "binder/bound_detach_database.h" +#include "common/cast.h" +#include "parser/detach_database.h" + +namespace kuzu { +namespace binder { + +std::unique_ptr Binder::bindDetachDatabase(const parser::Statement& statement) { + auto& detachDatabase = + common::ku_dynamic_cast(statement); + return std::make_unique(detachDatabase.getDBName()); +} + +} // namespace binder +} // namespace kuzu diff --git a/src/binder/bind/bind_explain.cpp b/src/binder/bind/bind_explain.cpp index f01d5256c99..bf256869432 100644 --- a/src/binder/bind/bind_explain.cpp +++ b/src/binder/bind/bind_explain.cpp @@ -8,8 +8,8 @@ namespace binder { std::unique_ptr Binder::bindExplain(const parser::Statement& statement) { auto& explain = (parser::ExplainStatement&)statement; auto boundStatementToExplain = bind(*explain.getStatementToExplain()); - return std::make_unique( - std::move(boundStatementToExplain), explain.getExplainType()); + return std::make_unique(std::move(boundStatementToExplain), + explain.getExplainType()); } } // namespace binder diff --git a/src/binder/bind/bind_export_database.cpp b/src/binder/bind/bind_export_database.cpp index 6006e22fba4..34eb09b611f 100644 --- a/src/binder/bind/bind_export_database.cpp +++ b/src/binder/bind/bind_export_database.cpp @@ -1,5 +1,8 @@ #include "binder/copy/bound_export_database.h" #include "binder/query/bound_regular_query.h" +#include "catalog/catalog.h" +#include "catalog/catalog_entry/node_table_catalog_entry.h" +#include "catalog/catalog_entry/rel_table_catalog_entry.h" #include "common/exception/binder.h" #include "common/string_utils.h" #include "main/client_context.h" @@ -23,8 +26,8 @@ static std::string getPrimaryKeyName(table_id_t tableId, const Catalog& catalog, return primaryProperty->getName(); } -static std::vector getExportInfo( - const Catalog& catalog, Transaction* tx, Binder* binder) { +static std::vector getExportInfo(const Catalog& catalog, Transaction* tx, + Binder* binder) { std::vector exportData; for (auto& nodeTableEntry : catalog.getNodeTableEntries(tx)) { auto tableName = nodeTableEntry->getName(); @@ -81,7 +84,7 @@ ExportedTableData Binder::extractExportData(std::string selQuery, std::string ta std::unique_ptr Binder::bindExportDatabaseClause(const Statement& statement) { auto& exportDatabaseStatement = ku_dynamic_cast(statement); auto boundFilePath = exportDatabaseStatement.getFilePath(); - auto exportData = getExportInfo(catalog, clientContext->getTx(), this); + auto exportData = getExportInfo(*clientContext->getCatalog(), clientContext->getTx(), this); auto parsedOptions = bindParsingOptions(exportDatabaseStatement.getParsingOptionsRef()); auto fileType = getFileType(parsedOptions); if (fileType != FileType::CSV && fileType != FileType::PARQUET) { @@ -90,14 +93,8 @@ std::unique_ptr Binder::bindExportDatabaseClause(const Statement if (fileType != FileType::CSV && parsedOptions.size() != 0) { throw BinderException{"Only export to csv can have options."}; } - // try to create the directory, if it doesn't exist yet - if (!vfs->fileOrPathExists(boundFilePath)) { - vfs->createDir(boundFilePath); - } else { - throw BinderException(stringFormat("Directory {} already exists.", boundFilePath)); - } - return std::make_unique( - boundFilePath, fileType, std::move(exportData), std::move(parsedOptions)); + return std::make_unique(boundFilePath, fileType, std::move(exportData), + std::move(parsedOptions)); } } // namespace binder } // namespace kuzu diff --git a/src/binder/bind/bind_extension.cpp b/src/binder/bind/bind_extension.cpp index b7ab836a85c..a5b5b0b4d66 100644 --- a/src/binder/bind/bind_extension.cpp +++ b/src/binder/bind/bind_extension.cpp @@ -11,8 +11,8 @@ namespace binder { std::unique_ptr Binder::bindExtension(const Statement& statement) { auto extensionStatement = common::ku_dynamic_cast(statement); - return std::make_unique( - extensionStatement.getAction(), extensionStatement.getPath()); + return std::make_unique(extensionStatement.getAction(), + extensionStatement.getPath()); } } // namespace binder diff --git a/src/binder/bind/bind_file_scan.cpp b/src/binder/bind/bind_file_scan.cpp index 230b88e2711..c866887e2a4 100644 --- a/src/binder/bind/bind_file_scan.cpp +++ b/src/binder/bind/bind_file_scan.cpp @@ -1,24 +1,25 @@ #include "binder/binder.h" +#include "binder/bound_scan_source.h" #include "binder/expression/literal_expression.h" #include "common/exception/binder.h" #include "common/exception/copy.h" #include "common/file_system/virtual_file_system.h" #include "common/string_format.h" #include "common/string_utils.h" +#include "function/table/bind_input.h" +#include "parser/scan_source.h" using namespace kuzu::parser; using namespace kuzu::binder; using namespace kuzu::common; +using namespace kuzu::function; namespace kuzu { namespace binder { -/* - * Bind file. - */ FileType Binder::bindFileType(const std::string& filePath) { std::filesystem::path fileName(filePath); - auto extension = vfs->getFileExtension(fileName); + auto extension = clientContext->getVFSUnsafe()->getFileExtension(fileName); auto fileType = FileTypeUtils::getFileTypeFromExtension(extension); return fileType; } @@ -38,13 +39,13 @@ FileType Binder::bindFileType(const std::vector& filePaths) { std::vector Binder::bindFilePaths(const std::vector& filePaths) { std::vector boundFilePaths; for (auto& filePath : filePaths) { - auto globbedFilePaths = vfs->glob(clientContext, filePath); + auto globbedFilePaths = clientContext->getVFSUnsafe()->glob(clientContext, filePath); if (globbedFilePaths.empty()) { throw BinderException{ stringFormat("No file found that matches the pattern: {}.", filePath)}; } - boundFilePaths.insert( - boundFilePaths.end(), globbedFilePaths.begin(), globbedFilePaths.end()); + boundFilePaths.insert(boundFilePaths.end(), globbedFilePaths.begin(), + globbedFilePaths.end()); } return boundFilePaths; } @@ -63,5 +64,58 @@ std::unordered_map Binder::bindParsingOptions( return options; } +std::unique_ptr Binder::bindScanSource(BaseScanSource* source, + const parsing_option_t& options, const std::vector& expectedColumnNames, + const std::vector& expectedColumnTypes) { + switch (source->type) { + case common::ScanSourceType::FILE: { + auto fileSource = ku_dynamic_cast(source); + // Bind path. + auto filePaths = bindFilePaths(fileSource->filePaths); + // Bind file type. + auto fileType = bindFileType(filePaths); + auto config = std::make_unique(fileType, std::move(filePaths)); + // Bind options. + config->options = bindParsingOptions(options); + // Bind file scan function. + auto func = getScanFunction(config->fileType, *config); + auto bindInput = std::make_unique(config->copy(), + std::move(expectedColumnNames), std::move(expectedColumnTypes), clientContext); + auto bindData = func.bindFunc(clientContext, bindInput.get()); + // Bind input columns + expression_vector inputColumns; + for (auto i = 0u; i < bindData->columnTypes.size(); i++) { + inputColumns.push_back( + createVariable(bindData->columnNames[i], bindData->columnTypes[i])); + } + auto fileScanInfo = BoundFileScanInfo(func, std::move(bindData), inputColumns); + return std::make_unique(std::move(fileScanInfo)); + } + case ScanSourceType::QUERY: { + auto querySource = ku_dynamic_cast(source); + auto boundStatement = bind(*querySource->statement); + // Bind input columns. + auto columns = boundStatement->getStatementResult()->getColumns(); + if (columns.size() != expectedColumnNames.size()) { + throw BinderException( + stringFormat("Query returns {} columns but {} columns were expected.", + columns.size(), expectedColumnNames.size())); + } + for (auto i = 0u; i < columns.size(); ++i) { + expressionBinder.validateDataType(*columns[i], expectedColumnTypes[i]); + columns[i]->setAlias(expectedColumnNames[i]); + } + return std::make_unique(std::move(boundStatement)); + } + case ScanSourceType::OBJECT: { + auto objectSource = ku_dynamic_cast(source); + throw BinderException(stringFormat("Scan from external object {} is not supported.", + objectSource->objectName)); + } + default: + KU_UNREACHABLE; + } +} + } // namespace binder } // namespace kuzu diff --git a/src/binder/bind/bind_graph_pattern.cpp b/src/binder/bind/bind_graph_pattern.cpp index c3bd5c68ced..ccbece6cd5f 100644 --- a/src/binder/bind/bind_graph_pattern.cpp +++ b/src/binder/bind/bind_graph_pattern.cpp @@ -3,6 +3,7 @@ #include "binder/expression/path_expression.h" #include "binder/expression/property_expression.h" #include "binder/expression_visitor.h" +#include "catalog/catalog.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "catalog/catalog_entry/rel_group_catalog_entry.h" @@ -11,7 +12,6 @@ #include "common/keyword/rdf_keyword.h" #include "common/string_format.h" #include "function/cast/functions/cast_from_string_functions.h" -#include "main/client_context.h" using namespace kuzu::common; using namespace kuzu::parser; @@ -56,15 +56,15 @@ QueryGraph Binder::bindPatternElement(const PatternElement& patternElement) { if (patternElement.hasPathName()) { auto pathName = patternElement.getPathName(); auto pathExpression = createPath(pathName, nodeAndRels); - scope->addExpression(pathName, pathExpression); + scope.addExpression(pathName, pathExpression); } return queryGraph; } -static std::unique_ptr getRecursiveRelLogicalType( - const LogicalType& nodeType, const LogicalType& relType) { - auto nodesType = LogicalType::VAR_LIST(nodeType.copy()); - auto relsType = LogicalType::VAR_LIST(relType.copy()); +static std::unique_ptr getRecursiveRelLogicalType(const LogicalType& nodeType, + const LogicalType& relType) { + auto nodesType = LogicalType::LIST(nodeType.copy()); + auto relsType = LogicalType::LIST(relType.copy()); std::vector recursiveRelFields; recursiveRelFields.emplace_back(InternalKeyword::NODES, std::move(nodesType)); recursiveRelFields.emplace_back(InternalKeyword::RELS, std::move(relsType)); @@ -84,8 +84,8 @@ static void extraFieldFromStructType(const LogicalType& structType, } } -std::shared_ptr Binder::createPath( - const std::string& pathName, const expression_vector& children) { +std::shared_ptr Binder::createPath(const std::string& pathName, + const expression_vector& children) { std::unordered_set nodeFieldNameSet; std::vector nodeFieldNames; std::vector> nodeFieldTypes; @@ -95,19 +95,19 @@ std::shared_ptr Binder::createPath( for (auto& child : children) { if (ExpressionUtil::isNodePattern(*child)) { auto node = ku_dynamic_cast(child.get()); - extraFieldFromStructType( - node->getDataType(), nodeFieldNameSet, nodeFieldNames, nodeFieldTypes); + extraFieldFromStructType(node->getDataType(), nodeFieldNameSet, nodeFieldNames, + nodeFieldTypes); } else if (ExpressionUtil::isRelPattern(*child)) { auto rel = ku_dynamic_cast(child.get()); - extraFieldFromStructType( - rel->getDataType(), relFieldNameSet, relFieldNames, relFieldTypes); + extraFieldFromStructType(rel->getDataType(), relFieldNameSet, relFieldNames, + relFieldTypes); } else if (ExpressionUtil::isRecursiveRelPattern(*child)) { auto recursiveRel = ku_dynamic_cast(child.get()); auto recursiveInfo = recursiveRel->getRecursiveInfo(); extraFieldFromStructType(recursiveInfo->node->getDataType(), nodeFieldNameSet, nodeFieldNames, nodeFieldTypes); - extraFieldFromStructType( - recursiveInfo->rel->getDataType(), relFieldNameSet, relFieldNames, relFieldTypes); + extraFieldFromStructType(recursiveInfo->rel->getDataType(), relFieldNameSet, + relFieldNames, relFieldTypes); } else { KU_UNREACHABLE; } @@ -172,8 +172,8 @@ std::shared_ptr Binder::bindQueryRel(const RelPattern& relPattern const std::shared_ptr& leftNode, const std::shared_ptr& rightNode, QueryGraph& queryGraph) { auto parsedName = relPattern.getVariableName(); - if (scope->contains(parsedName)) { - auto prevVariable = scope->getExpression(parsedName); + if (scope.contains(parsedName)) { + auto prevVariable = scope.getExpression(parsedName); auto expectedDataType = QueryRelTypeUtils::isRecursive(relPattern.getRelType()) ? LogicalTypeID::RECURSIVE_REL : LogicalTypeID::REL; @@ -212,8 +212,8 @@ std::shared_ptr Binder::bindQueryRel(const RelPattern& relPattern if (QueryRelTypeUtils::isRecursive(relPattern.getRelType())) { queryRel = createRecursiveQueryRel(relPattern, tableIDs, srcNode, dstNode, directionType); } else { - queryRel = createNonRecursiveQueryRel( - relPattern.getVariableName(), tableIDs, srcNode, dstNode, directionType); + queryRel = createNonRecursiveQueryRel(relPattern.getVariableName(), tableIDs, srcNode, + dstNode, directionType); for (auto& [propertyName, rhs] : relPattern.getPropertyKeyVals()) { auto boundLhs = expressionBinder.bindNodeOrRelPropertyExpression(*queryRel, propertyName); @@ -224,7 +224,7 @@ std::shared_ptr Binder::bindQueryRel(const RelPattern& relPattern } queryRel->setAlias(parsedName); if (!parsedName.empty()) { - scope->addExpression(parsedName, queryRel); + scope.addExpression(parsedName, queryRel); } queryGraph.addQueryRel(queryRel); return queryRel; @@ -245,9 +245,10 @@ std::shared_ptr Binder::createNonRecursiveQueryRel(const std::str // expression to mock as if predicate IRI exists in rel table. common::table_id_set_t rdfGraphTableIDSet; common::table_id_set_t nonRdfRelTableIDSet; + auto catalog = clientContext->getCatalog(); for (auto& tableID : relTableIDs) { bool isRdfRelTable = false; - for (auto& rdfGraphEntry : catalog.getRdfGraphEntries(clientContext->getTx())) { + for (auto& rdfGraphEntry : catalog->getRdfGraphEntries(clientContext->getTx())) { if (rdfGraphEntry->isParent(tableID)) { KU_ASSERT(rdfGraphEntry->getTableType() == TableType::RDF); rdfGraphTableIDSet.insert(rdfGraphEntry->getTableID()); @@ -261,10 +262,10 @@ std::shared_ptr Binder::createNonRecursiveQueryRel(const std::str if (!rdfGraphTableIDSet.empty()) { if (!nonRdfRelTableIDSet.empty()) { auto relTableName = - catalog.getTableCatalogEntry(clientContext->getTx(), *nonRdfRelTableIDSet.begin()) + catalog->getTableCatalogEntry(clientContext->getTx(), *nonRdfRelTableIDSet.begin()) ->getName(); auto rdfGraphName = - catalog.getTableCatalogEntry(clientContext->getTx(), *rdfGraphTableIDSet.begin()) + catalog->getTableCatalogEntry(clientContext->getTx(), *rdfGraphTableIDSet.begin()) ->getName(); throw BinderException(stringFormat( "Relationship pattern {} contains both PropertyGraph relationship " @@ -274,7 +275,7 @@ std::shared_ptr Binder::createNonRecursiveQueryRel(const std::str } common::table_id_vector_t resourceTableIDs; for (auto& tableID : rdfGraphTableIDSet) { - auto entry = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto entry = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); auto rdfGraphEntry = ku_dynamic_cast(entry); resourceTableIDs.push_back(rdfGraphEntry->getResourceTableID()); @@ -286,7 +287,7 @@ std::shared_ptr Binder::createNonRecursiveQueryRel(const std::str std::vector resourceTableSchemas; for (auto tableID : resourceTableIDs) { resourceTableSchemas.push_back( - catalog.getTableCatalogEntry(clientContext->getTx(), tableID)); + catalog->getTableCatalogEntry(clientContext->getTx(), tableID)); } // Mock existence of pIRI property. auto pIRI = createPropertyExpression(std::string(rdf::IRI), queryRel->getUniqueName(), @@ -298,8 +299,8 @@ std::shared_ptr Binder::createNonRecursiveQueryRel(const std::str fields.emplace_back(InternalKeyword::DST, LogicalType::INTERNAL_ID()); // Bind internal expressions. queryRel->setLabelExpression(expressionBinder.bindLabelFunction(*queryRel)); - fields.emplace_back( - InternalKeyword::LABEL, queryRel->getLabelExpression()->getDataType().copy()); + fields.emplace_back(InternalKeyword::LABEL, + queryRel->getLabelExpression()->getDataType().copy()); // Bind properties. for (auto& expression : queryRel->getPropertyExprsRef()) { auto property = ku_dynamic_cast(expression.get()); @@ -310,12 +311,12 @@ std::shared_ptr Binder::createNonRecursiveQueryRel(const std::str return queryRel; } -static void bindRecursiveRelProjectionList( - const expression_vector& projectionList, std::vector& fields) { +static void bindRecursiveRelProjectionList(const expression_vector& projectionList, + std::vector& fields) { for (auto& expression : projectionList) { if (expression->expressionType != common::ExpressionType::PROPERTY) { - throw BinderException(stringFormat( - "Unsupported projection item {} on recursive rel.", expression->toString())); + throw BinderException(stringFormat("Unsupported projection item {} on recursive rel.", + expression->toString())); } auto property = ku_dynamic_cast(expression.get()); fields.emplace_back(property->getPropertyName(), property->getDataType().copy()); @@ -329,21 +330,21 @@ std::shared_ptr Binder::createRecursiveQueryRel(const parser::Rel std::unordered_set nodeTableIDs; for (auto relTableID : relTableIDs) { auto relTableEntry = ku_dynamic_cast( - catalog.getTableCatalogEntry(clientContext->getTx(), relTableID)); + clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), relTableID)); nodeTableIDs.insert(relTableEntry->getSrcTableID()); nodeTableIDs.insert(relTableEntry->getDstTableID()); } auto recursivePatternInfo = relPattern.getRecursiveInfo(); auto prevScope = saveScope(); - scope->clear(); + scope.clear(); // Bind intermediate node. auto node = createQueryNode(recursivePatternInfo->nodeName, std::vector{nodeTableIDs.begin(), nodeTableIDs.end()}); - scope->addExpression(node->toString(), node); + scope.addExpression(node->toString(), node); std::vector nodeFields; nodeFields.emplace_back(InternalKeyword::ID, node->getInternalID()->getDataType().copy()); - nodeFields.emplace_back( - InternalKeyword::LABEL, node->getLabelExpression()->getDataType().copy()); + nodeFields.emplace_back(InternalKeyword::LABEL, + node->getLabelExpression()->getDataType().copy()); expression_vector nodeProjectionList; if (!recursivePatternInfo->hasProjection) { for (auto& expression : node->getPropertyExprsRef()) { @@ -360,9 +361,9 @@ std::shared_ptr Binder::createRecursiveQueryRel(const parser::Rel auto nodeCopy = createQueryNode(recursivePatternInfo->nodeName, std::vector{nodeTableIDs.begin(), nodeTableIDs.end()}); // Bind intermediate rel - auto rel = createNonRecursiveQueryRel( - recursivePatternInfo->relName, tableIDs, nullptr, nullptr, directionType); - scope->addExpression(rel->toString(), rel); + auto rel = createNonRecursiveQueryRel(recursivePatternInfo->relName, tableIDs, nullptr, nullptr, + directionType); + scope.addExpression(rel->toString(), rel); expression_vector relProjectionList; if (!recursivePatternInfo->hasProjection) { for (auto& expression : rel->getPropertyExprsRef()) { @@ -391,8 +392,8 @@ std::shared_ptr Binder::createRecursiveQueryRel(const parser::Rel auto boundRhs = expressionBinder.bindExpression(*rhs); boundRhs = ExpressionBinder::implicitCastIfNecessary(boundRhs, boundLhs->dataType); auto predicate = expressionBinder.createEqualityComparisonExpression(boundLhs, boundRhs); - relPredicate = expressionBinder.combineBooleanExpressions( - ExpressionType::AND, relPredicate, predicate); + relPredicate = expressionBinder.combineBooleanExpressions(ExpressionType::AND, relPredicate, + predicate); } // Bind predicates in (r, n | WHERE ) std::shared_ptr nodePredicate; @@ -408,19 +409,19 @@ std::shared_ptr Binder::createRecursiveQueryRel(const parser::Rel throw BinderException(stringFormat("Cannot evaluate {} in recursive pattern {}.", predicate->toString(), relPattern.getVariableName())); } else if (dependOnNode) { - nodePredicate = expressionBinder.combineBooleanExpressions( - ExpressionType::AND, nodePredicate, predicate); + nodePredicate = expressionBinder.combineBooleanExpressions(ExpressionType::AND, + nodePredicate, predicate); } else { - relPredicate = expressionBinder.combineBooleanExpressions( - ExpressionType::AND, relPredicate, predicate); + relPredicate = expressionBinder.combineBooleanExpressions(ExpressionType::AND, + relPredicate, predicate); } } } auto nodePredicateExecutionFlag = expressionBinder.createVariableExpression( LogicalType{LogicalTypeID::BOOL}, std::string(InternalKeyword::ANONYMOUS)); if (nodePredicate != nullptr) { - nodePredicate = expressionBinder.combineBooleanExpressions( - ExpressionType::OR, nodePredicate, nodePredicateExecutionFlag); + nodePredicate = expressionBinder.combineBooleanExpressions(ExpressionType::OR, + nodePredicate, nodePredicateExecutionFlag); } // Bind rel restoreScope(std::move(prevScope)); @@ -454,20 +455,20 @@ std::pair Binder::bindVariableLengthRelBound( function::CastString::operation( ku_string_t{recursiveInfo->lowerBound.c_str(), recursiveInfo->lowerBound.length()}, lowerBound); - auto upperBound = clientContext->varLengthExtendMaxDepth; + auto maxDepth = clientContext->getClientConfig()->varLengthMaxDepth; + auto upperBound = maxDepth; if (!recursiveInfo->upperBound.empty()) { function::CastString::operation( ku_string_t{recursiveInfo->upperBound.c_str(), recursiveInfo->upperBound.length()}, upperBound); } if (lowerBound > upperBound) { - throw BinderException( - "Lower bound of rel " + relPattern.getVariableName() + " is greater than upperBound."); + throw BinderException(stringFormat("Lower bound of rel {} is greater than upperBound.", + relPattern.getVariableName())); } - if (upperBound > clientContext->varLengthExtendMaxDepth) { - throw BinderException( - "Upper bound of rel " + relPattern.getVariableName() + - " exceeds maximum: " + std::to_string(clientContext->varLengthExtendMaxDepth) + "."); + if (upperBound > maxDepth) { + throw BinderException(stringFormat("Upper bound of rel {} exceeds maximum: {}.", + relPattern.getVariableName(), std::to_string(maxDepth))); } if ((relPattern.getRelType() == QueryRelType::ALL_SHORTEST || relPattern.getRelType() == QueryRelType::SHORTEST) && @@ -478,40 +479,56 @@ std::pair Binder::bindVariableLengthRelBound( } void Binder::bindQueryRelProperties(RelExpression& rel) { + auto catalog = clientContext->getCatalog(); std::vector tableCatalogEntries; for (auto tableID : rel.getTableIDs()) { - tableCatalogEntries.push_back( - catalog.getTableCatalogEntry(clientContext->getTx(), tableID)); + auto entry = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); + tableCatalogEntries.push_back(entry); } auto propertyNames = getPropertyNames(tableCatalogEntries); for (auto& propertyName : propertyNames) { - rel.addPropertyExpression( - propertyName, createPropertyExpression(propertyName, rel.getUniqueName(), - rel.getVariableName(), tableCatalogEntries)); + rel.addPropertyExpression(propertyName, + createPropertyExpression(propertyName, rel.getUniqueName(), rel.getVariableName(), + tableCatalogEntries)); } } -std::shared_ptr Binder::bindQueryNode( - const NodePattern& nodePattern, QueryGraph& queryGraph) { +static std::unique_ptr createInternalNodeIDExpression(const NodeExpression& node) { + std::unordered_map propertyIDPerTable; + for (auto tableID : node.getTableIDs()) { + propertyIDPerTable.insert({tableID, INVALID_PROPERTY_ID}); + } + return std::make_unique(*LogicalType::INTERNAL_ID(), InternalKeyword::ID, + node.getUniqueName(), node.getVariableName(), std::move(propertyIDPerTable), + false /* isPrimaryKey */); +} + +std::shared_ptr Binder::bindQueryNode(const NodePattern& nodePattern, + QueryGraph& queryGraph) { auto parsedName = nodePattern.getVariableName(); std::shared_ptr queryNode; - if (scope->contains(parsedName)) { // bind to node in scope - auto prevVariable = scope->getExpression(parsedName); + if (scope.contains(parsedName)) { // bind to node in scope + auto prevVariable = scope.getExpression(parsedName); if (!ExpressionUtil::isNodePattern(*prevVariable)) { - throw BinderException(stringFormat("Cannot bind {} as node pattern.", parsedName)); - } - queryNode = static_pointer_cast(prevVariable); - // E.g. MATCH (a:person) MATCH (a:organisation) - // We bind to a single node with both labels - if (!nodePattern.getTableNames().empty()) { - auto otherTableIDs = bindTableIDs(nodePattern.getTableNames(), true); - auto otherNodeTableIDs = getNodeTableIDs(otherTableIDs); - queryNode->addTableIDs(otherNodeTableIDs); + if (!scope.hasNodeReplacement(parsedName)) { + throw BinderException(stringFormat("Cannot bind {} as node pattern.", parsedName)); + } + queryNode = scope.getNodeReplacement(parsedName); + queryNode->addPropertyDataExpr(InternalKeyword::ID, queryNode->getInternalID()); + } else { + queryNode = std::static_pointer_cast(prevVariable); + // E.g. MATCH (a:person) MATCH (a:organisation) + // We bind to a single node with both labels + if (!nodePattern.getTableNames().empty()) { + auto otherTableIDs = bindTableIDs(nodePattern.getTableNames(), true); + auto otherNodeTableIDs = getNodeTableIDs(otherTableIDs); + queryNode->addTableIDs(otherNodeTableIDs); + } } } else { queryNode = createQueryNode(nodePattern); if (!parsedName.empty()) { - scope->addExpression(parsedName, queryNode); + scope.addExpression(parsedName, queryNode); } } for (auto& [propertyName, rhs] : nodePattern.getPropertyKeyVals()) { @@ -529,8 +546,8 @@ std::shared_ptr Binder::createQueryNode(const NodePattern& nodeP return createQueryNode(parsedName, bindTableIDs(nodePattern.getTableNames(), true)); } -std::shared_ptr Binder::createQueryNode( - const std::string& parsedName, const std::vector& tableIDs) { +std::shared_ptr Binder::createQueryNode(const std::string& parsedName, + const std::vector& tableIDs) { auto nodeTableIDs = getNodeTableIDs(tableIDs); auto queryNode = make_shared(LogicalType(LogicalTypeID::NODE), getUniqueExpressionName(parsedName), parsedName, nodeTableIDs); @@ -538,7 +555,7 @@ std::shared_ptr Binder::createQueryNode( std::vector fieldNames; std::vector> fieldTypes; // Bind internal expressions - queryNode->setInternalID(expressionBinder.createInternalNodeIDExpression(*queryNode)); + queryNode->setInternalID(createInternalNodeIDExpression(*queryNode)); queryNode->setLabelExpression(expressionBinder.bindLabelFunction(*queryNode)); fieldNames.emplace_back(InternalKeyword::ID); fieldNames.emplace_back(InternalKeyword::LABEL); @@ -557,32 +574,34 @@ std::shared_ptr Binder::createQueryNode( } void Binder::bindQueryNodeProperties(NodeExpression& node) { - auto tableSchemas = catalog.getTableSchemas(clientContext->getTx(), node.getTableIDs()); + auto tableSchemas = + clientContext->getCatalog()->getTableSchemas(clientContext->getTx(), node.getTableIDs()); auto propertyNames = getPropertyNames(tableSchemas); for (auto& propertyName : propertyNames) { - auto property = createPropertyExpression( - propertyName, node.getUniqueName(), node.getVariableName(), tableSchemas); + auto property = createPropertyExpression(propertyName, node.getUniqueName(), + node.getVariableName(), tableSchemas); node.addPropertyExpression(propertyName, std::move(property)); } } -std::vector Binder::bindTableIDs( - const std::vector& tableNames, bool nodePattern) { +std::vector Binder::bindTableIDs(const std::vector& tableNames, + bool nodePattern) { auto tx = clientContext->getTx(); + auto catalog = clientContext->getCatalog(); std::unordered_set tableIDSet; if (tableNames.empty()) { // Rewrite empty table names as all tables. if (nodePattern) { // Fill all node table schemas to node pattern. - if (!catalog.containsNodeTable(tx)) { + if (!catalog->containsNodeTable(tx)) { throw BinderException("No node table exists in database."); } - for (auto tableID : catalog.getNodeTableIDs(tx)) { + for (auto tableID : catalog->getNodeTableIDs(tx)) { tableIDSet.insert(tableID); } } else { // Fill all rel table schemas to rel pattern. - if (!catalog.containsRelTable(tx)) { + if (!catalog->containsRelTable(tx)) { throw BinderException("No rel table exists in database."); } - for (auto tableID : catalog.getRelTableIDs(tx)) { + for (auto tableID : catalog->getRelTableIDs(tx)) { tableIDSet.insert(tableID); } } @@ -612,7 +631,8 @@ std::vector Binder::getNodeTableIDs(const std::vector& t } std::vector Binder::getNodeTableIDs(table_id_t tableID) { - auto tableSchema = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto tableSchema = + clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), tableID); switch (tableSchema->getTableType()) { case TableType::NODE: { return {tableID}; @@ -639,7 +659,7 @@ std::vector Binder::getRelTableIDs(const std::vector& ta } std::vector Binder::getRelTableIDs(table_id_t tableID) { - auto entry = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto entry = clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), tableID); switch (entry->getTableType()) { case TableType::RDF: { auto rdfEntry = ku_dynamic_cast(entry); diff --git a/src/binder/bind/bind_import_database.cpp b/src/binder/bind/bind_import_database.cpp index 633e271afe9..83d4468cbfa 100644 --- a/src/binder/bind/bind_import_database.cpp +++ b/src/binder/bind/bind_import_database.cpp @@ -1,6 +1,14 @@ +#include + #include "binder/binder.h" #include "binder/copy/bound_import_database.h" +#include "common/cast.h" +#include "common/copier_config/csv_reader_config.h" #include "common/exception/binder.h" +#include "common/file_system/virtual_file_system.h" +#include "main/client_context.h" +#include "parser/copy.h" +#include "parser/parser.h" #include "parser/port_db.h" using namespace kuzu::common; @@ -9,8 +17,8 @@ using namespace kuzu::parser; namespace kuzu { namespace binder { -std::string getFilePath( - common::VirtualFileSystem* vfs, const std::string boundFilePath, const std::string fileName) { +static std::string getQueryFromFile(common::VirtualFileSystem* vfs, const std::string boundFilePath, + const std::string fileName) { auto filePath = vfs->joinPath(boundFilePath, fileName); if (!vfs->fileOrPathExists(filePath)) { throw BinderException(stringFormat("File {} does not exist.", filePath)); @@ -29,13 +37,32 @@ std::string getFilePath( std::unique_ptr Binder::bindImportDatabaseClause(const Statement& statement) { auto& importDatabaseStatement = ku_dynamic_cast(statement); auto boundFilePath = importDatabaseStatement.getFilePath(); - if (!vfs->fileOrPathExists(boundFilePath)) { + auto fs = clientContext->getVFSUnsafe(); + if (!fs->fileOrPathExists(boundFilePath)) { throw BinderException(stringFormat("Directory {} does not exist.", boundFilePath)); } std::string finalQueryStatements; - finalQueryStatements += getFilePath(vfs, boundFilePath, ImportDBConstants::SCHEMA_NAME); - finalQueryStatements += getFilePath(vfs, boundFilePath, ImportDBConstants::COPY_NAME); - finalQueryStatements += getFilePath(vfs, boundFilePath, ImportDBConstants::MACRO_NAME); + finalQueryStatements += getQueryFromFile(fs, boundFilePath, ImportDBConstants::SCHEMA_NAME); + // replace the path in copy from statement with the bound path + auto copyQuery = getQueryFromFile(fs, boundFilePath, ImportDBConstants::COPY_NAME); + auto parsedStatements = Parser::parseQuery(copyQuery); + for (auto& parsedStatement : parsedStatements) { + KU_ASSERT(parsedStatement->getStatementType() == StatementType::COPY_FROM); + auto copyFromStatement = + ku_dynamic_cast(parsedStatement.get()); + KU_ASSERT(copyFromStatement->getSource()->type == common::ScanSourceType::FILE); + auto filePaths = ku_dynamic_cast( + copyFromStatement->getSource()) + ->filePaths; + KU_ASSERT(filePaths.size() == 1); + auto copyFilePath = boundFilePath + "/" + filePaths[0]; + auto csvConfig = CSVReaderConfig::construct( + bindParsingOptions(copyFromStatement->getParsingOptionsRef())); + auto csvQuery = stringFormat("COPY {} FROM \"{}\" {};", copyFromStatement->getTableName(), + copyFilePath, csvConfig.option.toCypher()); + finalQueryStatements += csvQuery; + } + finalQueryStatements += getQueryFromFile(fs, boundFilePath, ImportDBConstants::MACRO_NAME); return std::make_unique(boundFilePath, finalQueryStatements); } } // namespace binder diff --git a/src/binder/bind/bind_projection_clause.cpp b/src/binder/bind/bind_projection_clause.cpp index 63e0e9c41bf..eec42bf2261 100644 --- a/src/binder/bind/bind_projection_clause.cpp +++ b/src/binder/bind/bind_projection_clause.cpp @@ -54,7 +54,7 @@ BoundWithClause Binder::bindWithClause(const WithClause& withClause) { auto boundProjectionBody = bindProjectionBody(*projectionBody, rewriteProjectionInWithClause(projectionExpressions)); validateOrderByFollowedBySkipOrLimitInWithClause(boundProjectionBody); - scope->clear(); + scope.clear(); addExpressionsToScope(projectionExpressions); auto boundWithClause = BoundWithClause(std::move(boundProjectionBody)); if (withClause.hasWhereExpression()) { @@ -75,9 +75,9 @@ BoundReturnClause Binder::bindReturnClause(const ReturnClause& returnClause) { return BoundReturnClause(std::move(boundProjectionBody), std::move(statementResult)); } -static bool isAggregateExpression( - const std::shared_ptr& expression, BinderScope* scope) { - if (expression->hasAlias() && scope->contains(expression->getAlias())) { +static bool isAggregateExpression(const std::shared_ptr& expression, + const BinderScope& scope) { + if (expression->hasAlias() && scope.contains(expression->getAlias())) { return false; } if (expression->expressionType == ExpressionType::AGGREGATE_FUNCTION) { @@ -91,10 +91,10 @@ static bool isAggregateExpression( return false; } -static expression_vector getAggregateExpressions( - const std::shared_ptr& expression, BinderScope* scope) { +static expression_vector getAggregateExpressions(const std::shared_ptr& expression, + const BinderScope& scope) { expression_vector result; - if (expression->hasAlias() && scope->contains(expression->getAlias())) { + if (expression->hasAlias() && scope.contains(expression->getAlias())) { return result; } if (expression->expressionType == ExpressionType::AGGREGATE_FUNCTION) { @@ -109,16 +109,16 @@ static expression_vector getAggregateExpressions( return result; } -BoundProjectionBody Binder::bindProjectionBody( - const parser::ProjectionBody& projectionBody, const expression_vector& projectionExpressions) { +BoundProjectionBody Binder::bindProjectionBody(const parser::ProjectionBody& projectionBody, + const expression_vector& projectionExpressions) { auto boundProjectionBody = BoundProjectionBody(projectionBody.getIsDistinct(), projectionExpressions); // Bind group by & aggregate. expression_vector groupByExpressions; expression_vector aggregateExpressions; for (auto& expression : projectionExpressions) { - if (isAggregateExpression(expression, scope.get())) { - for (auto& agg : getAggregateExpressions(expression, scope.get())) { + if (isAggregateExpression(expression, scope)) { + for (auto& agg : getAggregateExpressions(expression, scope)) { aggregateExpressions.push_back(agg); } } else { @@ -164,8 +164,8 @@ BoundProjectionBody Binder::bindProjectionBody( } } } - boundProjectionBody.setOrderByExpressions( - std::move(orderByExpressions), projectionBody.getSortOrders()); + boundProjectionBody.setOrderByExpressions(std::move(orderByExpressions), + projectionBody.getSortOrders()); } // Bind skip if (projectionBody.hasSkipExpression()) { @@ -186,11 +186,11 @@ expression_vector Binder::bindProjectionExpressions( for (auto& expression : projectionExpressions) { if (expression->getExpressionType() == ExpressionType::STAR) { // Rewrite star expression as all expression in scope. - if (scope->empty()) { + if (scope.empty()) { throw BinderException( "RETURN or WITH * is not allowed when there are no variables in scope."); } - for (auto& expr : scope->getExpressions()) { + for (auto& expr : scope.getExpressions()) { result.push_back(expr); } } else if (expression->getExpressionType() == ExpressionType::PROPERTY) { @@ -207,7 +207,6 @@ expression_vector Binder::bindProjectionExpressions( result.push_back(expressionBinder.bindExpression(*expression)); } } - resolveAnyDataTypeWithDefaultType(result); validateProjectionColumnNamesAreUnique(result); return result; } @@ -224,7 +223,6 @@ expression_vector Binder::bindOrderByExpressions( } boundOrderByExpressions.push_back(std::move(boundExpression)); } - resolveAnyDataTypeWithDefaultType(boundOrderByExpressions); return boundOrderByExpressions; } @@ -260,15 +258,7 @@ void Binder::addExpressionsToScope(const expression_vector& projectionExpression for (auto& expression : projectionExpressions) { // In RETURN clause, if expression is not aliased, its input name will serve its alias. auto alias = expression->hasAlias() ? expression->getAlias() : expression->toString(); - scope->addExpression(alias, expression); - } -} - -void Binder::resolveAnyDataTypeWithDefaultType(const expression_vector& expressions) { - for (auto& expression : expressions) { - if (expression->dataType.getLogicalTypeID() == LogicalTypeID::ANY) { - ExpressionBinder::implicitCastIfNecessary(expression, LogicalTypeID::STRING); - } + scope.addExpression(alias, expression); } } diff --git a/src/binder/bind/bind_query.cpp b/src/binder/bind/bind_query.cpp index a2511e07373..5a56b582278 100644 --- a/src/binder/bind/bind_query.cpp +++ b/src/binder/bind/bind_query.cpp @@ -23,8 +23,8 @@ void validateUnionColumnsOfTheSameType( // Check whether the dataTypes in union expressions are exactly the same in each single // query. for (auto j = 0u; j < columns.size(); j++) { - ExpressionBinder::validateExpectedDataType( - *otherColumns[j], columns[j]->dataType.getLogicalTypeID()); + ExpressionBinder::validateExpectedDataType(*otherColumns[j], + columns[j]->dataType.getLogicalTypeID()); } } } @@ -36,7 +36,7 @@ void validateIsAllUnionOrUnionAll(const BoundRegularQuery& regularQuery) { } if ((0 < unionAllExpressionCounter) && (unionAllExpressionCounter < regularQuery.getNumSingleQueries() - 1)) { - throw BinderException("Union and union all can't be used together."); + throw BinderException("Union and union all can not be used together."); } } @@ -45,15 +45,14 @@ std::unique_ptr Binder::bindQuery(const RegularQuery& regular for (auto i = 0u; i < regularQuery.getNumSingleQueries(); i++) { // Don't clear scope within bindSingleQuery() yet because it is also used for subquery // binding. - scope->clear(); + scope.clear(); normalizedSingleQueries.push_back(bindSingleQuery(*regularQuery.getSingleQuery(i))); } validateUnionColumnsOfTheSameType(normalizedSingleQueries); KU_ASSERT(!normalizedSingleQueries.empty()); - auto boundRegularQuery = std::make_unique( - regularQuery.getIsUnionAll(), normalizedSingleQueries[0].getStatementResult()->copy()); + auto boundRegularQuery = std::make_unique(regularQuery.getIsUnionAll(), + normalizedSingleQueries[0].getStatementResult()->copy()); for (auto& normalizedSingleQuery : normalizedSingleQueries) { - validateReadNotFollowUpdate(normalizedSingleQuery); boundRegularQuery->addSingleQuery(std::move(normalizedSingleQuery)); } validateIsAllUnionOrUnionAll(*boundRegularQuery); diff --git a/src/binder/bind/bind_reading_clause.cpp b/src/binder/bind/bind_reading_clause.cpp index 55ee466e8c4..c758ee92ada 100644 --- a/src/binder/bind/bind_reading_clause.cpp +++ b/src/binder/bind/bind_reading_clause.cpp @@ -4,11 +4,19 @@ #include "binder/query/reading_clause/bound_load_from.h" #include "binder/query/reading_clause/bound_match_clause.h" #include "binder/query/reading_clause/bound_unwind_clause.h" +#include "catalog/catalog.h" +#include "catalog/catalog_entry/table_catalog_entry.h" #include "common/exception/binder.h" +#include "common/exception/message.h" #include "common/string_format.h" +#include "common/string_utils.h" +#include "function/built_in_function_utils.h" #include "function/table/bind_input.h" -#include "main/client_context.h" +#include "main/attached_database.h" +#include "main/database.h" +#include "main/database_manager.h" #include "parser/expression/parsed_function_expression.h" +#include "parser/expression/parsed_variable_expression.h" #include "parser/query/reading_clause/in_query_call_clause.h" #include "parser/query/reading_clause/load_from.h" #include "parser/query/reading_clause/match_clause.h" @@ -88,8 +96,8 @@ void Binder::rewriteMatchPattern(BoundGraphPattern& boundGraphPattern) { expressionBinder.bindNodeOrRelPropertyExpression(*pattern, propertyName); auto predicate = expressionBinder.createEqualityComparisonExpression(propertyExpr, rhs); - where = expressionBinder.combineBooleanExpressions( - ExpressionType::AND, predicate, where); + where = expressionBinder.combineBooleanExpressions(ExpressionType::AND, predicate, + where); } } } @@ -99,11 +107,18 @@ void Binder::rewriteMatchPattern(BoundGraphPattern& boundGraphPattern) { std::unique_ptr Binder::bindUnwindClause(const ReadingClause& readingClause) { auto& unwindClause = ku_dynamic_cast(readingClause); auto boundExpression = expressionBinder.bindExpression(*unwindClause.getExpression()); - boundExpression = - ExpressionBinder::implicitCastIfNecessary(boundExpression, LogicalTypeID::VAR_LIST); - auto aliasExpression = createVariable( - unwindClause.getAlias(), *VarListType::getChildType(&boundExpression->dataType)); - return make_unique(std::move(boundExpression), std::move(aliasExpression)); + ExpressionBinder::validateDataType(*boundExpression, LogicalTypeID::LIST); + auto aliasName = unwindClause.getAlias(); + auto alias = createVariable(aliasName, *ListType::getChildType(&boundExpression->dataType)); + std::shared_ptr idExpr = nullptr; + if (scope.hasMemorizedTableIDs(boundExpression->getAlias())) { + auto tableIDs = scope.getMemorizedTableIDs(boundExpression->getAlias()); + auto node = createQueryNode(aliasName, tableIDs); + idExpr = node->getInternalID(); + scope.addNodeReplacement(node); + } + return make_unique(std::move(boundExpression), std::move(alias), + std::move(idExpr)); } std::unique_ptr Binder::bindInQueryCall(const ReadingClause& readingClause) { @@ -111,35 +126,60 @@ std::unique_ptr Binder::bindInQueryCall(const ReadingClause& auto expr = call.getFunctionExpression(); auto functionExpr = ku_dynamic_cast(expr); - std::vector inputValues; + // Bind parameters + std::unique_ptr replacementData; + expression_vector params; for (auto i = 0u; i < functionExpr->getNumChildren(); i++) { - auto parameter = expressionBinder.bindExpression(*functionExpr->getChild(i)); - if (parameter->expressionType != ExpressionType::LITERAL) { - throw BinderException{ - stringFormat("Cannot evaluate {} as a literal.", parameter->toString())}; + auto child = functionExpr->getChild(i); + try { + params.push_back(expressionBinder.bindExpression(*child)); + } catch (BinderException& exception) { + if (child->getExpressionType() != ExpressionType::VARIABLE) { + throw BinderException(exception.what()); // Cannot replace. Rethrow. + } + // Try replacement. + auto varExpr = ku_dynamic_cast(child); + auto var = varExpr->getVariableName(); + replacementData = clientContext->tryReplace(var); + if (replacementData == nullptr) { // Replacement fail. + throw BinderException(ExceptionMessage::variableNotInScope(var)); + } + } + } + TableFunction tableFunction; + std::unique_ptr bindData; + if (replacementData) { + tableFunction = replacementData->func; + bindData = tableFunction.bindFunc(clientContext, &replacementData->bindInput); + } else { + std::vector inputValues; + std::vector inputTypes; + for (auto& param : params) { + if (param->expressionType != ExpressionType::LITERAL) { + throw BinderException{ + stringFormat("Cannot evaluate {} as a literal.", param->toString())}; + } + auto literalExpr = + ku_dynamic_cast(param.get()); + inputTypes.push_back(literalExpr->getDataType()); + inputValues.push_back(*literalExpr->getValue()); } - auto literalExpr = - ku_dynamic_cast(parameter.get()); - inputValues.push_back(*literalExpr->getValue()); - } - std::vector inputTypes; - for (auto& val : inputValues) { - inputTypes.push_back(*val.getDataType()); - } - auto func = BuiltInFunctionsUtils::matchFunction( - functionExpr->getFunctionName(), inputTypes, catalog.getFunctions(clientContext->getTx())); - auto tableFunc = ku_dynamic_cast(func); - auto bindInput = std::make_unique(); - bindInput->inputs = std::move(inputValues); - auto bindData = tableFunc->bindFunc(clientContext, bindInput.get()); + auto functions = clientContext->getCatalog()->getFunctions(clientContext->getTx()); + auto func = BuiltInFunctionsUtils::matchFunction(functionExpr->getFunctionName(), + inputTypes, functions); + tableFunction = *ku_dynamic_cast(func); + auto bindInput = function::TableFuncBindInput(); + bindInput.inputs = std::move(inputValues); + bindData = tableFunction.bindFunc(clientContext, &bindInput); + } expression_vector columns; for (auto i = 0u; i < bindData->columnTypes.size(); i++) { columns.push_back(createVariable(bindData->columnNames[i], bindData->columnTypes[i])); } - auto offset = expressionBinder.createVariableExpression( - *LogicalType::INT64(), std::string(InternalKeyword::ROW_OFFSET)); - auto boundInQueryCall = std::make_unique( - tableFunc, std::move(bindData), std::move(columns), offset); + auto offset = expressionBinder.createVariableExpression(*LogicalType::INT64(), + std::string(InternalKeyword::ROW_OFFSET)); + auto boundInQueryCall = std::make_unique(tableFunction, std::move(bindData), + std::move(columns), offset); if (call.hasWherePredicate()) { auto wherePredicate = expressionBinder.bindExpression(*call.getWherePredicate()); boundInQueryCall->setPredicate(std::move(wherePredicate)); @@ -149,21 +189,42 @@ std::unique_ptr Binder::bindInQueryCall(const ReadingClause& std::unique_ptr Binder::bindLoadFrom(const ReadingClause& readingClause) { auto& loadFrom = ku_dynamic_cast(readingClause); - function::TableFunction* scanFunction; - std::unique_ptr bindInput; - if (loadFrom.hasObjectName()) { - auto objectName = loadFrom.getObjectname(); - auto objectExpr = expressionBinder.bindVariableExpression(objectName); - auto literalExpr = - ku_dynamic_cast(objectExpr.get()); - auto func = BuiltInFunctionsUtils::matchFunction(READ_PANDAS_FUNC_NAME, - std::vector{objectExpr->getDataType()}, - catalog.getFunctions(clientContext->getTx())); - scanFunction = ku_dynamic_cast(func); - bindInput = std::make_unique(); - bindInput->inputs.push_back(*literalExpr->getValue()); - } else { - auto filePaths = bindFilePaths(loadFrom.getFilePaths()); + TableFunction scanFunction; + std::unique_ptr bindData; + auto source = loadFrom.getSource(); + switch (source->type) { + case ScanSourceType::OBJECT: { + auto objectSource = ku_dynamic_cast(source); + auto objectName = objectSource->objectName; + if (objectName.find("_") == std::string::npos) { + // Bind table + auto replacementData = clientContext->tryReplace(objectName); + if (replacementData == nullptr) { + throw BinderException(ExceptionMessage::variableNotInScope(objectName)); + } + scanFunction = replacementData->func; + bindData = scanFunction.bindFunc(clientContext, &replacementData->bindInput); + } else { + auto dbName = common::StringUtils::split(objectName, "_")[0]; + auto attachedDB = + clientContext->getDatabase()->getDatabaseManagerUnsafe()->getAttachedDatabase( + dbName); + if (attachedDB == nullptr) { + throw BinderException{ + common::stringFormat("No database named {} has been attached.", dbName)}; + } + auto tableName = common::StringUtils::split(objectName, "_")[1]; + auto tableID = attachedDB->getCatalogContent()->getTableID(tableName); + auto tableCatalogEntry = ku_dynamic_cast( + attachedDB->getCatalogContent()->getTableCatalogEntry(tableID)); + scanFunction = tableCatalogEntry->getScanFunction(); + auto bindInput = function::TableFuncBindInput(); + bindData = scanFunction.bindFunc(clientContext, &bindInput); + } + } break; + case ScanSourceType::FILE: { + auto fileSource = ku_dynamic_cast(source); + auto filePaths = bindFilePaths(fileSource->filePaths); auto fileType = bindFileType(filePaths); auto readerConfig = std::make_unique(fileType, std::move(filePaths)); readerConfig->options = bindParsingOptions(loadFrom.getParsingOptionsRef()); @@ -181,27 +242,24 @@ std::unique_ptr Binder::bindLoadFrom(const ReadingClause& re } // Bind columns from input. std::vector expectedColumnNames; - std::vector expectedColumnTypes; + std::vector expectedColumnTypes; for (auto& [name, type] : loadFrom.getColumnNameDataTypesRef()) { expectedColumnNames.push_back(name); expectedColumnTypes.push_back(*bindDataType(type)); } scanFunction = getScanFunction(readerConfig->fileType, *readerConfig); - auto bindInput_ = std::make_unique(readerConfig->copy()); - bindInput_->expectedColumnNames = std::move(expectedColumnNames); - bindInput_->expectedColumnTypes = std::move(expectedColumnTypes); - bindInput_->context = clientContext; - bindInput = std::move(bindInput_); + auto bindInput = ScanTableFuncBindInput(readerConfig->copy(), + std::move(expectedColumnNames), std::move(expectedColumnTypes), clientContext); + bindData = scanFunction.bindFunc(clientContext, &bindInput); + } break; + default: + throw BinderException(stringFormat("LOAD FROM subquery is not supported.")); } - auto bindData = scanFunction->bindFunc(clientContext, bindInput.get()); expression_vector columns; for (auto i = 0u; i < bindData->columnTypes.size(); i++) { columns.push_back(createVariable(bindData->columnNames[i], bindData->columnTypes[i])); } - auto offset = expressionBinder.createVariableExpression( - LogicalType(LogicalTypeID::INT64), std::string(InternalKeyword::ROW_OFFSET)); - auto info = - BoundFileScanInfo(scanFunction, std::move(bindData), std::move(columns), std::move(offset)); + auto info = BoundFileScanInfo(scanFunction, std::move(bindData), std::move(columns)); auto boundLoadFrom = std::make_unique(std::move(info)); if (loadFrom.hasWherePredicate()) { auto wherePredicate = expressionBinder.bindExpression(*loadFrom.getWherePredicate()); diff --git a/src/binder/bind/bind_standalone_call.cpp b/src/binder/bind/bind_standalone_call.cpp index 5fa33023775..2f7c0bd0a94 100644 --- a/src/binder/bind/bind_standalone_call.cpp +++ b/src/binder/bind/bind_standalone_call.cpp @@ -15,7 +15,8 @@ std::unique_ptr Binder::bindStandaloneCall(const parser::Stateme ku_dynamic_cast(statement); main::Option* option = main::DBConfig::getOptionByName(callStatement.getOptionName()); if (option == nullptr) { - option = extensionOptions->getExtensionOption(callStatement.getOptionName()); + option = + clientContext->getExtensionOptions()->getExtensionOption(callStatement.getOptionName()); } if (option == nullptr) { throw BinderException{"Invalid option name: " + callStatement.getOptionName() + "."}; diff --git a/src/binder/bind/bind_updating_clause.cpp b/src/binder/bind/bind_updating_clause.cpp index a5d9acf7383..0664f4225f4 100644 --- a/src/binder/bind/bind_updating_clause.cpp +++ b/src/binder/bind/bind_updating_clause.cpp @@ -6,12 +6,14 @@ #include "binder/query/updating_clause/bound_insert_clause.h" #include "binder/query/updating_clause/bound_merge_clause.h" #include "binder/query/updating_clause/bound_set_clause.h" +#include "catalog/catalog.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "common/assert.h" #include "common/exception/binder.h" #include "common/keyword/rdf_keyword.h" #include "common/string_format.h" +#include "function/rdf/vector_rdf_functions.h" #include "main/client_context.h" #include "parser/query/updating_clause/delete_clause.h" #include "parser/query/updating_clause/insert_clause.h" @@ -45,12 +47,16 @@ std::unique_ptr Binder::bindUpdatingClause( } } -static expression_set populateNodeRelScope(const BinderScope& scope) { - expression_set result; +static std::unordered_set populatePatternsScope(const BinderScope& scope) { + std::unordered_set result; for (auto& expression : scope.getExpressions()) { if (ExpressionUtil::isNodePattern(*expression) || ExpressionUtil::isRelPattern(*expression)) { - result.insert(expression); + result.insert(expression->toString()); + } else if (expression->expressionType == ExpressionType::VARIABLE) { + if (scope.hasNodeReplacement(expression->toString())) { + result.insert(expression->toString()); + } } } return result; @@ -59,24 +65,25 @@ static expression_set populateNodeRelScope(const BinderScope& scope) { std::unique_ptr Binder::bindInsertClause( const UpdatingClause& updatingClause) { auto& insertClause = (InsertClause&)updatingClause; - auto nodeRelScope = populateNodeRelScope(*scope); + auto patternsScope = populatePatternsScope(scope); // bindGraphPattern will update scope. auto boundGraphPattern = bindGraphPattern(insertClause.getPatternElementsRef()); - auto insertInfos = bindInsertInfos(boundGraphPattern.queryGraphCollection, nodeRelScope); + auto insertInfos = bindInsertInfos(boundGraphPattern.queryGraphCollection, patternsScope); return std::make_unique(std::move(insertInfos)); } std::unique_ptr Binder::bindMergeClause( const parser::UpdatingClause& updatingClause) { auto& mergeClause = (MergeClause&)updatingClause; - auto nodeRelScope = populateNodeRelScope(*scope); + auto patternsScope = populatePatternsScope(scope); // bindGraphPattern will update scope. auto boundGraphPattern = bindGraphPattern(mergeClause.getPatternElementsRef()); rewriteMatchPattern(boundGraphPattern); - auto createInfos = bindInsertInfos(boundGraphPattern.queryGraphCollection, nodeRelScope); + auto createInfos = bindInsertInfos(boundGraphPattern.queryGraphCollection, patternsScope); + auto distinctMark = createVariable("__distinctMark", *LogicalType::BOOL()); auto boundMergeClause = std::make_unique(std::move(boundGraphPattern.queryGraphCollection), - std::move(boundGraphPattern.where), std::move(createInfos)); + std::move(boundGraphPattern.where), std::move(createInfos), std::move(distinctMark)); if (mergeClause.hasOnMatchSetItems()) { for (auto& [lhs, rhs] : mergeClause.getOnMatchSetItemsRef()) { auto setPropertyInfo = bindSetPropertyInfo(lhs.get(), rhs.get()); @@ -93,28 +100,37 @@ std::unique_ptr Binder::bindMergeClause( } std::vector Binder::bindInsertInfos( - const QueryGraphCollection& queryGraphCollection, const expression_set& nodeRelScope_) { - auto nodeRelScope = nodeRelScope_; + const QueryGraphCollection& queryGraphCollection, + const std::unordered_set& patternsInScope_) { + auto patternsInScope = patternsInScope_; std::vector result; - auto analyzer = QueryGraphLabelAnalyzer(catalog); + auto analyzer = QueryGraphLabelAnalyzer(*clientContext); for (auto i = 0u; i < queryGraphCollection.getNumQueryGraphs(); ++i) { auto queryGraph = queryGraphCollection.getQueryGraph(i); // Ensure query graph does not violate declared schema. analyzer.pruneLabel(*queryGraph); for (auto j = 0u; j < queryGraph->getNumQueryNodes(); ++j) { auto node = queryGraph->getQueryNode(j); - if (nodeRelScope.contains(node)) { + if (node->getVariableName().empty()) { // Always create anonymous node. + bindInsertNode(node, result); + continue; + } + if (patternsInScope.contains(node->getVariableName())) { continue; } - nodeRelScope.insert(node); + patternsInScope.insert(node->getVariableName()); bindInsertNode(node, result); } for (auto j = 0u; j < queryGraph->getNumQueryRels(); ++j) { auto rel = queryGraph->getQueryRel(j); - if (nodeRelScope.contains(rel)) { + if (rel->getVariableName().empty()) { // Always create anonymous rel. + bindInsertRel(rel, result); + continue; + } + if (patternsInScope.contains(rel->getVariableName())) { continue; } - nodeRelScope.insert(rel); + patternsInScope.insert(rel->getVariableName()); bindInsertRel(rel, result); } } @@ -124,8 +140,8 @@ std::vector Binder::bindInsertInfos( return result; } -static void validatePrimaryKeyExistence( - const NodeTableCatalogEntry* nodeTableEntry, const NodeExpression& node) { +static void validatePrimaryKeyExistence(const NodeTableCatalogEntry* nodeTableEntry, + const NodeExpression& node) { auto primaryKey = nodeTableEntry->getPrimaryKey(); if (*primaryKey->getDataType() == *LogicalType::SERIAL()) { if (node.hasPropertyDataExpr(primaryKey->getName())) { @@ -143,19 +159,20 @@ static void validatePrimaryKeyExistence( } } -void Binder::bindInsertNode( - std::shared_ptr node, std::vector& infos) { +void Binder::bindInsertNode(std::shared_ptr node, + std::vector& infos) { if (node->isMultiLabeled()) { throw BinderException( "Create node " + node->toString() + " with multiple node labels is not supported."); } + auto catalog = clientContext->getCatalog(); auto tableID = node->getSingleTableID(); - auto tableSchema = catalog.getTableCatalogEntry(clientContext->getTx(), tableID); + auto tableSchema = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); KU_ASSERT(tableSchema->getTableType() == TableType::NODE); validatePrimaryKeyExistence( ku_dynamic_cast(tableSchema), *node); auto insertInfo = BoundInsertInfo(TableType::NODE, node); - for (auto& entry : catalog.getRdfGraphEntries(clientContext->getTx())) { + for (auto& entry : catalog->getRdfGraphEntries(clientContext->getTx())) { auto rdfEntry = ku_dynamic_cast(entry); if (rdfEntry->isParent(tableID)) { insertInfo.conflictAction = ConflictAction::ON_CONFLICT_DO_NOTHING; @@ -172,8 +189,8 @@ void Binder::bindInsertNode( infos.push_back(std::move(insertInfo)); } -void Binder::bindInsertRel( - std::shared_ptr rel, std::vector& infos) { +void Binder::bindInsertRel(std::shared_ptr rel, + std::vector& infos) { if (rel->isMultiLabeled() || rel->isBoundByMultiLabeledNode()) { throw BinderException( "Create rel " + rel->toString() + @@ -185,9 +202,10 @@ void Binder::bindInsertRel( } rel->setTableIDs(std::vector{rel->getTableIDs()[0]}); auto relTableID = rel->getSingleTableID(); - auto tableEntry = catalog.getTableCatalogEntry(clientContext->getTx(), relTableID); + auto catalog = clientContext->getCatalog(); + auto tableEntry = catalog->getTableCatalogEntry(clientContext->getTx(), relTableID); TableCatalogEntry* parentTableEntry = nullptr; - for (auto& rdfGraphEntry : catalog.getRdfGraphEntries(clientContext->getTx())) { + for (auto& rdfGraphEntry : catalog->getRdfGraphEntries(clientContext->getTx())) { if (rdfGraphEntry->isParent(relTableID)) { parentTableEntry = rdfGraphEntry; } @@ -202,11 +220,11 @@ void Binder::bindInsertRel( } // Insert predicate resource node. auto resourceTableID = rdfGraphEntry->getResourceTableID(); - auto pNode = createQueryNode( - rel->getVariableName(), std::vector{resourceTableID}); + auto pNode = createQueryNode(rel->getVariableName(), + std::vector{resourceTableID}); auto iriData = rel->getPropertyDataExpr(std::string(rdf::IRI)); iriData = expressionBinder.bindScalarFunctionExpression( - expression_vector{std::move(iriData)}, VALIDATE_PREDICATE_FUNC_NAME); + expression_vector{std::move(iriData)}, function::ValidatePredicateFunction::name); pNode->addPropertyDataExpr(std::string(rdf::IRI), std::move(iriData)); bindInsertNode(pNode, infos); auto nodeInsertInfo = &infos[infos.size() - 1]; @@ -217,8 +235,8 @@ void Binder::bindInsertRel( auto relInsertInfo = BoundInsertInfo(TableType::REL, rel); std::unordered_map> relPropertyRhsExpr; relPropertyRhsExpr.insert({std::string(rdf::PID), pNode->getInternalID()}); - relInsertInfo.columnExprs.push_back(expressionBinder.bindNodeOrRelPropertyExpression( - *rel, std::string(InternalKeyword::ID))); + relInsertInfo.columnExprs.push_back(expressionBinder.bindNodeOrRelPropertyExpression(*rel, + std::string(InternalKeyword::ID))); relInsertInfo.columnExprs.push_back( expressionBinder.bindNodeOrRelPropertyExpression(*rel, std::string(rdf::PID))); relInsertInfo.columnDataExprs = @@ -227,8 +245,8 @@ void Binder::bindInsertRel( } else { auto insertInfo = BoundInsertInfo(TableType::REL, rel); insertInfo.columnExprs = rel->getPropertyExprs(); - insertInfo.columnDataExprs = bindInsertColumnDataExprs( - rel->getPropertyDataExprRef(), tableEntry->getPropertiesRef()); + insertInfo.columnDataExprs = bindInsertColumnDataExprs(rel->getPropertyDataExprRef(), + tableEntry->getPropertiesRef()); infos.push_back(std::move(insertInfo)); } } @@ -259,8 +277,8 @@ std::unique_ptr Binder::bindSetClause(const UpdatingClause& return boundSetClause; } -BoundSetPropertyInfo Binder::bindSetPropertyInfo( - parser::ParsedExpression* lhs, parser::ParsedExpression* rhs) { +BoundSetPropertyInfo Binder::bindSetPropertyInfo(parser::ParsedExpression* lhs, + parser::ParsedExpression* rhs) { auto pattern = expressionBinder.bindExpression(*lhs->getChild(0)); auto isNode = ExpressionUtil::isNodePattern(*pattern); auto isRel = ExpressionUtil::isRelPattern(*pattern); @@ -271,9 +289,10 @@ BoundSetPropertyInfo Binder::bindSetPropertyInfo( } auto patternExpr = ku_dynamic_cast(pattern.get()); auto boundSetItem = bindSetItem(lhs, rhs); + auto catalog = clientContext->getCatalog(); for (auto tableID : patternExpr->getTableIDs()) { - auto tableName = catalog.getTableCatalogEntry(clientContext->getTx(), tableID)->getName(); - for (auto& rdfGraphEntry : catalog.getRdfGraphEntries(clientContext->getTx())) { + auto tableName = catalog->getTableCatalogEntry(clientContext->getTx(), tableID)->getName(); + for (auto& rdfGraphEntry : catalog->getRdfGraphEntries(clientContext->getTx())) { if (rdfGraphEntry->isParent(tableID)) { throw BinderException( stringFormat("Cannot set properties of RDFGraph tables. Set {} requires " @@ -282,8 +301,8 @@ BoundSetPropertyInfo Binder::bindSetPropertyInfo( } } } - return BoundSetPropertyInfo( - isNode ? UpdateTableType::NODE : UpdateTableType::REL, pattern, std::move(boundSetItem)); + return BoundSetPropertyInfo(isNode ? UpdateTableType::NODE : UpdateTableType::REL, pattern, + std::move(boundSetItem)); } expression_pair Binder::bindSetItem(parser::ParsedExpression* lhs, parser::ParsedExpression* rhs) { @@ -316,8 +335,8 @@ std::unique_ptr Binder::bindDeleteClause( auto nodeOrRel = expressionBinder.bindExpression(*deleteClause.getExpression(i)); if (ExpressionUtil::isNodePattern(*nodeOrRel)) { validateRdfResourceDeletion(nodeOrRel.get(), clientContext); - auto deleteNodeInfo = BoundDeleteInfo( - UpdateTableType::NODE, nodeOrRel, deleteClause.getDeleteClauseType()); + auto deleteNodeInfo = BoundDeleteInfo(UpdateTableType::NODE, nodeOrRel, + deleteClause.getDeleteClauseType()); boundDeleteClause->addInfo(std::move(deleteNodeInfo)); } else if (ExpressionUtil::isRelPattern(*nodeOrRel)) { if (deleteClause.getDeleteClauseType() == DeleteClauseType::DETACH_DELETE) { diff --git a/src/binder/bind/copy/bind_copy_rdf_graph.cpp b/src/binder/bind/copy/bind_copy_rdf_graph.cpp index 2774a263b1a..f1342fd94ca 100644 --- a/src/binder/bind/copy/bind_copy_rdf_graph.cpp +++ b/src/binder/bind/copy/bind_copy_rdf_graph.cpp @@ -1,79 +1,89 @@ #include "binder/binder.h" #include "binder/copy/bound_copy_from.h" +#include "catalog/catalog.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "common/constants.h" #include "common/copier_config/rdf_reader_config.h" #include "common/keyword/rdf_keyword.h" +#include "function/built_in_function_utils.h" #include "function/table/bind_input.h" #include "main/client_context.h" +#include "parser/copy.h" +#include "processor/operator/persistent/reader/rdf/rdf_scan.h" using namespace kuzu::binder; using namespace kuzu::catalog; using namespace kuzu::common; using namespace kuzu::function; using namespace kuzu::processor; +using namespace kuzu::parser; namespace kuzu { namespace binder { -std::unique_ptr Binder::bindCopyRdfFrom(const parser::Statement&, - std::unique_ptr config, RDFGraphCatalogEntry* rdfGraphEntry) { - auto functions = catalog.getFunctions(clientContext->getTx()); - auto offset = expressionBinder.createVariableExpression( - *LogicalType::INT64(), InternalKeyword::ROW_OFFSET); +std::unique_ptr Binder::bindCopyRdfFrom(const parser::Statement& statement, + RDFGraphCatalogEntry* rdfGraphEntry) { + auto& copyStatement = ku_dynamic_cast(statement); + // Bind path. + KU_ASSERT(copyStatement.getSource()->type == ScanSourceType::FILE); + auto fileSource = ku_dynamic_cast(copyStatement.getSource()); + auto filePaths = bindFilePaths(fileSource->filePaths); + // Bind file type. + auto fileType = bindFileType(filePaths); + auto config = std::make_unique(fileType, std::move(filePaths)); + config->options = bindParsingOptions(copyStatement.getParsingOptionsRef()); + auto catalog = clientContext->getCatalog(); + auto functions = catalog->getFunctions(clientContext->getTx()); + auto offset = expressionBinder.createVariableExpression(*LogicalType::INT64(), + InternalKeyword::ROW_OFFSET); auto r = expressionBinder.createVariableExpression(*LogicalType::STRING(), rdf::IRI); auto l = expressionBinder.createVariableExpression(*LogicalType::RDF_VARIANT(), rdf::VAL); auto lang = expressionBinder.createVariableExpression(*LogicalType::STRING(), rdf::LANG); auto s = expressionBinder.createVariableExpression(*LogicalType::STRING(), rdf::SUBJECT); auto p = expressionBinder.createVariableExpression(*LogicalType::STRING(), rdf::PREDICATE); auto o = expressionBinder.createVariableExpression(*LogicalType::STRING(), rdf::OBJECT); - auto sOffset = expressionBinder.createVariableExpression( - *LogicalType::INT64(), InternalKeyword::SRC_OFFSET); + auto sOffset = expressionBinder.createVariableExpression(*LogicalType::INT64(), + InternalKeyword::SRC_OFFSET); auto pOffset = expressionBinder.createVariableExpression(*LogicalType::INT64(), rdf::PID); - auto oOffset = expressionBinder.createVariableExpression( - *LogicalType::INT64(), InternalKeyword::DST_OFFSET); + auto oOffset = expressionBinder.createVariableExpression(*LogicalType::INT64(), + InternalKeyword::DST_OFFSET); auto bindInput = std::make_unique(config->copy()); Function* func; // Bind file scan; auto inMemory = RdfReaderConfig::construct(config->options).inMemory; - func = BuiltInFunctionsUtils::matchFunction(READ_RDF_ALL_TRIPLE_FUNC_NAME, functions); + func = BuiltInFunctionsUtils::matchFunction(RdfAllTripleScan::name, functions); auto scanFunc = ku_dynamic_cast(func); auto bindData = scanFunc->bindFunc(clientContext, bindInput.get()); - auto scanInfo = std::make_unique( - scanFunc, bindData->copy(), expression_vector{}, offset); // Bind copy resource. - func = inMemory ? - BuiltInFunctionsUtils::matchFunction(IN_MEM_READ_RDF_RESOURCE_FUNC_NAME, functions) : - BuiltInFunctionsUtils::matchFunction(READ_RDF_RESOURCE_FUNC_NAME, functions); + func = inMemory ? BuiltInFunctionsUtils::matchFunction(RdfResourceInMemScan::name, functions) : + BuiltInFunctionsUtils::matchFunction(RdfResourceScan::name, functions); auto rScanFunc = ku_dynamic_cast(func); auto rColumns = expression_vector{r}; - auto rScanInfo = std::make_unique( - rScanFunc, bindData->copy(), std::move(rColumns), offset); + auto rFileScanInfo = BoundFileScanInfo(*rScanFunc, bindData->copy(), std::move(rColumns)); + auto rSource = std::make_unique(std::move(rFileScanInfo)); auto rTableID = rdfGraphEntry->getResourceTableID(); - auto rSchema = catalog.getTableCatalogEntry(clientContext->getTx(), rTableID); - auto rCopyInfo = BoundCopyFromInfo(rSchema, std::move(rScanInfo), false, nullptr); + auto rEntry = catalog->getTableCatalogEntry(clientContext->getTx(), rTableID); + auto rCopyInfo = BoundCopyFromInfo(rEntry, std::move(rSource), offset, nullptr /* extraInfo */); // Bind copy literal. - func = inMemory ? - BuiltInFunctionsUtils::matchFunction(IN_MEM_READ_RDF_LITERAL_FUNC_NAME, functions) : - BuiltInFunctionsUtils::matchFunction(READ_RDF_LITERAL_FUNC_NAME, functions); + func = inMemory ? BuiltInFunctionsUtils::matchFunction(RdfLiteralInMemScan::name, functions) : + BuiltInFunctionsUtils::matchFunction(RdfLiteralScan::name, functions); auto lScanFunc = ku_dynamic_cast(func); auto lColumns = expression_vector{l, lang}; - auto lScanInfo = std::make_unique( - lScanFunc, bindData->copy(), std::move(lColumns), offset); + auto lFileScanInfo = BoundFileScanInfo(*lScanFunc, bindData->copy(), std::move(lColumns)); + auto lSource = std::make_unique(std::move(lFileScanInfo)); auto lTableID = rdfGraphEntry->getLiteralTableID(); - auto lSchema = catalog.getTableCatalogEntry(clientContext->getTx(), lTableID); - auto lCopyInfo = BoundCopyFromInfo(lSchema, std::move(lScanInfo), true, nullptr); + auto lEntry = catalog->getTableCatalogEntry(clientContext->getTx(), lTableID); + auto lCopyInfo = BoundCopyFromInfo(lEntry, std::move(lSource), offset, nullptr /* extraInfo */); // Bind copy resource triples func = inMemory ? - BuiltInFunctionsUtils::matchFunction( - IN_MEM_READ_RDF_RESOURCE_TRIPLE_FUNC_NAME, functions) : - BuiltInFunctionsUtils::matchFunction(READ_RDF_RESOURCE_TRIPLE_FUNC_NAME, functions); + BuiltInFunctionsUtils::matchFunction(RdfResourceTripleInMemScan::name, functions) : + BuiltInFunctionsUtils::matchFunction(RdfResourceTripleScan::name, functions); auto rrrScanFunc = ku_dynamic_cast(func); auto rrrColumns = expression_vector{s, p, o}; - auto rrrScanInfo = - std::make_unique(rrrScanFunc, bindData->copy(), rrrColumns, offset); + auto rrrFileScanInfo = BoundFileScanInfo(*rrrScanFunc, bindData->copy(), rrrColumns); + auto rrrSource = std::make_unique(std::move(rrrFileScanInfo)); auto rrrTableID = rdfGraphEntry->getResourceTripleTableID(); - auto rrrSchema = catalog.getTableCatalogEntry(clientContext->getTx(), rrrTableID); + auto rrrEntry = catalog->getTableCatalogEntry(clientContext->getTx(), rrrTableID); auto rrrExtraInfo = std::make_unique(); auto sLookUp = IndexLookupInfo(rTableID, sOffset, s, s->getDataType()); auto pLookUp = IndexLookupInfo(rTableID, pOffset, p, p->getDataType()); @@ -84,18 +94,17 @@ std::unique_ptr Binder::bindCopyRdfFrom(const parser::Statement& rrrExtraInfo->fromOffset = sOffset; rrrExtraInfo->toOffset = oOffset; auto rrrCopyInfo = - BoundCopyFromInfo(rrrSchema, std::move(rrrScanInfo), false, std::move(rrrExtraInfo)); + BoundCopyFromInfo(rrrEntry, std::move(rrrSource), offset, std::move(rrrExtraInfo)); // Bind copy literal triples func = inMemory ? - BuiltInFunctionsUtils::matchFunction( - IN_MEM_READ_RDF_LITERAL_TRIPLE_FUNC_NAME, functions) : - BuiltInFunctionsUtils::matchFunction(READ_RDF_LITERAL_TRIPLE_FUNC_NAME, functions); + BuiltInFunctionsUtils::matchFunction(RdfLiteralTripleInMemScan::name, functions) : + BuiltInFunctionsUtils::matchFunction(RdfLiteralTripleScan::name, functions); auto rrlScanFunc = ku_dynamic_cast(func); auto rrlColumns = expression_vector{s, p, oOffset}; - auto rrlScanInfo = - std::make_unique(rrlScanFunc, bindData->copy(), rrlColumns, offset); + auto rrlFileScanInfo = BoundFileScanInfo(*rrlScanFunc, bindData->copy(), rrlColumns); + auto rrlSource = std::make_unique(std::move(rrlFileScanInfo)); auto rrlTableID = rdfGraphEntry->getLiteralTripleTableID(); - auto rrlSchema = catalog.getTableCatalogEntry(clientContext->getTx(), rrlTableID); + auto rrlEntry = catalog->getTableCatalogEntry(clientContext->getTx(), rrlTableID); auto rrlExtraInfo = std::make_unique(); rrlExtraInfo->infos.push_back(sLookUp.copy()); rrlExtraInfo->infos.push_back(pLookUp.copy()); @@ -103,12 +112,19 @@ std::unique_ptr Binder::bindCopyRdfFrom(const parser::Statement& rrlExtraInfo->fromOffset = sOffset; rrlExtraInfo->toOffset = oOffset; auto rrLCopyInfo = - BoundCopyFromInfo(rrlSchema, std::move(rrlScanInfo), false, std::move(rrlExtraInfo)); + BoundCopyFromInfo(rrlEntry, std::move(rrlSource), offset, std::move(rrlExtraInfo)); // Bind copy rdf - auto rdfExtraInfo = std::make_unique( - std::move(rCopyInfo), std::move(lCopyInfo), std::move(rrrCopyInfo), std::move(rrLCopyInfo)); - auto rdfCopyInfo = BoundCopyFromInfo( - rdfGraphEntry, inMemory ? std::move(scanInfo) : nullptr, false, std::move(rdfExtraInfo)); + auto rdfExtraInfo = std::make_unique(std::move(rCopyInfo), + std::move(lCopyInfo), std::move(rrrCopyInfo), std::move(rrLCopyInfo)); + std::unique_ptr source; + if (inMemory) { + auto fileScanInfo = BoundFileScanInfo(*scanFunc, bindData->copy(), expression_vector{}); + source = std::make_unique(std::move(fileScanInfo)); + } else { + source = std::make_unique(); + } + auto rdfCopyInfo = + BoundCopyFromInfo(rdfGraphEntry, std::move(source), offset, std::move(rdfExtraInfo)); return std::make_unique(std::move(rdfCopyInfo)); } diff --git a/src/binder/bind/ddl/bind_create_rdf_graph.cpp b/src/binder/bind/ddl/bind_create_rdf_graph.cpp index f4e85b15a97..8a8249f5930 100644 --- a/src/binder/bind/ddl/bind_create_rdf_graph.cpp +++ b/src/binder/bind/ddl/bind_create_rdf_graph.cpp @@ -1,4 +1,5 @@ #include "binder/binder.h" +#include "binder/ddl/bound_create_table_info.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "common/keyword/rdf_keyword.h" #include "parser/ddl/create_table_info.h" @@ -16,8 +17,8 @@ BoundCreateTableInfo Binder::bindCreateRdfGraphInfo(const CreateTableInfo* info) auto resourceTableName = RDFGraphCatalogEntry::getResourceTableName(rdfGraphName); std::vector resourceProperties; resourceProperties.emplace_back(std::string(rdf::IRI), *LogicalType::STRING()); - auto resourceExtraInfo = std::make_unique( - 0 /* primaryKeyIdx */, std::move(resourceProperties)); + auto resourceExtraInfo = std::make_unique(0 /* primaryKeyIdx */, + std::move(resourceProperties)); auto resourceCreateInfo = BoundCreateTableInfo(TableType::NODE, resourceTableName, std::move(resourceExtraInfo)); // Literal table. @@ -26,8 +27,8 @@ BoundCreateTableInfo Binder::bindCreateRdfGraphInfo(const CreateTableInfo* info) literalProperties.emplace_back(std::string(rdf::ID), *LogicalType::SERIAL()); literalProperties.emplace_back(std::string(rdf::VAL), *LogicalType::RDF_VARIANT()); literalProperties.emplace_back(std::string(rdf::LANG), *LogicalType::STRING()); - auto literalExtraInfo = std::make_unique( - 0 /* primaryKeyIdx */, std::move(literalProperties)); + auto literalExtraInfo = std::make_unique(0 /* primaryKeyIdx */, + std::move(literalProperties)); auto literalCreateInfo = BoundCreateTableInfo(TableType::NODE, literalTableName, std::move(literalExtraInfo)); // Resource triple table. @@ -35,21 +36,21 @@ BoundCreateTableInfo Binder::bindCreateRdfGraphInfo(const CreateTableInfo* info) std::vector resourceTripleProperties; resourceTripleProperties.emplace_back(InternalKeyword::ID, *LogicalType::INTERNAL_ID()); resourceTripleProperties.emplace_back(std::string(rdf::PID), *LogicalType::INTERNAL_ID()); - auto boundResourceTripleExtraInfo = std::make_unique( - common::RelMultiplicity::MANY, common::RelMultiplicity::MANY, INVALID_TABLE_ID, - INVALID_TABLE_ID, std::move(resourceTripleProperties)); - auto boundResourceTripleCreateInfo = BoundCreateTableInfo( - TableType::REL, resourceTripleTableName, std::move(boundResourceTripleExtraInfo)); + auto boundResourceTripleExtraInfo = + std::make_unique(RelMultiplicity::MANY, RelMultiplicity::MANY, + INVALID_TABLE_ID, INVALID_TABLE_ID, std::move(resourceTripleProperties)); + auto boundResourceTripleCreateInfo = BoundCreateTableInfo(TableType::REL, + resourceTripleTableName, std::move(boundResourceTripleExtraInfo)); // Literal triple table. auto literalTripleTableName = RDFGraphCatalogEntry::getLiteralTripleTableName(rdfGraphName); std::vector literalTripleProperties; literalTripleProperties.emplace_back(InternalKeyword::ID, *LogicalType::INTERNAL_ID()); literalTripleProperties.emplace_back(std::string(rdf::PID), *LogicalType::INTERNAL_ID()); - auto boundLiteralTripleExtraInfo = std::make_unique( - common::RelMultiplicity::MANY, common::RelMultiplicity::MANY, INVALID_TABLE_ID, - INVALID_TABLE_ID, std::move(literalTripleProperties)); - auto boundLiteralTripleCreateInfo = BoundCreateTableInfo( - TableType::REL, literalTripleTableName, std::move(boundLiteralTripleExtraInfo)); + auto boundLiteralTripleExtraInfo = + std::make_unique(RelMultiplicity::MANY, RelMultiplicity::MANY, + INVALID_TABLE_ID, INVALID_TABLE_ID, std::move(literalTripleProperties)); + auto boundLiteralTripleCreateInfo = BoundCreateTableInfo(TableType::REL, literalTripleTableName, + std::move(boundLiteralTripleExtraInfo)); // Rdf table. auto boundExtraInfo = std::make_unique( std::move(resourceCreateInfo), std::move(literalCreateInfo), diff --git a/src/binder/bind_expression/bind_boolean_expression.cpp b/src/binder/bind_expression/bind_boolean_expression.cpp index d698e9710e6..5e8ec912330 100644 --- a/src/binder/bind_expression/bind_boolean_expression.cpp +++ b/src/binder/bind_expression/bind_boolean_expression.cpp @@ -17,18 +17,18 @@ std::shared_ptr ExpressionBinder::bindBooleanExpression( return bindBooleanExpression(parsedExpression.getExpressionType(), children); } -std::shared_ptr ExpressionBinder::bindBooleanExpression( - ExpressionType expressionType, const expression_vector& children) { +std::shared_ptr ExpressionBinder::bindBooleanExpression(ExpressionType expressionType, + const expression_vector& children) { expression_vector childrenAfterCast; for (auto& child : children) { childrenAfterCast.push_back(implicitCastIfNecessary(child, LogicalTypeID::BOOL)); } auto functionName = expressionTypeToString(expressionType); - function::scalar_exec_func execFunc; + function::scalar_func_exec_t execFunc; function::VectorBooleanFunction::bindExecFunction(expressionType, childrenAfterCast, execFunc); - function::scalar_select_func selectFunc; - function::VectorBooleanFunction::bindSelectFunction( - expressionType, childrenAfterCast, selectFunc); + function::scalar_func_select_t selectFunc; + function::VectorBooleanFunction::bindSelectFunction(expressionType, childrenAfterCast, + selectFunc); auto bindData = std::make_unique(LogicalType::BOOL()); auto uniqueExpressionName = ScalarFunctionExpression::getUniqueName(functionName, childrenAfterCast); @@ -45,8 +45,8 @@ std::shared_ptr ExpressionBinder::combineBooleanExpressions( } else if (right == nullptr) { return left; } else { - return bindBooleanExpression( - expressionType, expression_vector{std::move(left), std::move(right)}); + return bindBooleanExpression(expressionType, + expression_vector{std::move(left), std::move(right)}); } } diff --git a/src/binder/bind_expression/bind_case_expression.cpp b/src/binder/bind_expression/bind_case_expression.cpp index f6977584785..be3d49804ad 100644 --- a/src/binder/bind_expression/bind_case_expression.cpp +++ b/src/binder/bind_expression/bind_case_expression.cpp @@ -1,6 +1,7 @@ #include "binder/binder.h" #include "binder/expression/case_expression.h" #include "binder/expression_binder.h" +#include "common/cast.h" #include "parser/expression/parsed_case_expression.h" using namespace kuzu::common; diff --git a/src/binder/bind_expression/bind_comparison_expression.cpp b/src/binder/bind_expression/bind_comparison_expression.cpp index b5f4366795c..251be59d28a 100644 --- a/src/binder/bind_expression/bind_comparison_expression.cpp +++ b/src/binder/bind_expression/bind_comparison_expression.cpp @@ -1,6 +1,9 @@ #include "binder/binder.h" #include "binder/expression/function_expression.h" #include "binder/expression_binder.h" +#include "catalog/catalog.h" +#include "common/exception/binder.h" +#include "function/built_in_function_utils.h" #include "main/client_context.h" using namespace kuzu::common; @@ -21,19 +24,38 @@ std::shared_ptr ExpressionBinder::bindComparisonExpression( std::shared_ptr ExpressionBinder::bindComparisonExpression( ExpressionType expressionType, const expression_vector& children) { - auto builtInFunctions = binder->catalog.getFunctions(binder->clientContext->getTx()); + auto functions = context->getCatalog()->getFunctions(binder->clientContext->getTx()); auto functionName = expressionTypeToString(expressionType); std::vector childrenTypes; for (auto& child : children) { childrenTypes.push_back(child->dataType); } auto function = ku_dynamic_cast( - function::BuiltInFunctionsUtils::matchFunction( - functionName, childrenTypes, builtInFunctions)); + function::BuiltInFunctionsUtils::matchFunction(functionName, childrenTypes, functions)); expression_vector childrenAfterCast; for (auto i = 0u; i < children.size(); ++i) { - childrenAfterCast.push_back( - implicitCastIfNecessary(children[i], function->parameterTypeIDs[i])); + if (LogicalTypeUtils::isNested(function->parameterTypeIDs[i]) && + children[i]->dataType.getLogicalTypeID() == LogicalTypeID::ANY) { + // try matching the type to any other children + bool foundValidChild = false; + for (auto j = 0u; !foundValidChild && j < children.size(); ++j) { + if (children[j]->dataType.getLogicalTypeID() == function->parameterTypeIDs[i]) { + childrenAfterCast.push_back( + implicitCastIfNecessary(children[i], children[j]->dataType)); + foundValidChild = true; + } + } + // LCOV_EXCL_START + if (!foundValidChild) { + throw common::BinderException( + stringFormat("Cannot resolve recursive data type for expression {}.", + children[i]->toString())); + } + // LCOV_EXCL_STOP + } else { + childrenAfterCast.push_back( + implicitCastIfNecessary(children[i], function->parameterTypeIDs[i])); + } } auto bindData = std::make_unique( std::make_unique(function->returnTypeID)); @@ -46,8 +68,8 @@ std::shared_ptr ExpressionBinder::bindComparisonExpression( std::shared_ptr ExpressionBinder::createEqualityComparisonExpression( std::shared_ptr left, std::shared_ptr right) { - return bindComparisonExpression( - ExpressionType::EQUALS, expression_vector{std::move(left), std::move(right)}); + return bindComparisonExpression(ExpressionType::EQUALS, + expression_vector{std::move(left), std::move(right)}); } } // namespace binder diff --git a/src/binder/bind_expression/bind_function_expression.cpp b/src/binder/bind_expression/bind_function_expression.cpp index bbea8074381..3b63cb759de 100644 --- a/src/binder/bind_expression/bind_function_expression.cpp +++ b/src/binder/bind_expression/bind_function_expression.cpp @@ -1,41 +1,49 @@ #include "binder/binder.h" #include "binder/expression/expression_util.h" #include "binder/expression/function_expression.h" -#include "binder/expression/literal_expression.h" #include "binder/expression/property_expression.h" #include "binder/expression_binder.h" +#include "catalog/catalog.h" #include "common/exception/binder.h" -#include "common/string_utils.h" +#include "function/aggregate/collect.h" +#include "function/arithmetic/vector_arithmetic_functions.h" +#include "function/built_in_function_utils.h" +#include "function/cast/vector_cast_functions.h" +#include "function/path/vector_path_functions.h" +#include "function/rewrite_function.h" +#include "function/scalar_macro_function.h" #include "function/schema/vector_label_functions.h" +#include "function/schema/vector_node_rel_functions.h" #include "main/client_context.h" #include "parser/expression/parsed_function_expression.h" #include "parser/parsed_expression_visitor.h" using namespace kuzu::common; using namespace kuzu::parser; +using namespace kuzu::function; +using namespace kuzu::catalog; namespace kuzu { namespace binder { -std::shared_ptr ExpressionBinder::bindFunctionExpression( - const ParsedExpression& parsedExpression) { - auto& parsedFunctionExpression = (ParsedFunctionExpression&)parsedExpression; - auto functionName = parsedFunctionExpression.getFunctionName(); - StringUtils::toUpper(functionName); - auto result = rewriteFunctionExpression(parsedExpression, functionName); +std::shared_ptr ExpressionBinder::bindFunctionExpression(const ParsedExpression& expr) { + auto& funcExpr = + ku_dynamic_cast(expr); + auto functionName = funcExpr.getNormalizedFunctionName(); + auto result = rewriteFunctionExpression(expr, functionName); if (result != nullptr) { return result; } - auto functionType = - binder->catalog.getFunctionType(binder->clientContext->getTx(), functionName); - switch (functionType) { - case ExpressionType::FUNCTION: - return bindScalarFunctionExpression(parsedExpression, functionName); - case ExpressionType::AGGREGATE_FUNCTION: - return bindAggregateFunctionExpression( - parsedExpression, functionName, parsedFunctionExpression.getIsDistinct()); - case ExpressionType::MACRO: - return bindMacroExpression(parsedExpression, functionName); + auto entry = context->getCatalog()->getFunctionEntry(context->getTx(), functionName); + switch (entry->getType()) { + case CatalogEntryType::SCALAR_FUNCTION_ENTRY: + return bindScalarFunctionExpression(expr, functionName); + case CatalogEntryType::REWRITE_FUNCTION_ENTRY: + return bindRewriteFunctionExpression(expr); + case CatalogEntryType::AGGREGATE_FUNCTION_ENTRY: + return bindAggregateFunctionExpression(expr, functionName, funcExpr.getIsDistinct()); + case CatalogEntryType::SCALAR_MACRO_ENTRY: + return bindMacroExpression(expr, functionName); default: KU_UNREACHABLE; } @@ -51,31 +59,33 @@ std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( return bindScalarFunctionExpression(children, functionName); } +static std::vector getTypes(const expression_vector& exprs) { + std::vector result; + for (auto& expr : exprs) { + result.push_back(expr->getDataType()); + } + return result; +} + std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( const expression_vector& children, const std::string& functionName) { - std::vector childrenTypes; - for (auto& child : children) { - childrenTypes.push_back(child->dataType); - } - auto function = ku_dynamic_cast( - function::BuiltInFunctionsUtils::matchFunction(functionName, childrenTypes, - binder->catalog.getFunctions(binder->clientContext->getTx()))); + auto childrenTypes = getTypes(children); + auto functions = context->getCatalog()->getFunctions(context->getTx()); + auto function = ku_dynamic_cast( + function::BuiltInFunctionsUtils::matchFunction(functionName, childrenTypes, functions)); expression_vector childrenAfterCast; std::unique_ptr bindData; - if (functionName == CAST_FUNC_NAME) { - // If the expression to cast already has the same type as the target type, skip casting. - if (children.size() == 2) { - auto targetTypeStr = (ku_dynamic_cast(*children[1])) - .getValue() - ->getValue(); - auto outputType = binder::Binder::bindDataType(targetTypeStr); - if (*outputType == children[0]->dataType) { - return children[0]; - } - } + if (functionName == CastAnyFunction::name) { bindData = function->bindFunc(children, function); - childrenAfterCast.push_back( - implicitCastIfNecessary(children[0], function->parameterTypeIDs[0])); + if (bindData == nullptr) { + return children[0]; + } + auto childAfterCast = children[0]; + // See castBindFunc for explanation. + if (children[0]->getDataType().getLogicalTypeID() == LogicalTypeID::ANY) { + childAfterCast = implicitCastIfNecessary(children[0], LogicalTypeID::STRING); + } + childrenAfterCast.push_back(std::move(childAfterCast)); } else { for (auto i = 0u; i < children.size(); ++i) { auto targetType = function->isVarLength ? function->parameterTypeIDs[0] : @@ -96,6 +106,23 @@ std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( function->compileFunc, uniqueExpressionName); } +std::shared_ptr ExpressionBinder::bindRewriteFunctionExpression( + const parser::ParsedExpression& expr) { + auto& funcExpr = + ku_dynamic_cast(expr); + expression_vector children; + for (auto i = 0u; i < expr.getNumChildren(); ++i) { + children.push_back(bindExpression(*expr.getChild(i))); + } + auto childrenTypes = getTypes(children); + auto functions = context->getCatalog()->getFunctions(context->getTx()); + auto match = BuiltInFunctionsUtils::matchFunction(funcExpr.getNormalizedFunctionName(), + childrenTypes, functions); + auto function = ku_dynamic_cast(match); + KU_ASSERT(function->rewriteFunc != nullptr); + return function->rewriteFunc(children, this); +} + std::shared_ptr ExpressionBinder::bindAggregateFunctionExpression( const ParsedExpression& parsedExpression, const std::string& functionName, bool isDistinct) { std::vector childrenTypes; @@ -110,12 +137,18 @@ std::shared_ptr ExpressionBinder::bindAggregateFunctionExpression( childrenTypes.push_back(child->dataType); children.push_back(std::move(child)); } + auto functions = context->getCatalog()->getFunctions(context->getTx()); auto function = function::BuiltInFunctionsUtils::matchAggregateFunction(functionName, - childrenTypes, isDistinct, binder->catalog.getFunctions(binder->clientContext->getTx())) + childrenTypes, isDistinct, functions) ->clone(); if (function->paramRewriteFunc) { function->paramRewriteFunc(children); } + if (functionName == CollectFunction::name && parsedExpression.hasAlias() && + children[0]->getDataType().getLogicalTypeID() == LogicalTypeID::NODE) { + auto node = ku_dynamic_cast(children[0].get()); + binder->scope.memorizeTableIDs(parsedExpression.getAlias(), node->getTableIDs()); + } auto uniqueExpressionName = AggregateFunctionExpression::getUniqueName(function->name, children, function->isDistinct); if (children.empty()) { @@ -134,7 +167,7 @@ std::shared_ptr ExpressionBinder::bindAggregateFunctionExpression( std::shared_ptr ExpressionBinder::bindMacroExpression( const ParsedExpression& parsedExpression, const std::string& macroName) { - auto scalarMacroFunction = binder->catalog.getScalarMacroFunction(macroName); + auto scalarMacroFunction = context->getCatalog()->getScalarMacroFunction(macroName); auto macroExpr = scalarMacroFunction->expression->copy(); auto parameterVals = scalarMacroFunction->getDefaultParameterVals(); auto& parsedFuncExpr = @@ -161,31 +194,25 @@ std::shared_ptr ExpressionBinder::bindMacroExpression( // Function rewriting happens when we need to expose internal property access through function so // that it becomes read-only or the function involves catalog information. Currently we write // Before | After -// ID(a) | a._id // LABEL(a) | LIST_EXTRACT(offset(a), [table names from catalog]) // LENGTH(e) | e._length // STARTNODE(a) | a._src // ENDNODE(a) | a._dst std::shared_ptr ExpressionBinder::rewriteFunctionExpression( const parser::ParsedExpression& parsedExpression, const std::string& functionName) { - if (functionName == ID_FUNC_NAME) { - auto child = bindExpression(*parsedExpression.getChild(0)); - validateExpectedDataType(*child, std::vector{LogicalTypeID::NODE, - LogicalTypeID::REL, LogicalTypeID::STRUCT}); - return bindInternalIDExpression(child); - } else if (functionName == LABEL_FUNC_NAME) { + if (functionName == LabelFunction::name) { auto child = bindExpression(*parsedExpression.getChild(0)); - validateExpectedDataType( - *child, std::vector{LogicalTypeID::NODE, LogicalTypeID::REL}); + validateExpectedDataType(*child, + std::vector{LogicalTypeID::NODE, LogicalTypeID::REL}); return bindLabelFunction(*child); - } else if (functionName == LENGTH_FUNC_NAME) { + } else if (functionName == LengthFunction::name) { auto child = bindExpression(*parsedExpression.getChild(0)); return bindRecursiveJoinLengthFunction(*child); - } else if (functionName == START_NODE_FUNC_NAME) { + } else if (functionName == StartNodeFunction::name) { auto child = bindExpression(*parsedExpression.getChild(0)); validateExpectedDataType(*child, std::vector{LogicalTypeID::REL}); return bindStartNodeExpression(*child); - } else if (functionName == END_NODE_FUNC_NAME) { + } else if (functionName == EndNodeFunction::name) { auto child = bindExpression(*parsedExpression.getChild(0)); validateExpectedDataType(*child, std::vector{LogicalTypeID::REL}); return bindEndNodeExpression(*child); @@ -193,34 +220,6 @@ std::shared_ptr ExpressionBinder::rewriteFunctionExpression( return nullptr; } -std::unique_ptr ExpressionBinder::createInternalNodeIDExpression( - const Expression& expression) { - auto& node = (NodeExpression&)expression; - std::unordered_map propertyIDPerTable; - for (auto tableID : node.getTableIDs()) { - propertyIDPerTable.insert({tableID, INVALID_PROPERTY_ID}); - } - return std::make_unique(LogicalType(LogicalTypeID::INTERNAL_ID), - InternalKeyword::ID, node.getUniqueName(), node.getVariableName(), - std::move(propertyIDPerTable), false /* isPrimaryKey */); -} - -std::shared_ptr ExpressionBinder::bindInternalIDExpression( - const std::shared_ptr& expression) { - if (ExpressionUtil::isNodePattern(*expression)) { - auto& node = (NodeExpression&)*expression; - return node.getInternalID(); - } - if (ExpressionUtil::isRelPattern(*expression)) { - return bindNodeOrRelPropertyExpression(*expression, InternalKeyword::ID); - } - KU_ASSERT(expression->dataType.getPhysicalType() == PhysicalTypeID::STRUCT); - auto stringValue = std::make_unique(LogicalType::STRING(), InternalKeyword::ID); - return bindScalarFunctionExpression( - expression_vector{expression, createLiteralExpression(std::move(stringValue))}, - STRUCT_EXTRACT_FUNC_NAME); -} - std::shared_ptr ExpressionBinder::bindStartNodeExpression( const Expression& expression) { auto& rel = (RelExpression&)expression; @@ -250,35 +249,34 @@ static std::vector> populateLabelValues(std::vector ExpressionBinder::bindLabelFunction(const Expression& expression) { - auto listType = LogicalType::VAR_LIST(LogicalType::STRING()); + auto catalog = context->getCatalog(); + auto listType = LogicalType::LIST(LogicalType::STRING()); expression_vector children; switch (expression.getDataType().getLogicalTypeID()) { case LogicalTypeID::NODE: { auto& node = (NodeExpression&)expression; if (!node.isMultiLabeled()) { - auto labelName = binder->catalog.getTableName( - binder->clientContext->getTx(), node.getSingleTableID()); + auto labelName = catalog->getTableName(context->getTx(), node.getSingleTableID()); return createLiteralExpression( std::make_unique(LogicalType::STRING(), labelName)); } - auto nodeTableIDs = binder->catalog.getNodeTableIDs(binder->clientContext->getTx()); + auto nodeTableIDs = catalog->getNodeTableIDs(context->getTx()); children.push_back(node.getInternalID()); auto labelsValue = std::make_unique(std::move(listType), - populateLabelValues(nodeTableIDs, binder->catalog, binder->clientContext->getTx())); + populateLabelValues(nodeTableIDs, *catalog, context->getTx())); children.push_back(createLiteralExpression(std::move(labelsValue))); } break; case LogicalTypeID::REL: { auto& rel = (RelExpression&)expression; if (!rel.isMultiLabeled()) { - auto labelName = binder->catalog.getTableName( - binder->clientContext->getTx(), rel.getSingleTableID()); + auto labelName = catalog->getTableName(context->getTx(), rel.getSingleTableID()); return createLiteralExpression( std::make_unique(LogicalType::STRING(), labelName)); } - auto relTableIDs = binder->catalog.getRelTableIDs(binder->clientContext->getTx()); + auto relTableIDs = catalog->getRelTableIDs(context->getTx()); children.push_back(rel.getInternalIDProperty()); auto labelsValue = std::make_unique(std::move(listType), - populateLabelValues(relTableIDs, binder->catalog, binder->clientContext->getTx())); + populateLabelValues(relTableIDs, *catalog, context->getTx())); children.push_back(createLiteralExpression(std::move(labelsValue))); } break; default: @@ -286,8 +284,9 @@ std::shared_ptr ExpressionBinder::bindLabelFunction(const Expression } auto execFunc = function::LabelFunction::execFunction; auto bindData = std::make_unique(LogicalType::STRING()); - auto uniqueExpressionName = ScalarFunctionExpression::getUniqueName(LABEL_FUNC_NAME, children); - return std::make_shared(LABEL_FUNC_NAME, ExpressionType::FUNCTION, + auto uniqueExpressionName = + ScalarFunctionExpression::getUniqueName(LabelFunction::name, children); + return std::make_shared(LabelFunction::name, ExpressionType::FUNCTION, std::move(bindData), std::move(children), execFunc, nullptr, uniqueExpressionName); } @@ -326,12 +325,12 @@ std::shared_ptr ExpressionBinder::bindRecursiveJoinLengthFunction( children.push_back(std::move(numRelsExpression)); children.push_back( ku_dynamic_cast(*recursiveRels[0]).getLengthExpression()); - auto result = bindScalarFunctionExpression(children, ADD_FUNC_NAME); + auto result = bindScalarFunctionExpression(children, AddFunction::name); for (auto i = 1u; i < recursiveRels.size(); ++i) { children[0] = std::move(result); children[1] = ku_dynamic_cast(*recursiveRels[i]) .getLengthExpression(); - result = bindScalarFunctionExpression(children, ADD_FUNC_NAME); + result = bindScalarFunctionExpression(children, AddFunction::name); } return result; } else if (ExpressionUtil::isRecursiveRelPattern(expression)) { diff --git a/src/binder/bind_expression/bind_literal_expression.cpp b/src/binder/bind_expression/bind_literal_expression.cpp index 56b02344b03..c1d115c2113 100644 --- a/src/binder/bind_expression/bind_literal_expression.cpp +++ b/src/binder/bind_expression/bind_literal_expression.cpp @@ -32,8 +32,8 @@ std::shared_ptr ExpressionBinder::createStringLiteralExpression( } std::shared_ptr ExpressionBinder::createNullLiteralExpression() { - return make_shared( - std::make_unique(Value::createNullValue()), binder->getUniqueExpressionName("NULL")); + return make_shared(std::make_unique(Value::createNullValue()), + binder->getUniqueExpressionName("NULL")); } } // namespace binder diff --git a/src/binder/bind_expression/bind_null_operator_expression.cpp b/src/binder/bind_expression/bind_null_operator_expression.cpp index cfa9cdd7eb1..b1450b692e4 100644 --- a/src/binder/bind_expression/bind_null_operator_expression.cpp +++ b/src/binder/bind_expression/bind_null_operator_expression.cpp @@ -21,9 +21,9 @@ std::shared_ptr ExpressionBinder::bindNullOperatorExpression( } auto expressionType = parsedExpression.getExpressionType(); auto functionName = expressionTypeToString(expressionType); - function::scalar_exec_func execFunc; + function::scalar_func_exec_t execFunc; function::VectorNullFunction::bindExecFunction(expressionType, children, execFunc); - function::scalar_select_func selectFunc; + function::scalar_func_select_t selectFunc; function::VectorNullFunction::bindSelectFunction(expressionType, children, selectFunc); auto bindData = std::make_unique(LogicalType::BOOL()); auto uniqueExpressionName = ScalarFunctionExpression::getUniqueName(functionName, children); diff --git a/src/binder/bind_expression/bind_property_expression.cpp b/src/binder/bind_expression/bind_property_expression.cpp index e52303dfe12..cc45fef1bf6 100644 --- a/src/binder/bind_expression/bind_property_expression.cpp +++ b/src/binder/bind_expression/bind_property_expression.cpp @@ -6,6 +6,7 @@ #include "common/cast.h" #include "common/exception/binder.h" #include "common/string_format.h" +#include "function/struct/vector_struct_functions.h" #include "parser/expression/parsed_property_expression.h" using namespace kuzu::common; @@ -65,8 +66,8 @@ std::shared_ptr ExpressionBinder::bindPropertyExpression( const ParsedExpression& parsedExpression) { auto& propertyExpression = (ParsedPropertyExpression&)parsedExpression; if (propertyExpression.isStar()) { - throw BinderException(stringFormat( - "Cannot bind {} as a single property expression.", parsedExpression.toString())); + throw BinderException(stringFormat("Cannot bind {} as a single property expression.", + parsedExpression.toString())); } auto propertyName = propertyExpression.getPropertyName(); auto child = bindExpression(*parsedExpression.getChild(0)); @@ -92,6 +93,13 @@ std::shared_ptr ExpressionBinder::bindPropertyExpression( std::shared_ptr ExpressionBinder::bindNodeOrRelPropertyExpression( const Expression& child, const std::string& propertyName) { auto& nodeOrRel = ku_dynamic_cast(child); + // TODO(Xiyang): we should be able to remove l97-l100 after removing propertyDataExprs from node + // & rel expression. + if (propertyName == InternalKeyword::ID && + child.dataType.getLogicalTypeID() == common::LogicalTypeID::NODE) { + auto& node = ku_dynamic_cast(child); + return node.getInternalID(); + } if (!nodeOrRel.hasPropertyExpression(propertyName)) { throw BinderException( "Cannot find property " + propertyName + " for " + child.toString() + "."); @@ -103,7 +111,7 @@ std::shared_ptr ExpressionBinder::bindStructPropertyExpression( std::shared_ptr child, const std::string& propertyName) { auto children = expression_vector{std::move(child), createStringLiteralExpression(propertyName)}; - return bindScalarFunctionExpression(children, STRUCT_EXTRACT_FUNC_NAME); + return bindScalarFunctionExpression(children, function::StructExtractFunctions::name); } } // namespace binder diff --git a/src/binder/bind_expression/bind_subquery_expression.cpp b/src/binder/bind_expression/bind_subquery_expression.cpp index ec8fd9eaee2..68b1732cc36 100644 --- a/src/binder/bind_expression/bind_subquery_expression.cpp +++ b/src/binder/bind_expression/bind_subquery_expression.cpp @@ -2,7 +2,10 @@ #include "binder/expression/function_expression.h" #include "binder/expression/subquery_expression.h" #include "binder/expression_binder.h" +#include "catalog/catalog.h" #include "common/types/value/value.h" +#include "function/aggregate/count_star.h" +#include "function/built_in_function_utils.h" #include "parser/expression/parsed_subquery_expression.h" using namespace kuzu::parser; @@ -31,14 +34,14 @@ std::shared_ptr ExpressionBinder::bindSubqueryExpression( std::move(boundGraphPattern.queryGraphCollection), uniqueName, std::move(rawName)); boundSubqueryExpr->setWhereExpression(boundGraphPattern.where); // Bind projection - auto function = BuiltInFunctionsUtils::matchAggregateFunction(COUNT_STAR_FUNC_NAME, - std::vector{}, false, - binder->catalog.getFunctions(binder->clientContext->getTx())); + auto functions = context->getCatalog()->getFunctions(context->getTx()); + auto function = BuiltInFunctionsUtils::matchAggregateFunction(CountStarFunction::name, + std::vector{}, false, functions); auto bindData = std::make_unique(std::make_unique(function->returnTypeID)); - auto countStarExpr = std::make_shared(COUNT_STAR_FUNC_NAME, + auto countStarExpr = std::make_shared(CountStarFunction::name, std::move(bindData), expression_vector{}, function->clone(), - binder->getUniqueExpressionName(COUNT_STAR_FUNC_NAME)); + binder->getUniqueExpressionName(CountStarFunction::name)); boundSubqueryExpr->setCountStarExpr(countStarExpr); std::shared_ptr projectionExpr; switch (subqueryType) { @@ -49,8 +52,8 @@ std::shared_ptr ExpressionBinder::bindSubqueryExpression( case SubqueryType::EXISTS: { // Rewrite EXISTS subquery as COUNT(*) > 0 auto literalExpr = createLiteralExpression(std::make_unique((int64_t)0)); - projectionExpr = bindComparisonExpression( - ExpressionType::GREATER_THAN, expression_vector{countStarExpr, literalExpr}); + projectionExpr = bindComparisonExpression(ExpressionType::GREATER_THAN, + expression_vector{countStarExpr, literalExpr}); } break; default: KU_UNREACHABLE; diff --git a/src/binder/bind_expression/bind_variable_expression.cpp b/src/binder/bind_expression/bind_variable_expression.cpp index ef2981fa1d5..a68fa7f1e32 100644 --- a/src/binder/bind_expression/bind_variable_expression.cpp +++ b/src/binder/bind_expression/bind_variable_expression.cpp @@ -1,8 +1,8 @@ #include "binder/binder.h" -#include "binder/expression/literal_expression.h" #include "binder/expression/variable_expression.h" #include "binder/expression_binder.h" #include "common/exception/binder.h" +#include "common/exception/message.h" #include "main/client_context.h" #include "parser/expression/parsed_variable_expression.h" @@ -21,18 +21,10 @@ std::shared_ptr ExpressionBinder::bindVariableExpression( } std::shared_ptr ExpressionBinder::bindVariableExpression(const std::string& varName) { - if (binder->scope->contains(varName)) { - return binder->scope->getExpression(varName); + if (binder->scope.contains(varName)) { + return binder->scope.getExpression(varName); } - if (binder->clientContext->hasReplaceFunc()) { - auto val = Value(varName); - auto replacedVal = binder->clientContext->replaceFunc(&val); - if (replacedVal != nullptr) { - return std::make_shared( - replacedVal->copy(), binder->getUniqueExpressionName(replacedVal->toString())); - } - } - throw BinderException(stringFormat("Variable {} is not in scope.", varName)); + throw BinderException(ExceptionMessage::variableNotInScope(varName)); } std::shared_ptr ExpressionBinder::createVariableExpression( @@ -40,10 +32,10 @@ std::shared_ptr ExpressionBinder::createVariableExpression( return createVariableExpression(logicalType, std::string(name)); } -std::shared_ptr ExpressionBinder::createVariableExpression( - LogicalType logicalType, std::string name) { - return std::make_shared( - std::move(logicalType), binder->getUniqueExpressionName(name), std::move(name)); +std::shared_ptr ExpressionBinder::createVariableExpression(LogicalType logicalType, + std::string name) { + return std::make_shared(std::move(logicalType), + binder->getUniqueExpressionName(name), std::move(name)); } } // namespace binder diff --git a/src/binder/binder.cpp b/src/binder/binder.cpp index 9bf794d913c..d416829746e 100644 --- a/src/binder/binder.cpp +++ b/src/binder/binder.cpp @@ -1,17 +1,24 @@ #include "binder/binder.h" #include "binder/bound_statement_rewriter.h" +#include "catalog/catalog.h" +#include "catalog/catalog_entry/table_catalog_entry.h" #include "common/copier_config/csv_reader_config.h" #include "common/exception/binder.h" #include "common/keyword/rdf_keyword.h" #include "common/string_format.h" #include "common/string_utils.h" +#include "function/built_in_function_utils.h" #include "function/table_functions.h" -#include "main/client_context.h" +#include "processor/operator/persistent/reader/csv/parallel_csv_reader.h" +#include "processor/operator/persistent/reader/csv/serial_csv_reader.h" +#include "processor/operator/persistent/reader/npy/npy_reader.h" +#include "processor/operator/persistent/reader/parquet/parquet_reader.h" using namespace kuzu::catalog; using namespace kuzu::common; using namespace kuzu::parser; +using namespace kuzu::processor; namespace kuzu { namespace binder { @@ -61,11 +68,17 @@ std::unique_ptr Binder::bind(const Statement& statement) { case StatementType::IMPORT_DATABASE: { boundStatement = bindImportDatabaseClause(statement); } break; + case StatementType::ATTACH_DATABASE: { + boundStatement = bindAttachDatabase(statement); + } break; + case StatementType::DETACH_DATABASE: { + boundStatement = bindDetachDatabase(statement); + } break; default: { KU_UNREACHABLE; } } - BoundStatementRewriter::rewrite(*boundStatement, catalog); + BoundStatementRewriter::rewrite(*boundStatement, *clientContext); return boundStatement; } @@ -76,56 +89,44 @@ std::shared_ptr Binder::bindWhereExpression(const ParsedExpression& } common::table_id_t Binder::bindTableID(const std::string& tableName) const { - if (!catalog.containsTable(clientContext->getTx(), tableName)) { + auto catalog = clientContext->getCatalog(); + if (!catalog->containsTable(clientContext->getTx(), tableName)) { throw BinderException(common::stringFormat("Table {} does not exist.", tableName)); } - return catalog.getTableID(clientContext->getTx(), tableName); + return catalog->getTableID(clientContext->getTx(), tableName); } -std::shared_ptr Binder::createVariable( - std::string_view name, common::LogicalTypeID typeID) { +std::shared_ptr Binder::createVariable(std::string_view name, + common::LogicalTypeID typeID) { return createVariable(std::string(name), LogicalType{typeID}); } -std::shared_ptr Binder::createVariable( - const std::string& name, LogicalTypeID logicalTypeID) { +std::shared_ptr Binder::createVariable(const std::string& name, + LogicalTypeID logicalTypeID) { return createVariable(name, LogicalType{logicalTypeID}); } -std::shared_ptr Binder::createVariable( - const std::string& name, const LogicalType& dataType) { - if (scope->contains(name)) { +std::shared_ptr Binder::createVariable(const std::string& name, + const LogicalType& dataType) { + if (scope.contains(name)) { throw BinderException("Variable " + name + " already exists."); } auto expression = expressionBinder.createVariableExpression(dataType, name); expression->setAlias(name); - scope->addExpression(name, expression); + scope.addExpression(name, expression); return expression; } std::unique_ptr Binder::bindDataType(const std::string& dataType) { auto boundType = LogicalTypeUtils::dataTypeFromString(dataType); - if (boundType.getLogicalTypeID() == LogicalTypeID::FIXED_LIST) { - auto validNumericTypes = LogicalTypeUtils::getNumericalLogicalTypeIDs(); - auto childType = FixedListType::getChildType(&boundType); - auto numElementsInList = FixedListType::getNumValuesInList(&boundType); - if (find(validNumericTypes.begin(), validNumericTypes.end(), - childType->getLogicalTypeID()) == validNumericTypes.end()) { - throw BinderException("The child type of a fixed list must be a numeric type. Given: " + - childType->toString() + "."); - } - if (numElementsInList == 0) { + if (boundType.getLogicalTypeID() == LogicalTypeID::ARRAY) { + auto numElementsInArray = ArrayType::getNumElements(&boundType); + if (numElementsInArray == 0) { // Note: the parser already guarantees that the number of elements is a non-negative // number. However, we still need to check whether the number of elements is 0. throw BinderException( - "The number of elements in a fixed list must be greater than 0. Given: " + - std::to_string(numElementsInList) + "."); - } - auto numElementsPerPage = storage::PageUtils::getNumElementsInAPage( - storage::StorageUtils::getDataTypeSize(boundType), true /* hasNull */); - if (numElementsPerPage == 0) { - throw BinderException(stringFormat("Cannot store a fixed list of size {} in a page.", - storage::StorageUtils::getDataTypeSize(boundType))); + "The number of elements in an array must be greater than 0. Given: " + + std::to_string(numElementsInArray) + "."); } } return std::make_unique(boundType); @@ -159,27 +160,16 @@ void Binder::validateOrderByFollowedBySkipOrLimitInWithClause( } } -void Binder::validateReadNotFollowUpdate(const NormalizedSingleQuery& singleQuery) { - bool hasSeenUpdateClause = false; - for (auto i = 0u; i < singleQuery.getNumQueryParts(); ++i) { - auto normalizedQueryPart = singleQuery.getQueryPart(i); - if (hasSeenUpdateClause && normalizedQueryPart->hasReadingClause()) { - throw BinderException( - "Read after update is not supported. Try query with multiple statements."); - } - hasSeenUpdateClause |= normalizedQueryPart->hasUpdatingClause(); - } -} - void Binder::validateTableType(table_id_t tableID, TableType expectedTableType) { - if (catalog.getTableCatalogEntry(clientContext->getTx(), tableID)->getTableType() != - expectedTableType) { + auto tableEntry = + clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), tableID); + if (tableEntry->getTableType() != expectedTableType) { throw BinderException("Table type mismatch."); } } void Binder::validateTableExist(const std::string& tableName) { - if (!catalog.containsTable(clientContext->getTx(), tableName)) { + if (!clientContext->getCatalog()->containsTable(clientContext->getTx(), tableName)) { throw BinderException("Table " + tableName + " does not exist."); } } @@ -199,39 +189,39 @@ bool Binder::isReservedPropertyName(const std::string& name) { return false; } -std::unique_ptr Binder::saveScope() { - return scope->copy(); +BinderScope Binder::saveScope() { + return scope.copy(); } -void Binder::restoreScope(std::unique_ptr prevVariableScope) { - scope = std::move(prevVariableScope); +void Binder::restoreScope(BinderScope prevScope) { + scope = std::move(prevScope); } -function::TableFunction* Binder::getScanFunction(FileType fileType, const ReaderConfig& config) { +function::TableFunction Binder::getScanFunction(FileType fileType, const ReaderConfig& config) { function::Function* func; auto stringType = LogicalType(LogicalTypeID::STRING); std::vector inputTypes; inputTypes.push_back(stringType); - auto functions = catalog.getFunctions(clientContext->getTx()); + auto functions = clientContext->getCatalog()->getFunctions(clientContext->getTx()); switch (fileType) { case FileType::PARQUET: { - func = function::BuiltInFunctionsUtils::matchFunction( - READ_PARQUET_FUNC_NAME, inputTypes, functions); + func = function::BuiltInFunctionsUtils::matchFunction(ParquetScanFunction::name, inputTypes, + functions); } break; case FileType::NPY: { - func = function::BuiltInFunctionsUtils::matchFunction( - READ_NPY_FUNC_NAME, inputTypes, functions); + func = function::BuiltInFunctionsUtils::matchFunction(NpyScanFunction::name, inputTypes, + functions); } break; case FileType::CSV: { auto csvConfig = CSVReaderConfig::construct(config.options); func = function::BuiltInFunctionsUtils::matchFunction( - csvConfig.parallel ? READ_CSV_PARALLEL_FUNC_NAME : READ_CSV_SERIAL_FUNC_NAME, - inputTypes, functions); + csvConfig.parallel ? ParallelCSVScan::name : SerialCSVScan::name, inputTypes, + functions); } break; default: KU_UNREACHABLE; } - return ku_dynamic_cast(func); + return *ku_dynamic_cast(func); } } // namespace binder diff --git a/src/binder/binder_scope.cpp b/src/binder/binder_scope.cpp new file mode 100644 index 00000000000..e2a540b4ba3 --- /dev/null +++ b/src/binder/binder_scope.cpp @@ -0,0 +1,18 @@ +#include "binder/binder_scope.h" + +namespace kuzu { +namespace binder { + +void BinderScope::addExpression(const std::string& varName, + std::shared_ptr expression) { + nameToExprIdx.insert({varName, expressions.size()}); + expressions.push_back(std::move(expression)); +} + +void BinderScope::clear() { + expressions.clear(); + nameToExprIdx.clear(); +} + +} // namespace binder +} // namespace kuzu diff --git a/src/binder/bound_statement_rewriter.cpp b/src/binder/bound_statement_rewriter.cpp index 3bdcac3799e..6dd62c0e5f3 100644 --- a/src/binder/bound_statement_rewriter.cpp +++ b/src/binder/bound_statement_rewriter.cpp @@ -2,17 +2,21 @@ #include "binder/rewriter/match_clause_pattern_label_rewriter.h" #include "binder/rewriter/with_clause_projection_rewriter.h" +#include "binder/visitor/default_type_solver.h" namespace kuzu { namespace binder { -void BoundStatementRewriter::rewrite( - BoundStatement& boundStatement, const catalog::Catalog& catalog) { +void BoundStatementRewriter::rewrite(BoundStatement& boundStatement, + const main::ClientContext& clientContext) { auto withClauseProjectionRewriter = WithClauseProjectionRewriter(); withClauseProjectionRewriter.visitUnsafe(boundStatement); - auto matchClausePatternLabelRewriter = MatchClausePatternLabelRewriter(catalog); + auto matchClausePatternLabelRewriter = MatchClausePatternLabelRewriter(clientContext); matchClausePatternLabelRewriter.visit(boundStatement); + + auto defaultTypeSolver = DefaultTypeSolver(); + defaultTypeSolver.visit(boundStatement); } } // namespace binder diff --git a/src/binder/bound_statement_visitor.cpp b/src/binder/bound_statement_visitor.cpp index 880a5793197..ce00260db72 100644 --- a/src/binder/bound_statement_visitor.cpp +++ b/src/binder/bound_statement_visitor.cpp @@ -1,6 +1,8 @@ #include "binder/bound_statement_visitor.h" #include "binder/bound_explain.h" +#include "binder/copy/bound_copy_from.h" +#include "binder/copy/bound_copy_to.h" #include "binder/query/bound_regular_query.h" #include "common/cast.h" @@ -53,6 +55,12 @@ void BoundStatementVisitor::visit(const BoundStatement& statement) { case StatementType::IMPORT_DATABASE: { visitImportDatabase(statement); } break; + case StatementType::ATTACH_DATABASE: { + visitAttachDatabase(statement); + } break; + case StatementType::DETACH_DATABASE: { + visitDetachDatabase(statement); + } break; default: KU_UNREACHABLE; } @@ -68,6 +76,20 @@ void BoundStatementVisitor::visitUnsafe(BoundStatement& statement) { } } +void BoundStatementVisitor::visitCopyFrom(const BoundStatement& statement) { + auto& copyFrom = ku_dynamic_cast(statement); + if (copyFrom.getInfo()->source->type == ScanSourceType::QUERY) { + auto querySource = ku_dynamic_cast( + copyFrom.getInfo()->source.get()); + visit(*querySource->statement); + } +} + +void BoundStatementVisitor::visitCopyTo(const BoundStatement& statement) { + auto& copyTo = ku_dynamic_cast(statement); + visitRegularQuery(*copyTo.getRegularQuery()); +} + void BoundStatementVisitor::visitRegularQuery(const BoundStatement& statement) { auto& regularQuery = ku_dynamic_cast(statement); diff --git a/src/binder/expression/CMakeLists.txt b/src/binder/expression/CMakeLists.txt index fbfacda7697..ee106d6723d 100644 --- a/src/binder/expression/CMakeLists.txt +++ b/src/binder/expression/CMakeLists.txt @@ -4,7 +4,9 @@ add_library( case_expression.cpp expression.cpp expression_util.cpp - function_expression.cpp) + function_expression.cpp + literal_expression.cpp + parameter_expression.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/binder/expression/expression.cpp b/src/binder/expression/expression.cpp index 25192ffe963..bbcfc82fd5c 100644 --- a/src/binder/expression/expression.cpp +++ b/src/binder/expression/expression.cpp @@ -1,10 +1,19 @@ #include "binder/expression/expression.h" +#include "common/exception/binder.h" + using namespace kuzu::common; namespace kuzu { namespace binder { +void Expression::cast(const LogicalType&) { + // LCOV_EXCL_START + throw BinderException( + stringFormat("Data type of expression {} should not be modified.", toString())); + // LCOV_EXCL_STOP +} + expression_vector Expression::splitOnAND() { expression_vector result; if (ExpressionType::AND == expressionType) { diff --git a/src/binder/expression/expression_util.cpp b/src/binder/expression/expression_util.cpp index 920d0ddb5aa..40e21c98fb0 100644 --- a/src/binder/expression/expression_util.cpp +++ b/src/binder/expression/expression_util.cpp @@ -5,8 +5,8 @@ using namespace kuzu::common; namespace kuzu { namespace binder { -bool ExpressionUtil::isExpressionsWithDataType( - const expression_vector& expressions, common::LogicalTypeID dataTypeID) { +bool ExpressionUtil::isExpressionsWithDataType(const expression_vector& expressions, + common::LogicalTypeID dataTypeID) { for (auto& expression : expressions) { if (expression->dataType.getLogicalTypeID() != dataTypeID) { return false; @@ -15,8 +15,8 @@ bool ExpressionUtil::isExpressionsWithDataType( return true; } -expression_vector ExpressionUtil::getExpressionsWithDataType( - const expression_vector& expressions, common::LogicalTypeID dataTypeID) { +expression_vector ExpressionUtil::getExpressionsWithDataType(const expression_vector& expressions, + common::LogicalTypeID dataTypeID) { expression_vector result; for (auto& expression : expressions) { if (expression->dataType.getLogicalTypeID() == dataTypeID) { @@ -61,8 +61,8 @@ std::string ExpressionUtil::toString(const expression_pair& expressionPair) { return expressionPair.first->toString() + "=" + expressionPair.second->toString(); } -expression_vector ExpressionUtil::excludeExpression( - const expression_vector& exprs, const Expression& exprToExclude) { +expression_vector ExpressionUtil::excludeExpression(const expression_vector& exprs, + const Expression& exprToExclude) { expression_vector result; for (auto& expr : exprs) { if (*expr != exprToExclude) { @@ -72,8 +72,8 @@ expression_vector ExpressionUtil::excludeExpression( return result; } -expression_vector ExpressionUtil::excludeExpressions( - const expression_vector& expressions, const expression_vector& expressionsToExclude) { +expression_vector ExpressionUtil::excludeExpressions(const expression_vector& expressions, + const expression_vector& expressionsToExclude) { expression_set excludeSet; for (auto& expression : expressionsToExclude) { excludeSet.insert(expression); @@ -87,12 +87,12 @@ expression_vector ExpressionUtil::excludeExpressions( return result; } -std::vector> ExpressionUtil::getDataTypes( +logical_type_vec_t ExpressionUtil::getDataTypes( const kuzu::binder::expression_vector& expressions) { - std::vector> result; + std::vector result; result.reserve(expressions.size()); for (auto& expression : expressions) { - result.push_back(expression->getDataType().copy()); + result.push_back(*expression->getDataType().copy()); } return result; } diff --git a/src/binder/expression/function_expression.cpp b/src/binder/expression/function_expression.cpp index 8a9ece310e3..ef4f77ebce7 100644 --- a/src/binder/expression/function_expression.cpp +++ b/src/binder/expression/function_expression.cpp @@ -5,8 +5,8 @@ namespace kuzu { namespace binder { -std::string ScalarFunctionExpression::getUniqueName( - const std::string& functionName, const kuzu::binder::expression_vector& children) { +std::string ScalarFunctionExpression::getUniqueName(const std::string& functionName, + const kuzu::binder::expression_vector& children) { auto result = functionName + "("; for (auto& child : children) { result += child->getUniqueName() + ", "; @@ -26,8 +26,8 @@ std::string ScalarFunctionExpression::toStringInternal() const { return result; } -std::string AggregateFunctionExpression::getUniqueName( - const std::string& functionName, kuzu::binder::expression_vector& children, bool isDistinct) { +std::string AggregateFunctionExpression::getUniqueName(const std::string& functionName, + kuzu::binder::expression_vector& children, bool isDistinct) { auto result = functionName + "("; if (isDistinct) { result += "DISTINCT "; diff --git a/src/binder/expression/literal_expression.cpp b/src/binder/expression/literal_expression.cpp new file mode 100644 index 00000000000..c0ed03e85a3 --- /dev/null +++ b/src/binder/expression/literal_expression.cpp @@ -0,0 +1,23 @@ +#include "binder/expression/literal_expression.h" + +#include "common/exception/binder.h" + +namespace kuzu { +using namespace common; + +namespace binder { + +void LiteralExpression::cast(const LogicalType& type) { + if (dataType.getLogicalTypeID() != LogicalTypeID::ANY) { + // LCOV_EXCL_START + throw BinderException( + stringFormat("Cannot change literal expression data type from {} to {}.", + dataType.toString(), type.toString())); + // LCOV_EXCL_STOP + } + dataType = type; + value->setDataType(type); +} + +} // namespace binder +} // namespace kuzu diff --git a/src/binder/expression/parameter_expression.cpp b/src/binder/expression/parameter_expression.cpp new file mode 100644 index 00000000000..c0a93cbf2ed --- /dev/null +++ b/src/binder/expression/parameter_expression.cpp @@ -0,0 +1,23 @@ +#include "binder/expression/parameter_expression.h" + +#include "common/exception/binder.h" + +namespace kuzu { +using namespace common; + +namespace binder { + +void ParameterExpression::cast(const LogicalType& type) { + if (dataType.getLogicalTypeID() != LogicalTypeID::ANY) { + // LCOV_EXCL_START + throw BinderException( + stringFormat("Cannot change parameter expression data type from {} to {}.", + dataType.toString(), type.toString())); + // LCOV_EXCL_STOP + } + dataType = type; + value->setDataType(type); +} + +} // namespace binder +} // namespace kuzu diff --git a/src/binder/expression_binder.cpp b/src/binder/expression_binder.cpp index 632d9c64357..07eb0a13720 100644 --- a/src/binder/expression_binder.cpp +++ b/src/binder/expression_binder.cpp @@ -2,14 +2,13 @@ #include "binder/binder.h" #include "binder/expression/function_expression.h" -#include "binder/expression/literal_expression.h" -#include "binder/expression/parameter_expression.h" #include "binder/expression_visitor.h" #include "common/exception/binder.h" #include "common/exception/not_implemented.h" #include "common/string_format.h" #include "expression_evaluator/expression_evaluator_utils.h" #include "function/cast/vector_cast_functions.h" +#include "main/client_context.h" using namespace kuzu::common; using namespace kuzu::function; @@ -59,8 +58,8 @@ std::shared_ptr ExpressionBinder::bindExpression( std::shared_ptr ExpressionBinder::foldExpression( const std::shared_ptr& expression) { - auto value = evaluator::ExpressionEvaluatorUtils::evaluateConstantExpression( - expression, binder->memoryManager); + auto value = evaluator::ExpressionEvaluatorUtils::evaluateConstantExpression(expression, + context->getMemoryManager()); auto result = createLiteralExpression(std::move(value)); // Fold result should preserve the alias original expression. E.g. // RETURN 2, 1 + 1 AS x @@ -74,8 +73,8 @@ std::shared_ptr ExpressionBinder::foldExpression( return result; } -static std::string unsupportedImplicitCastException( - const Expression& expression, const std::string& targetTypeStr) { +static std::string unsupportedImplicitCastException(const Expression& expression, + const std::string& targetTypeStr) { return stringFormat( "Expression {} has data type {} but expected {}. Implicit cast is not supported.", expression.toString(), expression.dataType.toString(), targetTypeStr); @@ -90,8 +89,8 @@ std::shared_ptr ExpressionBinder::implicitCastIfNecessary( } // We don't support casting to nested data type. So instead we validate type match. if (expression->getDataType().getLogicalTypeID() != targetTypeID) { - throw BinderException(unsupportedImplicitCastException( - *expression, LogicalTypeUtils::toString(targetTypeID))); + throw BinderException(unsupportedImplicitCastException(*expression, + LogicalTypeUtils::toString(targetTypeID))); } return expression; } @@ -104,7 +103,7 @@ std::shared_ptr ExpressionBinder::implicitCastIfNecessary( return expression; } if (expression->dataType.getLogicalTypeID() == LogicalTypeID::ANY) { - resolveAnyDataType(*expression, targetType); + expression->cast(targetType); return expression; } return implicitCast(expression, targetType); @@ -116,8 +115,8 @@ std::shared_ptr ExpressionBinder::implicitCast( auto functionName = stringFormat("CAST_TO({})", targetType.toString()); auto children = expression_vector{expression}; auto bindData = std::make_unique(targetType.copy()); - auto scalarFunction = CastFunction::bindCastFunction( - functionName, expression->dataType.getLogicalTypeID(), targetType.getLogicalTypeID()); + auto scalarFunction = CastFunction::bindCastFunction(functionName, + expression->dataType.getLogicalTypeID(), targetType.getLogicalTypeID()); auto uniqueName = ScalarFunctionExpression::getUniqueName(functionName, children); return std::make_shared(functionName, ExpressionType::FUNCTION, std::move(bindData), std::move(children), scalarFunction->execFunc, @@ -127,17 +126,8 @@ std::shared_ptr ExpressionBinder::implicitCast( } } -void ExpressionBinder::resolveAnyDataType(Expression& expression, const LogicalType& targetType) { - if (expression.expressionType == ExpressionType::PARAMETER) { // expression is parameter - ((ParameterExpression&)expression).setDataType(targetType); - } else { // expression is null literal - KU_ASSERT(expression.expressionType == ExpressionType::LITERAL); - ((LiteralExpression&)expression).setDataType(targetType); - } -} - -void ExpressionBinder::validateExpectedDataType( - const Expression& expression, const std::vector& targets) { +void ExpressionBinder::validateExpectedDataType(const Expression& expression, + const std::vector& targets) { auto dataType = expression.dataType; auto targetsSet = std::unordered_set{targets.begin(), targets.end()}; if (!targetsSet.contains(dataType.getLogicalTypeID())) { @@ -147,6 +137,21 @@ void ExpressionBinder::validateExpectedDataType( } } +void ExpressionBinder::validateDataType(const Expression& expr, const LogicalType& expectedType) { + if (expr.getDataType() != expectedType) { + throw BinderException(stringFormat("{} has data type {} but {} was expected.", + expr.toString(), expr.getDataType().toString(), expectedType.toString())); + } +} + +void ExpressionBinder::validateDataType(const Expression& expr, LogicalTypeID expectedTypeID) { + if (expr.getDataType().getLogicalTypeID() != expectedTypeID) { + throw BinderException( + stringFormat("{} has data type {} but {} was expected.", expr.toString(), + expr.getDataType().toString(), LogicalTypeUtils::toString(expectedTypeID))); + } +} + void ExpressionBinder::validateAggregationExpressionIsNotNested(const Expression& expression) { if (expression.getNumChildren() == 0) { return; diff --git a/src/binder/expression_visitor.cpp b/src/binder/expression_visitor.cpp index 837b83c8300..b49ccc9ca9c 100644 --- a/src/binder/expression_visitor.cpp +++ b/src/binder/expression_visitor.cpp @@ -7,6 +7,7 @@ #include "binder/expression/rel_expression.h" #include "binder/expression/subquery_expression.h" #include "common/cast.h" +#include "function/uuid/vector_uuid_functions.h" using namespace kuzu::common; @@ -107,7 +108,7 @@ bool ExpressionVisitor::isRandom(const Expression& expression) { return false; } auto& funcExpr = ku_dynamic_cast(expression); - if (funcExpr.getFunctionName() == GEN_RANDOM_UUID_FUNC_NAME) { + if (funcExpr.getFunctionName() == function::GenRandomUUIDFunction::name) { return true; } for (auto& child : ExpressionChildrenCollector::collectChildren(expression)) { @@ -118,8 +119,8 @@ bool ExpressionVisitor::isRandom(const Expression& expression) { return false; } -bool ExpressionVisitor::satisfyAny( - const Expression& expression, const std::function& condition) { +bool ExpressionVisitor::satisfyAny(const Expression& expression, + const std::function& condition) { if (condition(expression)) { return true; } diff --git a/src/binder/query/query_graph.cpp b/src/binder/query/query_graph.cpp index 7134df63cbd..1bf255ca7c8 100644 --- a/src/binder/query/query_graph.cpp +++ b/src/binder/query/query_graph.cpp @@ -215,13 +215,25 @@ void QueryGraphCollection::addAndMergeQueryGraphIfConnected(QueryGraph queryGrap } void QueryGraphCollection::finalize() { - auto baseGraph = std::move(queryGraphs[0]); + common::idx_t baseGraphIdx = 0; + while (true) { + auto prevNumGraphs = queryGraphs.size(); + queryGraphs = mergeGraphs(baseGraphIdx++); + if (queryGraphs.size() == prevNumGraphs || baseGraphIdx == queryGraphs.size()) { + return; + } + } +} + +std::vector QueryGraphCollection::mergeGraphs(common::idx_t baseGraphIdx) { + KU_ASSERT(baseGraphIdx < queryGraphs.size()); + auto baseGraph = std::move(queryGraphs[baseGraphIdx]); std::unordered_set mergedGraphIndices; - mergedGraphIndices.insert(0); + mergedGraphIndices.insert(baseGraphIdx); while (true) { // find graph to merge common::vector_idx_t graphToMergeIdx = common::INVALID_VECTOR_IDX; - for (auto i = 1u; i < queryGraphs.size(); ++i) { + for (auto i = 0u; i < queryGraphs.size(); ++i) { if (mergedGraphIndices.contains(i)) { // graph has been merged. continue; } @@ -238,14 +250,17 @@ void QueryGraphCollection::finalize() { mergedGraphIndices.insert(graphToMergeIdx); } std::vector finalGraphs; - finalGraphs.push_back(std::move(baseGraph)); - for (auto i = 1u; i < queryGraphs.size(); ++i) { + for (auto i = 0u; i < queryGraphs.size(); ++i) { + if (i == baseGraphIdx) { + finalGraphs.push_back(baseGraph); + continue; + } if (mergedGraphIndices.contains(i)) { continue; } finalGraphs.push_back(std::move(queryGraphs[i])); } - queryGraphs = std::move(finalGraphs); + return finalGraphs; } std::vector> QueryGraphCollection::getQueryNodes() const { diff --git a/src/binder/query/query_graph_label_analyzer.cpp b/src/binder/query/query_graph_label_analyzer.cpp index 8634df148b9..27cbc59ffe7 100644 --- a/src/binder/query/query_graph_label_analyzer.cpp +++ b/src/binder/query/query_graph_label_analyzer.cpp @@ -1,10 +1,10 @@ #include "binder/query/query_graph_label_analyzer.h" +#include "catalog/catalog.h" #include "catalog/catalog_entry/rel_table_catalog_entry.h" #include "common/cast.h" #include "common/exception/binder.h" #include "common/string_format.h" -#include "transaction/transaction.h" using namespace kuzu::common; using namespace kuzu::catalog; @@ -23,6 +23,7 @@ void QueryGraphLabelAnalyzer::pruneLabel(const QueryGraph& graph) { } void QueryGraphLabelAnalyzer::pruneNode(const QueryGraph& graph, NodeExpression& node) { + auto catalog = clientContext.getCatalog(); for (auto i = 0u; i < graph.getNumQueryRels(); ++i) { auto queryRel = graph.getQueryRel(i); if (queryRel->isRecursive()) { @@ -32,18 +33,18 @@ void QueryGraphLabelAnalyzer::pruneNode(const QueryGraph& graph, NodeExpression& std::unordered_set candidateNamesSet; auto isSrcConnect = *queryRel->getSrcNode() == node; auto isDstConnect = *queryRel->getDstNode() == node; - auto tx = &DUMMY_READ_TRANSACTION; + auto tx = clientContext.getTx(); if (queryRel->getDirectionType() == RelDirectionType::BOTH) { if (isSrcConnect || isDstConnect) { for (auto relTableID : queryRel->getTableIDs()) { auto relTableSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(tx, relTableID)); + catalog->getTableCatalogEntry(tx, relTableID)); auto srcTableID = relTableSchema->getSrcTableID(); auto dstTableID = relTableSchema->getDstTableID(); candidates.insert(srcTableID); candidates.insert(dstTableID); - auto srcTableSchema = catalog.getTableCatalogEntry(tx, srcTableID); - auto dstTableSchema = catalog.getTableCatalogEntry(tx, dstTableID); + auto srcTableSchema = catalog->getTableCatalogEntry(tx, srcTableID); + auto dstTableSchema = catalog->getTableCatalogEntry(tx, dstTableID); candidateNamesSet.insert(srcTableSchema->getName()); candidateNamesSet.insert(dstTableSchema->getName()); } @@ -52,19 +53,19 @@ void QueryGraphLabelAnalyzer::pruneNode(const QueryGraph& graph, NodeExpression& if (isSrcConnect) { for (auto relTableID : queryRel->getTableIDs()) { auto relTableSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(tx, relTableID)); + catalog->getTableCatalogEntry(tx, relTableID)); auto srcTableID = relTableSchema->getSrcTableID(); candidates.insert(srcTableID); - auto srcTableSchema = catalog.getTableCatalogEntry(tx, srcTableID); + auto srcTableSchema = catalog->getTableCatalogEntry(tx, srcTableID); candidateNamesSet.insert(srcTableSchema->getName()); } } else if (isDstConnect) { for (auto relTableID : queryRel->getTableIDs()) { auto relTableSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(tx, relTableID)); + catalog->getTableCatalogEntry(tx, relTableID)); auto dstTableID = relTableSchema->getDstTableID(); candidates.insert(dstTableID); - auto dstTableSchema = catalog.getTableCatalogEntry(tx, dstTableID); + auto dstTableSchema = catalog->getTableCatalogEntry(tx, dstTableID); candidateNamesSet.insert(dstTableSchema->getName()); } } @@ -95,6 +96,7 @@ void QueryGraphLabelAnalyzer::pruneNode(const QueryGraph& graph, NodeExpression& } void QueryGraphLabelAnalyzer::pruneRel(RelExpression& rel) { + auto catalog = clientContext.getCatalog(); if (rel.isRecursive()) { return; } @@ -109,7 +111,7 @@ void QueryGraphLabelAnalyzer::pruneRel(RelExpression& rel) { } for (auto& relTableID : rel.getTableIDs()) { auto relTableSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(&DUMMY_READ_TRANSACTION, relTableID)); + catalog->getTableCatalogEntry(clientContext.getTx(), relTableID)); auto srcTableID = relTableSchema->getSrcTableID(); auto dstTableID = relTableSchema->getDstTableID(); if (!boundTableIDSet.contains(srcTableID) || !boundTableIDSet.contains(dstTableID)) { @@ -122,7 +124,7 @@ void QueryGraphLabelAnalyzer::pruneRel(RelExpression& rel) { auto dstTableIDSet = rel.getDstNode()->getTableIDsSet(); for (auto& relTableID : rel.getTableIDs()) { auto relTableSchema = ku_dynamic_cast( - catalog.getTableCatalogEntry(&DUMMY_READ_TRANSACTION, relTableID)); + catalog->getTableCatalogEntry(clientContext.getTx(), relTableID)); auto srcTableID = relTableSchema->getSrcTableID(); auto dstTableID = relTableSchema->getDstTableID(); if (!srcTableIDSet.contains(srcTableID) || !dstTableIDSet.contains(dstTableID)) { diff --git a/src/binder/rewriter/with_clause_projection_rewriter.cpp b/src/binder/rewriter/with_clause_projection_rewriter.cpp index 2686a25363f..c9edb229d0d 100644 --- a/src/binder/rewriter/with_clause_projection_rewriter.cpp +++ b/src/binder/rewriter/with_clause_projection_rewriter.cpp @@ -8,8 +8,8 @@ using namespace kuzu::common; namespace kuzu { namespace binder { -static expression_vector getPropertiesOfSameVariable( - const expression_vector& expressions, const std::string& variableName) { +static expression_vector getPropertiesOfSameVariable(const expression_vector& expressions, + const std::string& variableName) { expression_vector result; for (auto& expression : expressions) { auto propertyExpression = (PropertyExpression*)expression.get(); @@ -21,8 +21,8 @@ static expression_vector getPropertiesOfSameVariable( return result; } -static expression_vector rewriteExpressions( - const expression_vector& expressions, const expression_vector& properties) { +static expression_vector rewriteExpressions(const expression_vector& expressions, + const expression_vector& properties) { expression_set distinctResult; for (auto& expression : expressions) { if (expression->expressionType != common::ExpressionType::PROPERTY) { diff --git a/src/binder/visitor/CMakeLists.txt b/src/binder/visitor/CMakeLists.txt index ddf93f29ddc..5bd4ed88b07 100644 --- a/src/binder/visitor/CMakeLists.txt +++ b/src/binder/visitor/CMakeLists.txt @@ -1,6 +1,7 @@ add_library( kuzu_binder_visitor OBJECT + default_type_solver.cpp property_collector.cpp) set(ALL_OBJECT_FILES diff --git a/src/binder/visitor/default_type_solver.cpp b/src/binder/visitor/default_type_solver.cpp new file mode 100644 index 00000000000..8315f654a8d --- /dev/null +++ b/src/binder/visitor/default_type_solver.cpp @@ -0,0 +1,25 @@ +#include "binder/visitor/default_type_solver.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace binder { + +static void resolveAnyType(Expression& expr) { + if (expr.getDataType().getLogicalTypeID() != LogicalTypeID::ANY) { + return; + } + expr.cast(*LogicalType::STRING()); +} + +void DefaultTypeSolver::visitProjectionBody(const BoundProjectionBody& projectionBody) { + for (auto& expr : projectionBody.getProjectionExpressions()) { + resolveAnyType(*expr); + } + for (auto& expr : projectionBody.getOrderByExpressions()) { + resolveAnyType(*expr); + } +} + +} // namespace binder +} // namespace kuzu diff --git a/src/c_api/connection.cpp b/src/c_api/connection.cpp index acd9b91e3e8..740dd8cb956 100644 --- a/src/c_api/connection.cpp +++ b/src/c_api/connection.cpp @@ -36,8 +36,8 @@ void kuzu_connection_destroy(kuzu_connection* connection) { free(connection); } -void kuzu_connection_set_max_num_thread_for_exec( - kuzu_connection* connection, uint64_t num_threads) { +void kuzu_connection_set_max_num_thread_for_exec(kuzu_connection* connection, + uint64_t num_threads) { static_cast(connection->_connection)->setMaxNumThreadForExec(num_threads); } @@ -52,10 +52,13 @@ kuzu_query_result* kuzu_connection_query(kuzu_connection* connection, const char if (query_result == nullptr) { return nullptr; } - auto* c_query_result = new kuzu_query_result; + auto* c_query_result = (kuzu_query_result*)malloc(sizeof(kuzu_query_result)); c_query_result->_query_result = query_result; + c_query_result->_is_owned_by_cpp = false; return c_query_result; - } catch (Exception& e) { return nullptr; } + } catch (Exception& e) { + return nullptr; + } } kuzu_prepared_statement* kuzu_connection_prepare(kuzu_connection* connection, const char* query) { @@ -64,15 +67,15 @@ kuzu_prepared_statement* kuzu_connection_prepare(kuzu_connection* connection, co if (prepared_statement == nullptr) { return nullptr; } - auto* c_prepared_statement = new kuzu_prepared_statement; + auto* c_prepared_statement = (kuzu_prepared_statement*)malloc(sizeof(kuzu_prepared_statement)); c_prepared_statement->_prepared_statement = prepared_statement; c_prepared_statement->_bound_values = new std::unordered_map>; return c_prepared_statement; } -kuzu_query_result* kuzu_connection_execute( - kuzu_connection* connection, kuzu_prepared_statement* prepared_statement) { +kuzu_query_result* kuzu_connection_execute(kuzu_connection* connection, + kuzu_prepared_statement* prepared_statement) { auto prepared_statement_ptr = static_cast(prepared_statement->_prepared_statement); auto bound_values = static_cast>*>( @@ -92,8 +95,9 @@ kuzu_query_result* kuzu_connection_execute( if (query_result == nullptr) { return nullptr; } - auto* c_query_result = new kuzu_query_result; + auto* c_query_result = (kuzu_query_result*)malloc(sizeof(kuzu_query_result)); c_query_result->_query_result = query_result; + c_query_result->_is_owned_by_cpp = false; return c_query_result; } diff --git a/src/c_api/data_type.cpp b/src/c_api/data_type.cpp index 6364d2e62e8..d7158e77851 100644 --- a/src/c_api/data_type.cpp +++ b/src/c_api/data_type.cpp @@ -5,15 +5,15 @@ using namespace kuzu::common; namespace kuzu::common { struct CAPIHelper { - static inline LogicalType* createLogicalType( - LogicalTypeID typeID, std::unique_ptr extraTypeInfo) { + static inline LogicalType* createLogicalType(LogicalTypeID typeID, + std::unique_ptr extraTypeInfo) { return new LogicalType(typeID, std::move(extraTypeInfo)); } }; } // namespace kuzu::common -kuzu_logical_type* kuzu_data_type_create( - kuzu_data_type_id id, kuzu_logical_type* child_type, uint64_t fixed_num_elements_in_list) { +kuzu_logical_type* kuzu_data_type_create(kuzu_data_type_id id, kuzu_logical_type* child_type, + uint64_t num_elements_in_array) { auto* c_data_type = (kuzu_logical_type*)malloc(sizeof(kuzu_logical_type)); uint8_t data_type_id_u8 = id; LogicalType* data_type; @@ -23,10 +23,10 @@ kuzu_logical_type* kuzu_data_type_create( } else { auto child_type_pty = std::make_unique(*static_cast(child_type->_data_type)); - auto extraTypeInfo = fixed_num_elements_in_list > 0 ? - std::make_unique( - std::move(child_type_pty), fixed_num_elements_in_list) : - std::make_unique(std::move(child_type_pty)); + auto extraTypeInfo = + num_elements_in_array > 0 ? + std::make_unique(std::move(child_type_pty), num_elements_in_array) : + std::make_unique(std::move(child_type_pty)); data_type = CAPIHelper::createLogicalType(logicalTypeID, std::move(extraTypeInfo)); } c_data_type->_data_type = data_type; @@ -60,10 +60,10 @@ kuzu_data_type_id kuzu_data_type_get_id(kuzu_logical_type* data_type) { return static_cast(data_type_id_u8); } -uint64_t kuzu_data_type_get_fixed_num_elements_in_list(kuzu_logical_type* data_type) { +uint64_t kuzu_data_type_get_num_elements_in_array(kuzu_logical_type* data_type) { auto parent_type = static_cast(data_type->_data_type); - if (parent_type->getLogicalTypeID() != LogicalTypeID::FIXED_LIST) { + if (parent_type->getLogicalTypeID() != LogicalTypeID::ARRAY) { return 0; } - return FixedListType::getNumValuesInList(static_cast(data_type->_data_type)); + return ArrayType::getNumElements(static_cast(data_type->_data_type)); } diff --git a/src/c_api/database.cpp b/src/c_api/database.cpp index 18d27f29960..97403d791fb 100644 --- a/src/c_api/database.cpp +++ b/src/c_api/database.cpp @@ -9,9 +9,9 @@ kuzu_database* kuzu_database_init(const char* database_path, kuzu_system_config auto database = (kuzu_database*)malloc(sizeof(kuzu_database)); std::string database_path_str = database_path; try { - database->_database = new Database( - database_path_str, SystemConfig(config.buffer_pool_size, config.max_num_threads, - config.enable_compression, config.read_only)); + database->_database = new Database(database_path_str, + SystemConfig(config.buffer_pool_size, config.max_num_threads, config.enable_compression, + config.read_only)); } catch (Exception& e) { free(database); return nullptr; diff --git a/src/c_api/flat_tuple.cpp b/src/c_api/flat_tuple.cpp index 5a7aefb6832..4c689355c25 100644 --- a/src/c_api/flat_tuple.cpp +++ b/src/c_api/flat_tuple.cpp @@ -25,7 +25,9 @@ kuzu_value* kuzu_flat_tuple_get_value(kuzu_flat_tuple* flat_tuple, uint64_t inde Value* _value; try { _value = (*flat_tuple_shared_ptr)->getValue(index); - } catch (Exception& e) { return nullptr; } + } catch (Exception& e) { + return nullptr; + } auto* value = (kuzu_value*)malloc(sizeof(kuzu_value)); value->_value = _value; // We set the ownership of the value to C++, so it will not be deleted if the value is destroyed diff --git a/src/c_api/prepared_statement.cpp b/src/c_api/prepared_statement.cpp index c6d5e485eb9..20b25507014 100644 --- a/src/c_api/prepared_statement.cpp +++ b/src/c_api/prepared_statement.cpp @@ -25,7 +25,7 @@ void kuzu_prepared_statement_destroy(kuzu_prepared_statement* prepared_statement delete static_cast>*>( prepared_statement->_bound_values); } - delete prepared_statement; + free(prepared_statement); } bool kuzu_prepared_statement_allow_active_transaction(kuzu_prepared_statement* prepared_statement) { @@ -46,74 +46,74 @@ char* kuzu_prepared_statement_get_error_message(kuzu_prepared_statement* prepare return convertToOwnedCString(error_message); } -void kuzu_prepared_statement_bind_bool( - kuzu_prepared_statement* prepared_statement, const char* param_name, bool value) { +void kuzu_prepared_statement_bind_bool(kuzu_prepared_statement* prepared_statement, + const char* param_name, bool value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_int64( - kuzu_prepared_statement* prepared_statement, const char* param_name, int64_t value) { +void kuzu_prepared_statement_bind_int64(kuzu_prepared_statement* prepared_statement, + const char* param_name, int64_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_int32( - kuzu_prepared_statement* prepared_statement, const char* param_name, int32_t value) { +void kuzu_prepared_statement_bind_int32(kuzu_prepared_statement* prepared_statement, + const char* param_name, int32_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_int16( - kuzu_prepared_statement* prepared_statement, const char* param_name, int16_t value) { +void kuzu_prepared_statement_bind_int16(kuzu_prepared_statement* prepared_statement, + const char* param_name, int16_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_int8( - kuzu_prepared_statement* prepared_statement, const char* param_name, int8_t value) { +void kuzu_prepared_statement_bind_int8(kuzu_prepared_statement* prepared_statement, + const char* param_name, int8_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_uint64( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint64_t value) { +void kuzu_prepared_statement_bind_uint64(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint64_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_uint32( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint32_t value) { +void kuzu_prepared_statement_bind_uint32(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint32_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_uint16( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint16_t value) { +void kuzu_prepared_statement_bind_uint16(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint16_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_uint8( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint8_t value) { +void kuzu_prepared_statement_bind_uint8(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint8_t value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_double( - kuzu_prepared_statement* prepared_statement, const char* param_name, double value) { +void kuzu_prepared_statement_bind_double(kuzu_prepared_statement* prepared_statement, + const char* param_name, double value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_float( - kuzu_prepared_statement* prepared_statement, const char* param_name, float value) { +void kuzu_prepared_statement_bind_float(kuzu_prepared_statement* prepared_statement, + const char* param_name, float value) { auto value_ptr = std::make_unique(value); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_date( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_date_t value) { +void kuzu_prepared_statement_bind_date(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_date_t value) { auto value_ptr = std::make_unique(date_t(value.days)); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } @@ -142,26 +142,26 @@ void kuzu_prepared_statement_bind_timestamp_tz(kuzu_prepared_statement* prepared kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_timestamp( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_timestamp_t value) { +void kuzu_prepared_statement_bind_timestamp(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_timestamp_t value) { auto value_ptr = std::make_unique(timestamp_t(value.value)); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_interval( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_interval_t value) { +void kuzu_prepared_statement_bind_interval(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_interval_t value) { auto value_ptr = std::make_unique(interval_t(value.months, value.days, value.micros)); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_string( - kuzu_prepared_statement* prepared_statement, const char* param_name, const char* value) { +void kuzu_prepared_statement_bind_string(kuzu_prepared_statement* prepared_statement, + const char* param_name, const char* value) { auto value_ptr = std::make_unique(LogicalType::STRING(), std::string(value)); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } -void kuzu_prepared_statement_bind_value( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_value* value) { +void kuzu_prepared_statement_bind_value(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_value* value) { auto value_ptr = std::make_unique(*static_cast(value->_value)); kuzu_prepared_statement_bind_cpp_value(prepared_statement, param_name, std::move(value_ptr)); } diff --git a/src/c_api/query_result.cpp b/src/c_api/query_result.cpp index 8bdc49d2b38..508ccc2f059 100644 --- a/src/c_api/query_result.cpp +++ b/src/c_api/query_result.cpp @@ -12,9 +12,11 @@ void kuzu_query_result_destroy(kuzu_query_result* query_result) { return; } if (query_result->_query_result != nullptr) { - delete static_cast(query_result->_query_result); + if (!query_result->_is_owned_by_cpp) { + delete static_cast(query_result->_query_result); + } } - delete query_result; + free(query_result); } bool kuzu_query_result_is_success(kuzu_query_result* query_result) { @@ -41,8 +43,8 @@ char* kuzu_query_result_get_column_name(kuzu_query_result* query_result, uint64_ return convertToOwnedCString(column_names[index]); } -kuzu_logical_type* kuzu_query_result_get_column_data_type( - kuzu_query_result* query_result, uint64_t index) { +kuzu_logical_type* kuzu_query_result_get_column_data_type(kuzu_query_result* query_result, + uint64_t index) { auto column_data_types = static_cast(query_result->_query_result)->getColumnDataTypes(); if (index >= column_data_types.size()) { @@ -69,6 +71,22 @@ bool kuzu_query_result_has_next(kuzu_query_result* query_result) { return static_cast(query_result->_query_result)->hasNext(); } +bool kuzu_query_result_has_next_query_result(kuzu_query_result* query_result) { + return static_cast(query_result->_query_result)->hasNextQueryResult(); +} + +kuzu_query_result* kuzu_query_result_get_next_query_result(kuzu_query_result* query_result) { + auto next_query_result = + static_cast(query_result->_query_result)->getNextQueryResult(); + if (next_query_result == nullptr) { + return nullptr; + } + auto* c_query_result = (kuzu_query_result*)malloc(sizeof(kuzu_query_result)); + c_query_result->_query_result = next_query_result; + c_query_result->_is_owned_by_cpp = true; + return c_query_result; +} + kuzu_flat_tuple* kuzu_query_result_get_next(kuzu_query_result* query_result) { auto flat_tuple = static_cast(query_result->_query_result)->getNext(); auto* flat_tuple_c = (kuzu_flat_tuple*)malloc(sizeof(kuzu_flat_tuple)); @@ -89,7 +107,7 @@ struct ArrowSchema kuzu_query_result_get_arrow_schema(kuzu_query_result* query_r return *static_cast(query_result->_query_result)->getArrowSchema(); } -struct ArrowArray kuzu_query_result_get_next_arrow_chunk( - kuzu_query_result* query_result, int64_t chunk_size) { +struct ArrowArray kuzu_query_result_get_next_arrow_chunk(kuzu_query_result* query_result, + int64_t chunk_size) { return *static_cast(query_result->_query_result)->getNextArrowChunk(chunk_size); } diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 720adba49aa..4b39975d4f9 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -1,13 +1,18 @@ #include "catalog/catalog.h" +#include "binder/ddl/bound_alter_info.h" +#include "binder/ddl/bound_create_table_info.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "catalog/catalog_entry/rel_group_catalog_entry.h" #include "catalog/catalog_entry/rel_table_catalog_entry.h" +#include "catalog/catalog_entry/scalar_macro_catalog_entry.h" +#include "common/exception/catalog.h" #include "storage/wal/wal.h" #include "transaction/transaction.h" #include "transaction/transaction_action.h" +using namespace kuzu::binder; using namespace kuzu::common; using namespace kuzu::storage; using namespace kuzu::transaction; @@ -43,11 +48,11 @@ table_id_t Catalog::getTableID(Transaction* tx, const std::string& tableName) co return getVersion(tx)->getTableID(tableName); } -std::vector Catalog::getNodeTableIDs(Transaction* tx) const { +std::vector Catalog::getNodeTableIDs(Transaction* tx) const { return getVersion(tx)->getTableIDs(CatalogEntryType::NODE_TABLE_ENTRY); } -std::vector Catalog::getRelTableIDs(Transaction* tx) const { +std::vector Catalog::getRelTableIDs(Transaction* tx) const { return getVersion(tx)->getTableIDs(CatalogEntryType::REL_TABLE_ENTRY); } @@ -55,8 +60,7 @@ std::string Catalog::getTableName(Transaction* tx, table_id_t tableID) const { return getVersion(tx)->getTableName(tableID); } -TableCatalogEntry* Catalog::getTableCatalogEntry( - transaction::Transaction* tx, common::table_id_t tableID) const { +TableCatalogEntry* Catalog::getTableCatalogEntry(Transaction* tx, table_id_t tableID) const { return ku_dynamic_cast( getVersion(tx)->getTableCatalogEntry(tableID)); } @@ -66,23 +70,22 @@ std::vector Catalog::getNodeTableEntries(Transaction* tx CatalogEntryType::NODE_TABLE_ENTRY); } -std::vector Catalog::getRelTableEntries(transaction::Transaction* tx) const { +std::vector Catalog::getRelTableEntries(Transaction* tx) const { return getVersion(tx)->getTableCatalogEntries( CatalogEntryType::REL_TABLE_ENTRY); } -std::vector Catalog::getRelTableGroupEntries( - transaction::Transaction* tx) const { +std::vector Catalog::getRelTableGroupEntries(Transaction* tx) const { return getVersion(tx)->getTableCatalogEntries( CatalogEntryType::REL_GROUP_ENTRY); } -std::vector Catalog::getRdfGraphEntries(transaction::Transaction* tx) const { +std::vector Catalog::getRdfGraphEntries(Transaction* tx) const { return getVersion(tx)->getTableCatalogEntries( CatalogEntryType::RDF_GRAPH_ENTRY); } -std::vector Catalog::getTableEntries(transaction::Transaction* tx) const { +std::vector Catalog::getTableEntries(Transaction* tx) const { std::vector result; for (auto& [_, entry] : getVersion(tx)->tables->getEntries()) { result.push_back(ku_dynamic_cast(entry.get())); @@ -90,8 +93,8 @@ std::vector Catalog::getTableEntries(transaction::Transactio return result; } -std::vector Catalog::getTableSchemas( - Transaction* tx, const table_id_vector_t& tableIDs) const { +std::vector Catalog::getTableSchemas(Transaction* tx, + const table_id_vector_t& tableIDs) const { std::vector result; for (auto tableID : tableIDs) { result.push_back(ku_dynamic_cast( @@ -100,10 +103,6 @@ std::vector Catalog::getTableSchemas( return result; } -CatalogSet* Catalog::getFunctions(Transaction* tx) const { - return getVersion(tx)->functions.get(); -} - void Catalog::prepareCommitOrRollback(TransactionAction action) { if (hasUpdates()) { wal->logCatalogRecord(); @@ -120,33 +119,37 @@ void Catalog::checkpointInMemory() { } } -ExpressionType Catalog::getFunctionType(Transaction* tx, const std::string& name) const { - return getVersion(tx)->getFunctionType(name); -} - -table_id_t Catalog::addNodeTableSchema(const binder::BoundCreateTableInfo& info) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - return readWriteVersion->createNodeTable(info); -} - -table_id_t Catalog::addRelTableSchema(const binder::BoundCreateTableInfo& info) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - return readWriteVersion->createRelTable(info); -} - -common::table_id_t Catalog::addRelTableGroupSchema(const binder::BoundCreateTableInfo& info) { +table_id_t Catalog::createTableSchema(const BoundCreateTableInfo& info) { KU_ASSERT(readWriteVersion != nullptr); setToUpdated(); - auto tableID = readWriteVersion->createRelGroup(info); + auto tableID = readWriteVersion->createTable(info); + logCreateTableToWAL(info, tableID); return tableID; } -table_id_t Catalog::addRdfGraphSchema(const binder::BoundCreateTableInfo& info) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - return readWriteVersion->createRDFGraph(info); +void Catalog::logCreateTableToWAL(const BoundCreateTableInfo& info, table_id_t tableID) { + auto tableEntry = readWriteVersion->getTableCatalogEntry(tableID); + switch (info.type) { + case TableType::NODE: + case TableType::REL: { + wal->logCreateTableRecord(tableID, info.type); + } break; + case TableType::REL_GROUP: { + auto newRelGroupEntry = ku_dynamic_cast(tableEntry); + for (auto& relTableID : newRelGroupEntry->getRelTableIDs()) { + wal->logCreateTableRecord(relTableID, TableType::REL); + } + } break; + case TableType::RDF: { + auto rdfGraphEntry = ku_dynamic_cast(tableEntry); + wal->logCreateRdfGraphRecord(tableID, rdfGraphEntry->getResourceTableID(), + rdfGraphEntry->getLiteralTableID(), rdfGraphEntry->getResourceTripleTableID(), + rdfGraphEntry->getLiteralTripleTableID()); + } break; + default: { + KU_UNREACHABLE; + } + } } void Catalog::dropTableSchema(table_id_t tableID) { @@ -187,64 +190,36 @@ void Catalog::dropTableSchema(table_id_t tableID) { } } -void Catalog::renameTable(table_id_t tableID, const std::string& newName) { +void Catalog::alterTableSchema(const BoundAlterInfo& info) { KU_ASSERT(readWriteVersion != nullptr); setToUpdated(); - auto tableEntry = readWriteVersion->getTableCatalogEntry(tableID); - switch (tableEntry->getType()) { - case CatalogEntryType::RDF_GRAPH_ENTRY: { - auto rdfGraphSchema = ku_dynamic_cast(tableEntry); - readWriteVersion->renameTable(rdfGraphSchema->getResourceTableID(), - RDFGraphCatalogEntry::getResourceTableName(newName)); - readWriteVersion->renameTable(rdfGraphSchema->getLiteralTableID(), - RDFGraphCatalogEntry::getLiteralTableName(newName)); - readWriteVersion->renameTable(rdfGraphSchema->getResourceTripleTableID(), - RDFGraphCatalogEntry::getResourceTripleTableName(newName)); - readWriteVersion->renameTable(rdfGraphSchema->getLiteralTripleTableID(), - RDFGraphCatalogEntry::getLiteralTripleTableName(newName)); - readWriteVersion->renameTable(tableID, newName); + readWriteVersion->alterTable(info); + logAlterTableToWAL(info); +} + +void Catalog::logAlterTableToWAL(const BoundAlterInfo& info) { + auto tableSchema = ku_dynamic_cast( + readWriteVersion->getTableCatalogEntry(info.tableID)); + switch (info.alterType) { + case AlterType::ADD_PROPERTY: { + auto& addPropInfo = + ku_dynamic_cast( + *info.extraInfo); + wal->logAddPropertyRecord(info.tableID, + tableSchema->getPropertyID(addPropInfo.propertyName)); + } break; + case AlterType::DROP_PROPERTY: { + auto& dropPropInfo = + ku_dynamic_cast( + *info.extraInfo); + wal->logDropPropertyRecord(info.tableID, dropPropInfo.propertyID); } break; default: { - readWriteVersion->renameTable(tableID, newName); + // DO NOTHING. } } } -void Catalog::addNodeProperty( - table_id_t tableID, const std::string& propertyName, std::unique_ptr dataType) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - auto tableEntry = readWriteVersion->getTableCatalogEntry(tableID); - ku_dynamic_cast(tableEntry) - ->addProperty(propertyName, std::move(dataType)); -} - -void Catalog::addRelProperty( - table_id_t tableID, const std::string& propertyName, std::unique_ptr dataType) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - auto tableEntry = readWriteVersion->getTableCatalogEntry(tableID); - ku_dynamic_cast(tableEntry) - ->addProperty(propertyName, std::move(dataType)); -} - -void Catalog::dropProperty(table_id_t tableID, property_id_t propertyID) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - auto tableEntry = readWriteVersion->getTableCatalogEntry(tableID); - ku_dynamic_cast(tableEntry)->dropProperty(propertyID); - wal->logDropPropertyRecord(tableID, propertyID); -} - -void Catalog::renameProperty( - table_id_t tableID, property_id_t propertyID, const std::string& newName) { - KU_ASSERT(readWriteVersion != nullptr); - setToUpdated(); - auto tableEntry = readWriteVersion->getTableCatalogEntry(tableID); - ku_dynamic_cast(tableEntry) - ->renameProperty(propertyID, newName); -} - void Catalog::addFunction(std::string name, function::function_set functionSet) { initCatalogContentForWriteTrxIfNecessary(); KU_ASSERT(readWriteVersion != nullptr); @@ -256,18 +231,32 @@ void Catalog::addBuiltInFunction(std::string name, function::function_set functi readOnlyVersion->addFunction(std::move(name), std::move(functionSet)); } +CatalogSet* Catalog::getFunctions(Transaction* tx) const { + return getVersion(tx)->functions.get(); +} + +CatalogEntry* Catalog::getFunctionEntry(Transaction* tx, const std::string& name) { + auto catalogSet = getVersion(tx)->functions.get(); + if (!catalogSet->containsEntry(name)) { + throw CatalogException(stringFormat("function {} does not exist.", name)); + } + return catalogSet->getEntry(name); +} + bool Catalog::containsMacro(Transaction* tx, const std::string& macroName) const { return getVersion(tx)->containMacro(macroName); } -void Catalog::addScalarMacroFunction( - std::string name, std::unique_ptr macro) { +void Catalog::addScalarMacroFunction(std::string name, + std::unique_ptr macro) { KU_ASSERT(readWriteVersion != nullptr); setToUpdated(); - readWriteVersion->addScalarMacroFunction(std::move(name), std::move(macro)); + auto scalarMacroCatalogEntry = + std::make_unique(std::move(name), std::move(macro)); + readWriteVersion->functions->createEntry(std::move(scalarMacroCatalogEntry)); } -std::vector Catalog::getMacroNames(transaction::Transaction* tx) const { +std::vector Catalog::getMacroNames(Transaction* tx) const { std::vector macroNames; for (auto& [_, function] : getVersion(tx)->functions->getEntries()) { if (function->getType() == CatalogEntryType::SCALAR_MACRO_ENTRY) { diff --git a/src/catalog/catalog_content.cpp b/src/catalog/catalog_content.cpp index 00f3bd8ec68..9b11b84ce39 100644 --- a/src/catalog/catalog_content.cpp +++ b/src/catalog/catalog_content.cpp @@ -2,12 +2,13 @@ #include +#include "binder/ddl/bound_alter_info.h" #include "binder/ddl/bound_create_table_info.h" +#include "catalog/catalog_entry/function_catalog_entry.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" #include "catalog/catalog_entry/rel_group_catalog_entry.h" #include "catalog/catalog_entry/rel_table_catalog_entry.h" -#include "catalog/catalog_entry/scalar_function_catalog_entry.h" #include "catalog/catalog_entry/scalar_macro_catalog_entry.h" #include "common/cast.h" #include "common/exception/catalog.h" @@ -17,8 +18,9 @@ #include "common/serializer/deserializer.h" #include "common/serializer/serializer.h" #include "common/string_format.h" -#include "storage/storage_info.h" +#include "function/built_in_function_utils.h" #include "storage/storage_utils.h" +#include "storage/storage_version_info.h" using namespace kuzu::binder; using namespace kuzu::common; @@ -27,7 +29,7 @@ using namespace kuzu::storage; namespace kuzu { namespace catalog { -CatalogContent::CatalogContent(common::VirtualFileSystem* vfs) : nextTableID{0}, vfs{vfs} { +CatalogContent::CatalogContent(VirtualFileSystem* vfs) : nextTableID{0}, vfs{vfs} { tables = std::make_unique(); functions = std::make_unique(); registerBuiltInFunctions(); @@ -38,24 +40,47 @@ CatalogContent::CatalogContent(const std::string& directory, VirtualFileSystem* registerBuiltInFunctions(); } -table_id_t CatalogContent::createNodeTable(const binder::BoundCreateTableInfo& info) { +table_id_t CatalogContent::createTable(const BoundCreateTableInfo& info) { table_id_t tableID = assignNextTableID(); - auto extraInfo = ku_dynamic_cast( - info.extraInfo.get()); + std::unique_ptr entry; + switch (info.type) { + case TableType::NODE: { + entry = createNodeTableEntry(tableID, info); + } break; + case TableType::REL: { + entry = createRelTableEntry(tableID, info); + } break; + case TableType::REL_GROUP: { + entry = createRelTableGroupEntry(tableID, info); + } break; + case TableType::RDF: { + entry = createRdfGraphEntry(tableID, info); + } break; + default: + KU_UNREACHABLE; + } + tables->createEntry(std::move(entry)); + return tableID; +} + +std::unique_ptr CatalogContent::createNodeTableEntry(table_id_t tableID, + const BoundCreateTableInfo& info) const { + auto extraInfo = + ku_dynamic_cast( + info.extraInfo.get()); auto nodeTableEntry = std::make_unique(info.tableName, tableID, extraInfo->primaryKeyIdx); for (auto& propertyInfo : extraInfo->propertyInfos) { nodeTableEntry->addProperty(propertyInfo.name, propertyInfo.type.copy()); } - tableNameToIDMap.emplace(nodeTableEntry->getName(), tableID); - tables->createEntry(std::move(nodeTableEntry)); - return tableID; + return nodeTableEntry; } -table_id_t CatalogContent::createRelTable(const binder::BoundCreateTableInfo& info) { - table_id_t tableID = assignNextTableID(); - auto extraInfo = ku_dynamic_cast( - info.extraInfo.get()); +std::unique_ptr CatalogContent::createRelTableEntry(table_id_t tableID, + const BoundCreateTableInfo& info) const { + auto extraInfo = + ku_dynamic_cast( + info.extraInfo.get()); auto srcTableEntry = ku_dynamic_cast( getTableCatalogEntry(extraInfo->srcTableID)); auto dstTableEntry = ku_dynamic_cast( @@ -68,63 +93,56 @@ table_id_t CatalogContent::createRelTable(const binder::BoundCreateTableInfo& in for (auto& propertyInfo : extraInfo->propertyInfos) { relTableEntry->addProperty(propertyInfo.name, propertyInfo.type.copy()); } - tableNameToIDMap.emplace(relTableEntry->getName(), tableID); - tables->createEntry(std::move(relTableEntry)); - return tableID; + return relTableEntry; } -table_id_t CatalogContent::createRelGroup(const binder::BoundCreateTableInfo& info) { - auto relGroupID = assignNextTableID(); - auto extraInfo = (BoundExtraCreateRelTableGroupInfo*)info.extraInfo.get(); +std::unique_ptr CatalogContent::createRelTableGroupEntry(table_id_t tableID, + const BoundCreateTableInfo& info) { + auto extraInfo = + ku_dynamic_cast( + info.extraInfo.get()); std::vector relTableIDs; relTableIDs.reserve(extraInfo->infos.size()); for (auto& childInfo : extraInfo->infos) { - relTableIDs.push_back(createRelTable(childInfo)); + relTableIDs.push_back(createTable(childInfo)); } - auto relGroupName = info.tableName; - auto relGroupEntry = - std::make_unique(relGroupName, relGroupID, std::move(relTableIDs)); - tableNameToIDMap.emplace(relGroupName, relGroupID); - tables->createEntry(std::move(relGroupEntry)); - return relGroupID; + return std::make_unique(info.tableName, tableID, std::move(relTableIDs)); } -table_id_t CatalogContent::createRDFGraph(const binder::BoundCreateTableInfo& info) { - table_id_t rdfGraphID = assignNextTableID(); - auto extraInfo = ku_dynamic_cast( - info.extraInfo.get()); +std::unique_ptr CatalogContent::createRdfGraphEntry(table_id_t tableID, + const BoundCreateTableInfo& info) { + auto extraInfo = + ku_dynamic_cast( + info.extraInfo.get()); auto& resourceInfo = extraInfo->resourceInfo; auto& literalInfo = extraInfo->literalInfo; auto& resourceTripleInfo = extraInfo->resourceTripleInfo; auto& literalTripleInfo = extraInfo->literalTripleInfo; auto resourceTripleExtraInfo = - ku_dynamic_cast( + ku_dynamic_cast( resourceTripleInfo.extraInfo.get()); auto literalTripleExtraInfo = - ku_dynamic_cast( + ku_dynamic_cast( literalTripleInfo.extraInfo.get()); // Resource table - auto resourceTableID = createNodeTable(resourceInfo); + auto resourceTableID = createTable(resourceInfo); // Literal table - auto literalTableID = createNodeTable(literalInfo); + auto literalTableID = createTable(literalInfo); // Resource triple table resourceTripleExtraInfo->srcTableID = resourceTableID; resourceTripleExtraInfo->dstTableID = resourceTableID; - auto resourceTripleTableID = createRelTable(resourceTripleInfo); + auto resourceTripleTableID = createTable(resourceTripleInfo); // Literal triple table literalTripleExtraInfo->srcTableID = resourceTableID; literalTripleExtraInfo->dstTableID = literalTableID; - auto literalTripleTableID = createRelTable(literalTripleInfo); + auto literalTripleTableID = createTable(literalTripleInfo); // Rdf graph entry auto rdfGraphName = info.tableName; - auto rdfGraphEntry = std::make_unique(rdfGraphName, rdfGraphID, - resourceTableID, literalTableID, resourceTripleTableID, literalTripleTableID); - tableNameToIDMap.emplace(rdfGraphName, rdfGraphID); - tables->createEntry(std::move(rdfGraphEntry)); - return rdfGraphID; + return std::make_unique(rdfGraphName, tableID, resourceTableID, + literalTableID, resourceTripleTableID, literalTripleTableID); } -void CatalogContent::dropTable(common::table_id_t tableID) { +void CatalogContent::dropTable(table_id_t tableID) { auto tableEntry = getTableCatalogEntry(tableID); if (tableEntry->getType() == CatalogEntryType::REL_GROUP_ENTRY) { auto relGroupEntry = ku_dynamic_cast(tableEntry); @@ -132,14 +150,61 @@ void CatalogContent::dropTable(common::table_id_t tableID) { dropTable(relTableID); } } - tableNameToIDMap.erase(tableEntry->getName()); tables->removeEntry(tableEntry->getName()); } +void CatalogContent::alterTable(const BoundAlterInfo& info) { + switch (info.alterType) { + case AlterType::RENAME_TABLE: { + auto& renameInfo = + ku_dynamic_cast( + *info.extraInfo); + renameTable(info.tableID, renameInfo.newName); + } break; + case AlterType::ADD_PROPERTY: { + auto& addPropInfo = + ku_dynamic_cast( + *info.extraInfo); + auto tableEntry = + ku_dynamic_cast(getTableCatalogEntry(info.tableID)); + tableEntry->addProperty(addPropInfo.propertyName, addPropInfo.dataType.copy()); + } break; + case AlterType::RENAME_PROPERTY: { + auto& renamePropInfo = + ku_dynamic_cast( + *info.extraInfo); + auto tableEntry = + ku_dynamic_cast(getTableCatalogEntry(info.tableID)); + tableEntry->renameProperty(renamePropInfo.propertyID, renamePropInfo.newName); + } break; + case AlterType::DROP_PROPERTY: { + auto& dropPropInfo = + ku_dynamic_cast( + *info.extraInfo); + auto tableEntry = + ku_dynamic_cast(getTableCatalogEntry(info.tableID)); + tableEntry->dropProperty(dropPropInfo.propertyID); + } break; + default: { + KU_UNREACHABLE; + } + } +} + void CatalogContent::renameTable(table_id_t tableID, const std::string& newName) { + // TODO(Xiyang/Ziyi): Do we allow renaming of rel table groups? auto tableEntry = getTableCatalogEntry(tableID); - tableNameToIDMap.erase(tableEntry->getName()); - tableNameToIDMap.emplace(newName, tableID); + if (tableEntry->getType() == CatalogEntryType::RDF_GRAPH_ENTRY) { + auto rdfGraphEntry = ku_dynamic_cast(tableEntry); + renameTable(rdfGraphEntry->getResourceTableID(), + RDFGraphCatalogEntry::getResourceTableName(newName)); + renameTable(rdfGraphEntry->getLiteralTableID(), + RDFGraphCatalogEntry::getLiteralTableName(newName)); + renameTable(rdfGraphEntry->getResourceTripleTableID(), + RDFGraphCatalogEntry::getResourceTripleTableName(newName)); + renameTable(rdfGraphEntry->getLiteralTripleTableID(), + RDFGraphCatalogEntry::getLiteralTripleTableName(newName)); + } tables->renameEntry(tableEntry->getName(), newName); } @@ -194,43 +259,16 @@ void CatalogContent::readFromFile(const std::string& directory, FileVersionType deserializer.deserializeValue(savedStorageVersion); validateStorageVersion(savedStorageVersion); tables = CatalogSet::deserialize(deserializer); - for (auto& [name, entry] : tables->getEntries()) { - tableNameToIDMap[entry->getName()] = - ku_dynamic_cast(entry.get())->getTableID(); - } deserializer.deserializeValue(nextTableID); functions = CatalogSet::deserialize(deserializer); } -ExpressionType CatalogContent::getFunctionType(const std::string& name) const { - if (!functions->containsEntry(name)) { - throw CatalogException{common::stringFormat("function {} does not exist.", name)}; - } - auto functionEntry = functions->getEntry(name); - switch (functionEntry->getType()) { - case CatalogEntryType::SCALAR_MACRO_ENTRY: - return ExpressionType::MACRO; - case CatalogEntryType::SCALAR_FUNCTION_ENTRY: - return ExpressionType::FUNCTION; - case CatalogEntryType::AGGREGATE_FUNCTION_ENTRY: - return ExpressionType::AGGREGATE_FUNCTION; - default: - KU_UNREACHABLE; - } -} - void CatalogContent::addFunction(std::string name, function::function_set definitions) { if (functions->containsEntry(name)) { - throw CatalogException{common::stringFormat("function {} already exists.", name)}; + throw CatalogException{stringFormat("function {} already exists.", name)}; } - functions->createEntry( - std::make_unique(std::move(name), std::move(definitions))); -} - -void CatalogContent::addScalarMacroFunction( - std::string name, std::unique_ptr macro) { - functions->createEntry( - std::make_unique(std::move(name), std::move(macro))); + functions->createEntry(std::make_unique( + CatalogEntryType::SCALAR_FUNCTION_ENTRY, std::move(name), std::move(definitions))); } function::ScalarMacroFunction* CatalogContent::getScalarMacroFunction( @@ -241,8 +279,7 @@ function::ScalarMacroFunction* CatalogContent::getScalarMacroFunction( std::unique_ptr CatalogContent::copy() const { std::unordered_map> macrosToCopy; - return std::make_unique( - tables->copy(), tableNameToIDMap, nextTableID, functions->copy(), vfs); + return std::make_unique(tables->copy(), nextTableID, functions->copy(), vfs); } void CatalogContent::registerBuiltInFunctions() { @@ -250,7 +287,7 @@ void CatalogContent::registerBuiltInFunctions() { } bool CatalogContent::containsTable(const std::string& tableName) const { - return tableNameToIDMap.contains(tableName); + return tables->containsEntry(tableName); } bool CatalogContent::containsTable(CatalogEntryType tableType) const { @@ -276,13 +313,12 @@ CatalogEntry* CatalogContent::getTableCatalogEntry(table_id_t tableID) const { KU_UNREACHABLE; } -common::table_id_t CatalogContent::getTableID(const std::string& tableName) const { +table_id_t CatalogContent::getTableID(const std::string& tableName) const { if (tables->containsEntry(tableName)) { return ku_dynamic_cast(tables->getEntry(tableName)) ->getTableID(); } else { - throw common::CatalogException{ - common::stringFormat("Table: {} does not exist.", tableName)}; + throw CatalogException{stringFormat("Table: {} does not exist.", tableName)}; } } diff --git a/src/catalog/catalog_entry/CMakeLists.txt b/src/catalog/catalog_entry/CMakeLists.txt index 52560c84ecc..648fc3041b6 100644 --- a/src/catalog/catalog_entry/CMakeLists.txt +++ b/src/catalog/catalog_entry/CMakeLists.txt @@ -1,6 +1,5 @@ add_library(kuzu_catalog_entry OBJECT - aggregate_function_catalog_entry.cpp catalog_entry.cpp function_catalog_entry.cpp table_catalog_entry.cpp @@ -8,9 +7,7 @@ add_library(kuzu_catalog_entry rel_table_catalog_entry.cpp rel_group_catalog_entry.cpp rdf_graph_catalog_entry.cpp - scalar_macro_catalog_entry.cpp - scalar_function_catalog_entry.cpp - table_function_catalog_entry.cpp) + scalar_macro_catalog_entry.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/catalog/catalog_entry/aggregate_function_catalog_entry.cpp b/src/catalog/catalog_entry/aggregate_function_catalog_entry.cpp deleted file mode 100644 index 157e9d2e03e..00000000000 --- a/src/catalog/catalog_entry/aggregate_function_catalog_entry.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "catalog/catalog_entry/aggregate_function_catalog_entry.h" - -#include "common/utils.h" - -namespace kuzu { -namespace catalog { - -AggregateFunctionCatalogEntry::AggregateFunctionCatalogEntry( - std::string name, function::function_set functionSet) - : FunctionCatalogEntry{ - CatalogEntryType::AGGREGATE_FUNCTION_ENTRY, std::move(name), std::move(functionSet)} {} - -std::unique_ptr AggregateFunctionCatalogEntry::copy() const { - return std::make_unique( - getName(), common::copyVector(functionSet)); -} - -} // namespace catalog -} // namespace kuzu diff --git a/src/catalog/catalog_entry/function_catalog_entry.cpp b/src/catalog/catalog_entry/function_catalog_entry.cpp index edc8c74164d..293ae88cf92 100644 --- a/src/catalog/catalog_entry/function_catalog_entry.cpp +++ b/src/catalog/catalog_entry/function_catalog_entry.cpp @@ -5,13 +5,13 @@ namespace kuzu { namespace catalog { -FunctionCatalogEntry::FunctionCatalogEntry( - CatalogEntryType entryType, std::string name, function::function_set functionSet) +FunctionCatalogEntry::FunctionCatalogEntry(CatalogEntryType entryType, std::string name, + function::function_set functionSet) : CatalogEntry{entryType, std::move(name)}, functionSet{std::move(functionSet)} {} std::unique_ptr FunctionCatalogEntry::copy() const { - return std::make_unique( - getType(), getName(), common::copyVector>(functionSet)); + return std::make_unique(getType(), getName(), + common::copyVector>(functionSet)); } } // namespace catalog diff --git a/src/catalog/catalog_entry/node_table_catalog_entry.cpp b/src/catalog/catalog_entry/node_table_catalog_entry.cpp index 451bcb128e4..fb1398c94bc 100644 --- a/src/catalog/catalog_entry/node_table_catalog_entry.cpp +++ b/src/catalog/catalog_entry/node_table_catalog_entry.cpp @@ -1,12 +1,10 @@ #include "catalog/catalog_entry/node_table_catalog_entry.h" -#include - namespace kuzu { namespace catalog { -NodeTableCatalogEntry::NodeTableCatalogEntry( - std::string name, common::table_id_t tableID, common::property_id_t primaryKeyPID) +NodeTableCatalogEntry::NodeTableCatalogEntry(std::string name, common::table_id_t tableID, + common::property_id_t primaryKeyPID) : TableCatalogEntry{CatalogEntryType::NODE_TABLE_ENTRY, std::move(name), tableID}, primaryKeyPID{primaryKeyPID} {} @@ -44,11 +42,8 @@ std::unique_ptr NodeTableCatalogEntry::copy() const { } std::string NodeTableCatalogEntry::toCypher(main::ClientContext* /*clientContext*/) const { - std::stringstream ss; - ss << "CREATE NODE TABLE " << getName() << "("; - Property::toCypher(getPropertiesRef(), ss); - ss << " PRIMARY KEY(" << getPrimaryKey()->getName() << "));"; - return ss.str(); + return common::stringFormat("CREATE NODE TABLE {} ({} PRIMARY KEY({}));", getName(), + Property::toCypher(getPropertiesRef()), getPrimaryKey()->getName()); } } // namespace catalog diff --git a/src/catalog/catalog_entry/rel_group_catalog_entry.cpp b/src/catalog/catalog_entry/rel_group_catalog_entry.cpp index 17711e028af..c047ac11201 100644 --- a/src/catalog/catalog_entry/rel_group_catalog_entry.cpp +++ b/src/catalog/catalog_entry/rel_group_catalog_entry.cpp @@ -3,8 +3,8 @@ namespace kuzu { namespace catalog { -RelGroupCatalogEntry::RelGroupCatalogEntry( - std::string tableName, common::table_id_t tableID, std::vector relTableIDs) +RelGroupCatalogEntry::RelGroupCatalogEntry(std::string tableName, common::table_id_t tableID, + std::vector relTableIDs) : TableCatalogEntry{CatalogEntryType::REL_GROUP_ENTRY, std::move(tableName), tableID}, relTableIDs{std::move(relTableIDs)} {} diff --git a/src/catalog/catalog_entry/rel_table_catalog_entry.cpp b/src/catalog/catalog_entry/rel_table_catalog_entry.cpp index 82922f68708..b08a91c780a 100644 --- a/src/catalog/catalog_entry/rel_table_catalog_entry.cpp +++ b/src/catalog/catalog_entry/rel_table_catalog_entry.cpp @@ -1,13 +1,17 @@ #include "catalog/catalog_entry/rel_table_catalog_entry.h" +#include + #include "catalog/catalog.h" +using namespace kuzu::common; + namespace kuzu { namespace catalog { -RelTableCatalogEntry::RelTableCatalogEntry(std::string name, common::table_id_t tableID, - common::RelMultiplicity srcMultiplicity, common::RelMultiplicity dstMultiplicity, - common::table_id_t srcTableID, common::table_id_t dstTableID) +RelTableCatalogEntry::RelTableCatalogEntry(std::string name, table_id_t tableID, + RelMultiplicity srcMultiplicity, RelMultiplicity dstMultiplicity, table_id_t srcTableID, + table_id_t dstTableID) : TableCatalogEntry{CatalogEntryType::REL_TABLE_ENTRY, std::move(name), tableID}, srcMultiplicity{srcMultiplicity}, dstMultiplicity{dstMultiplicity}, srcTableID{srcTableID}, dstTableID{dstTableID} {} @@ -20,27 +24,31 @@ RelTableCatalogEntry::RelTableCatalogEntry(const RelTableCatalogEntry& other) dstTableID = other.dstTableID; } -bool RelTableCatalogEntry::isParent(common::table_id_t tableID) { +bool RelTableCatalogEntry::isParent(table_id_t tableID) { return srcTableID == tableID || dstTableID == tableID; } -bool RelTableCatalogEntry::isSingleMultiplicity(common::RelDataDirection direction) const { - return getMultiplicity(direction) == common::RelMultiplicity::ONE; +column_id_t RelTableCatalogEntry::getColumnID(property_id_t propertyID) const { + auto it = std::find_if(properties.begin(), properties.end(), + [&propertyID](const auto& property) { return property.getPropertyID() == propertyID; }); + // Skip the first column in the rel table, which is reserved for nbrID. + return it == properties.end() ? INVALID_COLUMN_ID : std::distance(properties.begin(), it) + 1; +} + +bool RelTableCatalogEntry::isSingleMultiplicity(RelDataDirection direction) const { + return getMultiplicity(direction) == RelMultiplicity::ONE; } -common::RelMultiplicity RelTableCatalogEntry::getMultiplicity( - common::RelDataDirection direction) const { - return direction == common::RelDataDirection::FWD ? dstMultiplicity : srcMultiplicity; +RelMultiplicity RelTableCatalogEntry::getMultiplicity(RelDataDirection direction) const { + return direction == RelDataDirection::FWD ? dstMultiplicity : srcMultiplicity; } -common::table_id_t RelTableCatalogEntry::getBoundTableID( - common::RelDataDirection relDirection) const { - return relDirection == common::RelDataDirection::FWD ? srcTableID : dstTableID; +table_id_t RelTableCatalogEntry::getBoundTableID(RelDataDirection relDirection) const { + return relDirection == RelDataDirection::FWD ? srcTableID : dstTableID; } -common::table_id_t RelTableCatalogEntry::getNbrTableID( - common::RelDataDirection relDirection) const { - return relDirection == common::RelDataDirection::FWD ? dstTableID : srcTableID; +table_id_t RelTableCatalogEntry::getNbrTableID(RelDataDirection relDirection) const { + return relDirection == RelDataDirection::FWD ? dstTableID : srcTableID; } -void RelTableCatalogEntry::serialize(common::Serializer& serializer) const { +void RelTableCatalogEntry::serialize(Serializer& serializer) const { TableCatalogEntry::serialize(serializer); serializer.write(srcMultiplicity); serializer.write(dstMultiplicity); @@ -49,11 +57,11 @@ void RelTableCatalogEntry::serialize(common::Serializer& serializer) const { } std::unique_ptr RelTableCatalogEntry::deserialize( - common::Deserializer& deserializer) { - common::RelMultiplicity srcMultiplicity; - common::RelMultiplicity dstMultiplicity; - common::table_id_t srcTableID; - common::table_id_t dstTableID; + Deserializer& deserializer) { + RelMultiplicity srcMultiplicity; + RelMultiplicity dstMultiplicity; + table_id_t srcTableID; + table_id_t dstTableID; deserializer.deserializeValue(srcMultiplicity); deserializer.deserializeValue(dstMultiplicity); deserializer.deserializeValue(srcTableID); @@ -75,12 +83,12 @@ std::string RelTableCatalogEntry::toCypher(main::ClientContext* clientContext) c auto catalog = clientContext->getCatalog(); auto srcTableName = catalog->getTableName(clientContext->getTx(), srcTableID); auto dstTableName = catalog->getTableName(clientContext->getTx(), dstTableID); - ss << "CREATE REL TABLE " << getName() << "( FROM " << srcTableName << " TO " << dstTableName - << ", "; - Property::toCypher(getPropertiesRef(), ss); auto srcMultiStr = srcMultiplicity == common::RelMultiplicity::MANY ? "MANY" : "ONE"; auto dstMultiStr = dstMultiplicity == common::RelMultiplicity::MANY ? "MANY" : "ONE"; - ss << srcMultiStr << "_" << dstMultiStr << ");"; + std::string tableInfo = + stringFormat("CREATE REL TABLE {} (FROM {} TO {}, ", getName(), srcTableName, dstTableName); + ss << tableInfo << Property::toCypher(getPropertiesRef()) << srcMultiStr << "_" << dstMultiStr + << ");"; return ss.str(); } diff --git a/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp b/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp deleted file mode 100644 index de921bda66d..00000000000 --- a/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "catalog/catalog_entry/scalar_function_catalog_entry.h" - -#include "common/utils.h" - -namespace kuzu { -namespace catalog { - -ScalarFunctionCatalogEntry::ScalarFunctionCatalogEntry( - std::string name, function::function_set functionSet) - : FunctionCatalogEntry{ - CatalogEntryType::SCALAR_FUNCTION_ENTRY, std::move(name), std::move(functionSet)} {} - -std::unique_ptr ScalarFunctionCatalogEntry::copy() const { - return std::make_unique(getName(), common::copyVector(functionSet)); -} - -} // namespace catalog -} // namespace kuzu diff --git a/src/catalog/catalog_entry/scalar_macro_catalog_entry.cpp b/src/catalog/catalog_entry/scalar_macro_catalog_entry.cpp index aea87f907fd..ce2e695eb6a 100644 --- a/src/catalog/catalog_entry/scalar_macro_catalog_entry.cpp +++ b/src/catalog/catalog_entry/scalar_macro_catalog_entry.cpp @@ -3,10 +3,10 @@ namespace kuzu { namespace catalog { -ScalarMacroCatalogEntry::ScalarMacroCatalogEntry( - std::string name, std::unique_ptr macroFunction) - : CatalogEntry{CatalogEntryType::SCALAR_MACRO_ENTRY, std::move(name)}, macroFunction{std::move( - macroFunction)} {} +ScalarMacroCatalogEntry::ScalarMacroCatalogEntry(std::string name, + std::unique_ptr macroFunction) + : CatalogEntry{CatalogEntryType::SCALAR_MACRO_ENTRY, std::move(name)}, + macroFunction{std::move(macroFunction)} {} void ScalarMacroCatalogEntry::serialize(common::Serializer& serializer) const { CatalogEntry::serialize(serializer); diff --git a/src/catalog/catalog_entry/table_catalog_entry.cpp b/src/catalog/catalog_entry/table_catalog_entry.cpp index cbae0dd4f1c..74edb93d72a 100644 --- a/src/catalog/catalog_entry/table_catalog_entry.cpp +++ b/src/catalog/catalog_entry/table_catalog_entry.cpp @@ -30,19 +30,18 @@ const Property* TableCatalogEntry::getProperty(common::property_id_t propertyID) common::column_id_t TableCatalogEntry::getColumnID(const common::property_id_t propertyID) const { auto it = std::find_if(properties.begin(), properties.end(), [&propertyID](const auto& property) { return property.getPropertyID() == propertyID; }); - return it == properties.end() ? common::INVALID_COLUMN_ID : - std::distance(properties.begin(), it); + KU_ASSERT(it != properties.end()); + return std::distance(properties.begin(), it); } bool TableCatalogEntry::containPropertyType(const common::LogicalType& logicalType) const { - return std::any_of( - properties.begin(), properties.end(), [&logicalType](const Property& property) { - return *property.getDataType() == logicalType; - }); + return std::any_of(properties.begin(), properties.end(), + [&logicalType]( + const Property& property) { return *property.getDataType() == logicalType; }); } -void TableCatalogEntry::addProperty( - std::string propertyName, std::unique_ptr dataType) { +void TableCatalogEntry::addProperty(std::string propertyName, + std::unique_ptr dataType) { properties.emplace_back(std::move(propertyName), std::move(dataType), nextPID++, tableID); } @@ -54,8 +53,8 @@ void TableCatalogEntry::dropProperty(common::property_id_t propertyID) { properties.end()); } -void TableCatalogEntry::renameProperty( - common::property_id_t propertyID, const std::string& newName) { +void TableCatalogEntry::renameProperty(common::property_id_t propertyID, + const std::string& newName) { auto it = std::find_if(properties.begin(), properties.end(), [&propertyID](const auto& property) { return property.getPropertyID() == propertyID; }); KU_ASSERT(it != properties.end()); diff --git a/src/catalog/catalog_entry/table_function_catalog_entry.cpp b/src/catalog/catalog_entry/table_function_catalog_entry.cpp deleted file mode 100644 index 26b4f69dd53..00000000000 --- a/src/catalog/catalog_entry/table_function_catalog_entry.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "catalog/catalog_entry/table_function_catalog_entry.h" - -#include "common/utils.h" - -namespace kuzu { -namespace catalog { - -TableFunctionCatalogEntry::TableFunctionCatalogEntry( - std::string name, function::function_set functionSet) - : FunctionCatalogEntry{ - CatalogEntryType::TABLE_FUNCTION_ENTRY, std::move(name), std::move(functionSet)} {} - -std::unique_ptr TableFunctionCatalogEntry::copy() const { - return std::make_unique(getName(), common::copyVector(functionSet)); -} - -} // namespace catalog -} // namespace kuzu diff --git a/src/catalog/catalog_set.cpp b/src/catalog/catalog_set.cpp index 7f0a5122065..0c36fd5a39e 100644 --- a/src/catalog/catalog_set.cpp +++ b/src/catalog/catalog_set.cpp @@ -1,6 +1,10 @@ #include "catalog/catalog_set.h" #include "common/assert.h" +#include "common/exception/catalog.h" +#include "common/string_format.h" + +using namespace kuzu::common; namespace kuzu { namespace catalog { @@ -10,6 +14,13 @@ bool CatalogSet::containsEntry(const std::string& name) const { } CatalogEntry* CatalogSet::getEntry(const std::string& name) { + // LCOV_EXCL_START + // We should not trigger the following check. If so, we should throw more informative error + // message at catalog level. + if (!containsEntry(name)) { + throw CatalogException(stringFormat("Cannot find catalog entry with name {}.", name)); + } + // LCOV_EXCL_STOP return entries.at(name).get(); } @@ -36,6 +47,7 @@ void CatalogSet::serialize(common::Serializer serializer) const { for (auto& [name, entry] : entries) { switch (entry->getType()) { case CatalogEntryType::SCALAR_FUNCTION_ENTRY: + case CatalogEntryType::REWRITE_FUNCTION_ENTRY: case CatalogEntryType::AGGREGATE_FUNCTION_ENTRY: case CatalogEntryType::TABLE_FUNCTION_ENTRY: continue; diff --git a/src/catalog/property.cpp b/src/catalog/property.cpp index 2dabd86f2f1..f3da2ab0c88 100644 --- a/src/catalog/property.cpp +++ b/src/catalog/property.cpp @@ -29,8 +29,8 @@ Property Property::deserialize(Deserializer& deserializer) { return Property(name, std::move(dataType), propertyID, tableID); } -void Property::toCypher( - const std::vector& properties, std::stringstream& ss) { +std::string Property::toCypher(const std::vector& properties) { + std::stringstream ss; for (auto& prop : properties) { if (prop.getDataType()->getPhysicalType() == PhysicalTypeID::INTERNAL_ID) { continue; @@ -42,6 +42,7 @@ void Property::toCypher( } ss << prop.getName() << " " << propStr << ","; } + return ss.str(); } } // namespace catalog diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 513ef8acbec..0ae41a12b12 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(file_system) add_library(kuzu_common OBJECT + case_insensitive_map.cpp constants.cpp expression_type.cpp in_mem_overflow_buffer.cpp diff --git a/src/common/arrow/CMakeLists.txt b/src/common/arrow/CMakeLists.txt index c3281117ebf..34f81286f20 100644 --- a/src/common/arrow/CMakeLists.txt +++ b/src/common/arrow/CMakeLists.txt @@ -1,7 +1,10 @@ add_library(kuzu_common_arrow OBJECT + arrow_array_scan.cpp + arrow_converter.cpp + arrow_null_mask_tree.cpp arrow_row_batch.cpp - arrow_converter.cpp) + arrow_type.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/common/arrow/arrow_array_scan.cpp b/src/common/arrow/arrow_array_scan.cpp new file mode 100644 index 00000000000..82aa4bd3cc7 --- /dev/null +++ b/src/common/arrow/arrow_array_scan.cpp @@ -0,0 +1,552 @@ +#include "common/arrow/arrow_converter.h" +#include "common/types/interval_t.h" +#include "common/types/types.h" +#include "common/vector/value_vector.h" + +namespace kuzu { +namespace common { + +// scans are based on data specification found here +// https://arrow.apache.org/docs/format/Columnar.html + +// all offsets are measured by value, not physical size + +template +static void scanArrowArrayFixedSizePrimitive(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto arrayBuffer = (const uint8_t*)array->buffers[1]; + mask->copyToValueVector(&outputVector, dstOffset, count); + memcpy(outputVector.getData() + dstOffset * outputVector.getNumBytesPerValue(), + arrayBuffer + srcOffset * sizeof(T), count * sizeof(T)); +} + +template<> +void scanArrowArrayFixedSizePrimitive(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto arrayBuffer = (const uint8_t*)array->buffers[1]; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + outputVector.setValue(i + dstOffset, + NullMask::isNull((const uint64_t*)arrayBuffer, i + srcOffset)); + } +} + +static void scanArrowArrayDurationScaledUp(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, int64_t scaleFactor, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto arrayBuffer = ((const int64_t*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curValue = arrayBuffer[i]; + outputVector.setValue(i + dstOffset, + interval_t(0, 0, curValue * scaleFactor)); + } + } +} + +static void scanArrowArrayDurationScaledDown(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, int64_t scaleFactor, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto arrayBuffer = ((const int64_t*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curValue = arrayBuffer[i]; + outputVector.setValue(i + dstOffset, + interval_t(0, 0, curValue / scaleFactor)); + } + } +} + +static void scanArrowArrayMonthInterval(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto arrayBuffer = ((const int32_t*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curValue = arrayBuffer[i]; + outputVector.setValue(i + dstOffset, interval_t(curValue, 0, 0)); + } + } +} + +static void scanArrowArrayDayTimeInterval(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto arrayBuffer = ((const int64_t*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + int64_t curValue = arrayBuffer[i]; + int32_t day = curValue; + int64_t micros = (curValue >> (4 * sizeof(int64_t))) * 1000; + // arrow stores ms, while we store us + outputVector.setValue(i + dstOffset, interval_t(0, day, micros)); + } + } +} + +static void scanArrowArrayMonthDayNanoInterval(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto arrayBuffer = + (const int64_t*)((const uint8_t*)array->buffers[1] + srcOffset * 16); // 16 bits per value + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + int64_t curValue = arrayBuffer[2 * i]; + int32_t month = curValue; + int32_t day = curValue >> (4 * sizeof(int64_t)); + int64_t micros = arrayBuffer[2 * i + 1] / 1000; + outputVector.setValue(i + dstOffset, interval_t(month, day, micros)); + } + } +} + +template +static void scanArrowArrayBLOB(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto offsets = ((const offsetsT*)array->buffers[1]) + srcOffset; + auto arrayBuffer = (const uint8_t*)array->buffers[2]; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curOffset = offsets[i], nextOffset = offsets[i + 1]; + const uint8_t* data = arrayBuffer + curOffset; + auto length = nextOffset - curOffset; + BlobVector::addBlob(&outputVector, i + dstOffset, data, length); + } + } +} + +static void scanArrowArrayBLOBView(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, uint64_t count) { + auto arrayBuffer = (const uint8_t*)(array->buffers[1]); + auto valueBuffs = (const uint8_t**)(array->buffers + 2); + // BLOB value buffers begin from index 2 onwards + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curView = (const int32_t*)(arrayBuffer + (i + srcOffset) * 16); + // view structures are 16 bytes long + auto viewLength = curView[0]; + if (viewLength <= 12) { + BlobVector::addBlob(&outputVector, i + dstOffset, (uint8_t*)(curView + 1), + viewLength); + } else { + auto bufIndex = curView[2]; + auto offset = curView[3]; + BlobVector::addBlob(&outputVector, i + dstOffset, valueBuffs[bufIndex] + offset, + viewLength); + } + } + } +} + +static void scanArrowArrayFixedBLOB(const ArrowArray* array, ValueVector& outputVector, + ArrowNullMaskTree* mask, int64_t BLOBsize, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto arrayBuffer = ((const uint8_t*)array->buffers[1]) + srcOffset * BLOBsize; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + BlobVector::addBlob(&outputVector, i + dstOffset, arrayBuffer + i * BLOBsize, BLOBsize); + } + } +} + +template +static void scanArrowArrayList(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto offsets = ((const offsetsT*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + uint64_t auxDstPosition = 0; + for (uint64_t i = 0; i < count; i++) { + auto curOffset = offsets[i], nextOffset = offsets[i + 1]; + if (!mask->isNull(i)) { + auto newEntry = ListVector::addList(&outputVector, nextOffset - curOffset); + outputVector.setValue(i + dstOffset, newEntry); + if (i == 0) { + auxDstPosition = newEntry.offset; + } + } + } + ValueVector* auxiliaryBuffer = ListVector::getDataVector(&outputVector); + ArrowConverter::fromArrowArray(schema->children[0], array->children[0], *auxiliaryBuffer, + mask->getChild(0), offsets[0], auxDstPosition, offsets[count] - offsets[0]); +} + +template +static void scanArrowArrayListView(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto offsets = ((const offsetsT*)array->buffers[1]) + srcOffset; + auto sizes = ((const offsetsT*)array->buffers[2]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + ValueVector* auxiliaryBuffer = ListVector::getDataVector(&outputVector); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curOffset = offsets[i], size = sizes[i]; + auto newEntry = ListVector::addList(&outputVector, size); + outputVector.setValue(i + dstOffset, newEntry); + ArrowNullMaskTree childTree(schema->children[0], array->children[0], srcOffset, count); + // make our own child here. precomputing through the mask tree is too complicated + ArrowConverter::fromArrowArray(schema->children[0], array->children[0], + *auxiliaryBuffer, &childTree, curOffset, newEntry.offset, newEntry.size); + } + } +} +/* +TODO manh: scan arrow fixed list +static void scanArrowArrayFixedList(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + mask->copyToValueVector(&outputVector, dstOffset, count); + int64_t numValuesInList = FixedListType::getNumValuesInList(&outputVector.dataType); + ArrowConverter::fromArrowArray(schema->children[0], array->children[0], outputVector, + mask->getChild(0), srcOffset * numValuesInList, dstOffset * numValuesInList, + count * numValuesInList); +} +*/ + +static void scanArrowArrayStruct(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + outputVector.setValue(i + dstOffset, + i + dstOffset); // struct_entry_t doesn't work for some reason + } + } + for (int64_t j = 0; j < schema->n_children; j++) { + ArrowConverter::fromArrowArray(schema->children[j], array->children[j], + *StructVector::getFieldVector(&outputVector, j).get(), mask->getChild(j), srcOffset, + dstOffset, count); + } +} + +static void scanArrowArrayDenseUnion(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto types = ((const int8_t*)array->buffers[0]) + srcOffset; + auto offsets = ((const int32_t*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curType = types[i]; + auto curOffset = offsets[i]; + UnionVector::setTagField(&outputVector, curType); + ArrowConverter::fromArrowArray(schema->children[curType], array->children[curType], + *StructVector::getFieldVector(&outputVector, curType).get(), + mask->getChild(curType), curOffset + srcOffset, i + dstOffset, 1); + // may be inefficient, since we're only scanning a single value + // should probably ask if we support dense unions (ie. is it okay to pack them) + } + } +} + +static void scanArrowArraySparseUnion(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + auto types = ((const int8_t*)array->buffers[0]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto curType = types[i]; + UnionVector::setTagField(&outputVector, curType); + } + } + // it is specified that values that aren't selected in the type buffer + // must also be semantically correct. this is why this scanning works. + // however, there is possibly room for optimization here. + // eg. nulling out unselected children + for (int8_t i = 0; i < array->n_children; i++) { + ArrowConverter::fromArrowArray(schema->children[i], array->children[i], + *StructVector::getFieldVector(&outputVector, i), mask->getChild(i), srcOffset, + dstOffset, count); + } +} + +template +static void scanArrowArrayDictionaryEncoded(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + + auto values = ((const offsetsT*)array->buffers[1]) + srcOffset; + mask->copyToValueVector(&outputVector, dstOffset, count); + for (uint64_t i = 0; i < count; i++) { + if (!mask->isNull(i)) { + auto dictOffseted = (*mask->getDictionary()) + values[i]; + ArrowConverter::fromArrowArray(schema->dictionary, array->dictionary, outputVector, + &dictOffseted, values[i] + array->dictionary->offset, i + dstOffset, + 1); // possibly inefficient? + } + } +} + +static void scanArrowArrayRunEndEncoded(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + + const ArrowArray* runEndArray = array->children[0]; + auto runEndBuffer = (const uint32_t*)runEndArray->buffers[1]; + + // binary search run end corresponding to srcOffset + auto runEndIdx = runEndArray->offset; + { + auto L = runEndArray->offset, H = L + runEndArray->length; + while (H >= L) { + auto M = (H + L) >> 1; + if (runEndBuffer[M] < srcOffset) { + runEndIdx = M; + H = M - 1; + } else { + L = M + 1; + } + } + } + + for (uint64_t i = 0; i < count; i++) { + while (i + srcOffset >= runEndBuffer[runEndIdx + 1]) { + runEndIdx++; + } + auto valuesOffseted = (*mask->getChild(1)) + runEndIdx; + ArrowConverter::fromArrowArray(schema->children[1], array->children[1], outputVector, + &valuesOffseted, runEndIdx, i + dstOffset, + 1); // there is optimization to be made here... + } +} + +void ArrowConverter::fromArrowArray(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count) { + const auto arrowType = schema->format; + if (array->dictionary != nullptr) { + switch (arrowType[0]) { + case 'c': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 'C': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 's': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 'S': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 'i': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 'I': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 'l': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + case 'L': + return scanArrowArrayDictionaryEncoded(schema, array, outputVector, mask, + srcOffset, dstOffset, count); + default: + throw RuntimeException("Invalid Index Type: " + std::string(arrowType)); + } + } + switch (arrowType[0]) { + case 'n': + // NULL + outputVector.setAllNull(); + return; + case 'b': + // BOOL + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'c': + // INT8 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'C': + // UINT8 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 's': + // INT16 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'S': + // UINT16 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'i': + // INT32 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'I': + // UINT32 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'l': + // INT64 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'L': + // UINT64 + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'f': + // FLOAT + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'g': + // DOUBLE + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'z': + // BLOB + return scanArrowArrayBLOB(array, outputVector, mask, srcOffset, dstOffset, count); + case 'Z': + // LONG BLOB + return scanArrowArrayBLOB(array, outputVector, mask, srcOffset, dstOffset, count); + case 'u': + // STRING + return scanArrowArrayBLOB(array, outputVector, mask, srcOffset, dstOffset, count); + case 'U': + // LONG STRING + return scanArrowArrayBLOB(array, outputVector, mask, srcOffset, dstOffset, count); + case 'v': + switch (arrowType[1]) { + case 'z': + // BINARY VIEW + case 'u': + // STRING VIEW + return scanArrowArrayBLOBView(array, outputVector, mask, srcOffset, dstOffset, count); + default: + KU_UNREACHABLE; + } + case 'w': + // FIXED BLOB + return scanArrowArrayFixedBLOB(array, outputVector, mask, std::stoi(arrowType + 2), + srcOffset, dstOffset, count); + case 't': + switch (arrowType[1]) { + case 'd': + // DATE + if (arrowType[2] == 'D') { + // days since unix epoch + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, + srcOffset, dstOffset, count); + } else { + // ms since unix epoch + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, + srcOffset, dstOffset, count); + } + case 't': + // TODO pure time type + KU_UNREACHABLE; + case 's': + // TIMESTAMP + return scanArrowArrayFixedSizePrimitive(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'D': + // DURATION (KUZU INTERVAL) + switch (arrowType[2]) { + case 's': + // consider implement overflow checking here? + return scanArrowArrayDurationScaledUp(array, outputVector, mask, 1000000, srcOffset, + dstOffset, count); + case 'm': + return scanArrowArrayDurationScaledUp(array, outputVector, mask, 1000, srcOffset, + dstOffset, count); + case 'u': + return scanArrowArrayDurationScaledUp(array, outputVector, mask, 1, srcOffset, + dstOffset, count); + case 'n': + return scanArrowArrayDurationScaledDown(array, outputVector, mask, 1000, srcOffset, + dstOffset, count); + default: + KU_UNREACHABLE; + } + case 'i': + // INTERVAL + switch (arrowType[2]) { + case 'M': + return scanArrowArrayMonthInterval(array, outputVector, mask, srcOffset, dstOffset, + count); + case 'D': + return scanArrowArrayDayTimeInterval(array, outputVector, mask, srcOffset, + dstOffset, count); + case 'n': + return scanArrowArrayMonthDayNanoInterval(array, outputVector, mask, srcOffset, + dstOffset, count); + default: + KU_UNREACHABLE; + } + default: + KU_UNREACHABLE; + } + case '+': + switch (arrowType[1]) { + case 'r': + // RUN END ENCODED + return scanArrowArrayRunEndEncoded(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + case 'l': + // LIST + return scanArrowArrayList(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + case 'L': + // LONG LIST + return scanArrowArrayList(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + case 'w': + // FIXED_LIST + // TODO Manh: Array Scanning + KU_UNREACHABLE; + // return scanArrowArrayFixedList( + // schema, array, outputVector, mask, srcOffset, dstOffset, count); + case 's': + // STRUCT + return scanArrowArrayStruct(schema, array, outputVector, mask, srcOffset, dstOffset, + count); + case 'm': + // MAP + return scanArrowArrayList(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + case 'u': + if (arrowType[2] == 'd') { + // DENSE UNION + return scanArrowArrayDenseUnion(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + } else { + // SPARSE UNION + return scanArrowArraySparseUnion(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + } + case 'v': + switch (arrowType[2]) { + case 'l': + return scanArrowArrayListView(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + case 'L': + return scanArrowArrayListView(schema, array, outputVector, mask, srcOffset, + dstOffset, count); + // LONG LIST VIEW + default: + KU_UNREACHABLE; + } + default: + KU_UNREACHABLE; + } + default: + KU_UNREACHABLE; + } +} + +void ArrowConverter::fromArrowArray(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector) { + ArrowNullMaskTree mask(schema, array, array->offset, array->length); + return fromArrowArray(schema, array, outputVector, &mask, array->offset, 0, array->length); +} + +} // namespace common +} // namespace kuzu diff --git a/src/common/arrow/arrow_converter.cpp b/src/common/arrow/arrow_converter.cpp index 7cb05e19309..e6c4f9c4893 100644 --- a/src/common/arrow/arrow_converter.cpp +++ b/src/common/arrow/arrow_converter.cpp @@ -41,8 +41,8 @@ void ArrowConverter::initializeChild(ArrowSchema& child, const std::string& name child.dictionary = nullptr; } -void ArrowConverter::setArrowFormatForStruct( - ArrowSchemaHolder& rootHolder, ArrowSchema& child, const main::DataTypeInfo& typeInfo) { +void ArrowConverter::setArrowFormatForStruct(ArrowSchemaHolder& rootHolder, ArrowSchema& child, + const main::DataTypeInfo& typeInfo) { auto& childrenTypesInfo = typeInfo.childrenTypesInfo; child.format = "+s"; // name is set by parent. @@ -62,8 +62,8 @@ void ArrowConverter::setArrowFormatForStruct( } } -void ArrowConverter::setArrowFormat( - ArrowSchemaHolder& rootHolder, ArrowSchema& child, const main::DataTypeInfo& typeInfo) { +void ArrowConverter::setArrowFormat(ArrowSchemaHolder& rootHolder, ArrowSchema& child, + const main::DataTypeInfo& typeInfo) { switch (typeInfo.typeID) { case LogicalTypeID::BOOL: { child.format = "b"; @@ -127,7 +127,7 @@ void ArrowConverter::setArrowFormat( case LogicalTypeID::STRING: { child.format = "u"; } break; - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::LIST: { child.format = "+l"; child.n_children = 1; rootHolder.nestedChildren.emplace_back(); @@ -139,9 +139,9 @@ void ArrowConverter::setArrowFormat( child.children[0]->name = "l"; setArrowFormat(rootHolder, **child.children, *typeInfo.childrenTypesInfo[0]); } break; - case LogicalTypeID::FIXED_LIST: { - auto numValuesPerList = "+w:" + std::to_string(typeInfo.numValuesPerList); - child.format = copyName(rootHolder, numValuesPerList); + case LogicalTypeID::ARRAY: { + auto numValuesPerArray = "+w:" + std::to_string(typeInfo.fixedNumValues); + child.format = copyName(rootHolder, numValuesPerArray); child.n_children = 1; rootHolder.nestedChildren.emplace_back(); rootHolder.nestedChildren.back().resize(1); @@ -195,8 +195,8 @@ std::unique_ptr ArrowConverter::toArrowSchema( return outSchema; } -void ArrowConverter::toArrowArray( - main::QueryResult& queryResult, ArrowArray* outArray, std::int64_t chunkSize) { +void ArrowConverter::toArrowArray(main::QueryResult& queryResult, ArrowArray* outArray, + std::int64_t chunkSize) { auto typesInfo = queryResult.getColumnTypesInfo(); auto rowBatch = make_unique(std::move(typesInfo), chunkSize); *outArray = rowBatch->append(queryResult, chunkSize); diff --git a/src/common/arrow/arrow_null_mask_tree.cpp b/src/common/arrow/arrow_null_mask_tree.cpp new file mode 100644 index 00000000000..e9d7405aa6d --- /dev/null +++ b/src/common/arrow/arrow_null_mask_tree.cpp @@ -0,0 +1,218 @@ +#include + +#include "common/arrow/arrow.h" +#include "common/arrow/arrow_nullmask_tree.h" + +namespace kuzu { +namespace common { + +// scans are based on data specification found here +// https://arrow.apache.org/docs/format/Columnar.html + +// all offsets are measured by value, not physical size + +void ArrowNullMaskTree::copyToValueVector(ValueVector* vec, uint64_t dstOffset, uint64_t count) { + vec->setNullFromBits(mask->getData(), offset, dstOffset, count); +} + +ArrowNullMaskTree ArrowNullMaskTree::operator+(int64_t offset) { + // this operation is mostly a special case for dictionary/run-end encoding + ArrowNullMaskTree ret(*this); + ret.offset += offset; + return ret; +} + +bool ArrowNullMaskTree::copyFromBuffer(const void* buffer, uint64_t srcOffset, uint64_t count) { + if (buffer == nullptr) { + mask->setAllNonNull(); + return false; + } + mask->copyFromNullBits((const uint64_t*)buffer, srcOffset, 0, count, true); + return true; +} + +bool ArrowNullMaskTree::applyParentBitmap(const NullMask* parent, uint64_t count) { + if (parent == nullptr) { + return false; + } + const uint64_t* buffer = parent->data; + if (buffer != nullptr) { + for (uint64_t i = 0; i < (count >> NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2); i++) { + mask->buffer[i] |= buffer[i]; + } + return true; + } + return false; +} + +template +void ArrowNullMaskTree::scanListPushDown(const ArrowSchema* schema, const ArrowArray* array, + uint64_t srcOffset, uint64_t count) { + const offsetsT* offsets = ((const offsetsT*)array->buffers[1]) + srcOffset; + offsetsT auxiliaryLength = offsets[count] - offsets[0]; + NullMask pushDownMask((auxiliaryLength + NullMask::NUM_BITS_PER_NULL_ENTRY - 1) >> + NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2); + for (uint64_t i = 0; i < count; i++) { + pushDownMask.setNullFromRange(offsets[i] - offsets[0], offsets[i + 1] - offsets[i], + isNull(i)); + } + children->push_back(ArrowNullMaskTree(schema->children[0], array->children[0], offsets[0], + auxiliaryLength, &pushDownMask)); +} + +void ArrowNullMaskTree::scanStructPushDown(const ArrowSchema* schema, const ArrowArray* array, + uint64_t srcOffset, uint64_t count) { + for (int64_t i = 0; i < array->n_children; i++) { + children->push_back(ArrowNullMaskTree(schema->children[i], array->children[i], srcOffset, + count, mask.get())); + } +} + +ArrowNullMaskTree::ArrowNullMaskTree(const ArrowSchema* schema, const ArrowArray* array, + uint64_t srcOffset, uint64_t count, const NullMask* parentBitmap) + : offset{0}, + mask{std::make_shared((count + NullMask::NUM_BITS_PER_NULL_ENTRY - 1) >> + NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2)}, + children(std::make_shared>()) { + if (schema->dictionary != nullptr) { + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + dictionary = std::make_shared(schema->dictionary, array->dictionary, + array->dictionary->offset, array->dictionary->length); + return; + } + const char* arrowType = schema->format; + std::vector structFields; + switch (arrowType[0]) { + case 'n': + mask->setAllNull(); + break; + case 'b': + case 'c': + case 'C': + case 's': + case 'S': + case 'i': + case 'I': + case 'l': + case 'L': + case 'f': + case 'g': + copyFromBuffer(array->buffers[0], srcOffset, count); + break; + case 'z': + case 'Z': + case 'u': + case 'U': + case 'v': + case 'w': + case 't': + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + break; + case '+': + switch (arrowType[1]) { + case 'l': + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + scanListPushDown(schema, array, srcOffset, count); + break; + case 'L': + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + scanListPushDown(schema, array, srcOffset, count); + break; + case 'w': + // TODO manh: array null resolution + KU_UNREACHABLE; + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + break; + case 's': + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + scanStructPushDown(schema, array, srcOffset, count); + break; + case 'm': + copyFromBuffer(array->buffers[0], srcOffset, count); + applyParentBitmap(parentBitmap, count); + scanListPushDown(schema, array, srcOffset, count); + break; + case 'u': { + const int8_t* types = (const int8_t*)array->buffers[0]; + if (schema->format[2] == 'd') { + const int32_t* offsets = (const int32_t*)array->buffers[1]; + std::vector countChildren(array->n_children), + lowestOffsets(array->n_children); + std::vector highestOffsets(array->n_children); + for (auto i = srcOffset; i < srcOffset + count; i++) { + int32_t curOffset = offsets[i]; + int32_t curType = types[i]; + if (countChildren[curType] == 0) { + lowestOffsets[curType] = curOffset; + } + highestOffsets[curType] = curOffset; + countChildren[curType]++; + } + for (int64_t i = 0; i < array->n_children; i++) { + children->push_back(ArrowNullMaskTree(schema->children[i], array->children[i], + lowestOffsets[i], highestOffsets[i] - lowestOffsets[i])); + } + for (auto i = 0u; i < count; i++) { + int32_t curOffset = offsets[i + srcOffset]; + int8_t curType = types[i + srcOffset]; + mask->setNull(i, children->operator[](curType).isNull(curOffset)); + } + } else { + for (int64_t i = 0; i < array->n_children; i++) { + children->push_back(ArrowNullMaskTree(schema->children[i], array->children[i], + srcOffset, count)); + } + for (auto i = 0u; i < count; i++) { + int8_t curType = types[i + srcOffset]; + mask->setNull(i, children->operator[](curType).isNull(i)); + // this isn't specified in the arrow specification, but is it valid to + // compute this using a bitwise OR? + } + } + if (parentBitmap != nullptr) { + for (uint64_t i = 0; i < count >> NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2; i++) { + mask->buffer[i] |= parentBitmap->buffer[i]; + } + } + } break; + case 'v': + // list views *suck*, especially when trying to write code that can support + // parallelization for this, we generate child NullMaskTrees on the fly, rather than + // attempt any precomputation + if (array->buffers[0] == nullptr) { + mask->setAllNonNull(); + } else { + mask->copyFromNullBits((const uint64_t*)array->buffers[0], srcOffset, 0, count, + true); + } + if (parentBitmap != nullptr) { + for (uint64_t i = 0; i < count >> NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2; i++) { + mask->buffer[i] |= parentBitmap->buffer[i]; + } + } + break; + case 'r': + // it's better to resolve validity during the actual scanning for run-end encoded arrays + // so for this, let's just resolve child validities and move on + for (int64_t i = 0; i < array->n_children; i++) { + children->push_back(ArrowNullMaskTree(schema->children[i], array->children[i], + array->children[i]->offset, array->children[i]->length)); + } + break; + default: + KU_UNREACHABLE; + } + break; + default: + KU_UNREACHABLE; + } +} + +} // namespace common +} // namespace kuzu diff --git a/src/common/arrow/arrow_row_batch.cpp b/src/common/arrow/arrow_row_batch.cpp index 435f9b26462..964966930fc 100644 --- a/src/common/arrow/arrow_row_batch.cpp +++ b/src/common/arrow/arrow_row_batch.cpp @@ -12,8 +12,8 @@ namespace kuzu { namespace common { -ArrowRowBatch::ArrowRowBatch( - std::vector> typesInfo, std::int64_t capacity) +ArrowRowBatch::ArrowRowBatch(std::vector> typesInfo, + std::int64_t capacity) : typesInfo{std::move(typesInfo)}, numTuples{0} { auto numVectors = this->typesInfo.size(); vectors.resize(numVectors); @@ -24,22 +24,22 @@ ArrowRowBatch::ArrowRowBatch( // TODO(Ziyi): use physical type instead of logical type here. template -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, std::int64_t capacity) { initializeNullBits(vector->validity, capacity); vector->data.reserve(storage::StorageUtils::getDataTypeSize(LogicalType{DT}) * capacity); } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, std::int64_t capacity) { initializeNullBits(vector->validity, capacity); vector->data.reserve(getNumBytesForBits(capacity)); } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, std::int64_t capacity) { initializeNullBits(vector->validity, capacity); // Initialize offsets and string values buffer. vector->data.reserve((capacity + 1) * sizeof(std::uint32_t)); @@ -48,8 +48,8 @@ void ArrowRowBatch::templateInitializeVector( } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, std::int64_t capacity) { initializeNullBits(vector->validity, capacity); KU_ASSERT(typeInfo.childrenTypesInfo.size() == 1); auto childTypeInfo = typeInfo.childrenTypesInfo[0].get(); @@ -61,8 +61,8 @@ void ArrowRowBatch::templateInitializeVector( } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, std::int64_t capacity) { initializeNullBits(vector->validity, capacity); KU_ASSERT(typeInfo.childrenTypesInfo.size() == 1); auto childTypeInfo = typeInfo.childrenTypesInfo[0].get(); @@ -71,13 +71,13 @@ void ArrowRowBatch::templateInitializeVector( } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, std::int64_t capacity) { initializeStructVector(vector, typeInfo, capacity); } -void ArrowRowBatch::initializeStructVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::initializeStructVector(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + std::int64_t capacity) { initializeNullBits(vector->validity, capacity); for (auto& childTypeInfo : typeInfo.childrenTypesInfo) { auto childVector = createVector(*childTypeInfo, capacity); @@ -86,25 +86,25 @@ void ArrowRowBatch::initializeStructVector( } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, std::int64_t capacity) { initializeStructVector(vector, typeInfo, capacity); } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, std::int64_t capacity) { initializeStructVector(vector, typeInfo, capacity); } template<> -void ArrowRowBatch::templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +void ArrowRowBatch::templateInitializeVector(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, std::int64_t capacity) { initializeStructVector(vector, typeInfo, capacity); } -std::unique_ptr ArrowRowBatch::createVector( - const main::DataTypeInfo& typeInfo, std::int64_t capacity) { +std::unique_ptr ArrowRowBatch::createVector(const main::DataTypeInfo& typeInfo, + std::int64_t capacity) { auto result = std::make_unique(); switch (typeInfo.typeID) { case LogicalTypeID::BOOL: { @@ -168,11 +168,11 @@ std::unique_ptr ArrowRowBatch::createVector( case LogicalTypeID::STRING: { templateInitializeVector(result.get(), typeInfo, capacity); } break; - case LogicalTypeID::VAR_LIST: { - templateInitializeVector(result.get(), typeInfo, capacity); + case LogicalTypeID::LIST: { + templateInitializeVector(result.get(), typeInfo, capacity); } break; - case LogicalTypeID::FIXED_LIST: { - templateInitializeVector(result.get(), typeInfo, capacity); + case LogicalTypeID::ARRAY: { + templateInitializeVector(result.get(), typeInfo, capacity); } break; case LogicalTypeID::STRUCT: { templateInitializeVector(result.get(), typeInfo, capacity); @@ -214,8 +214,8 @@ static void setBitToOne(std::uint8_t* data, std::int64_t pos) { data[bytePos] |= ((std::uint64_t)1 << bitOffset); } -void ArrowRowBatch::appendValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value) { +void ArrowRowBatch::appendValue(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + Value* value) { if (value->isNull()) { copyNullValue(vector, value, vector->numValues); } else { @@ -225,15 +225,15 @@ void ArrowRowBatch::appendValue( } template -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { auto valSize = storage::StorageUtils::getDataTypeSize(LogicalType{DT}); std::memcpy(vector->data.data() + pos * valSize, &value->val, valSize); } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { if (value->val.booleanVal) { setBitToOne(vector->data.data(), pos); } else { @@ -242,8 +242,8 @@ void ArrowRowBatch::templateCopyNonNullValue( } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { auto offsets = (std::uint32_t*)vector->data.data(); auto strLength = value->strVal.length(); offsets[pos + 1] = offsets[pos] + strLength; @@ -252,8 +252,8 @@ void ArrowRowBatch::templateCopyNonNullValue( } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& /*typeInfo*/, Value* value, std::int64_t pos) { auto offsets = (std::uint32_t*)vector->data.data(); auto str = UUID::toString(value->val.int128Val); auto strLength = str.length(); @@ -263,8 +263,8 @@ void ArrowRowBatch::templateCopyNonNullValue( } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos) { vector->data.resize((pos + 2) * sizeof(std::uint32_t)); auto offsets = (std::uint32_t*)vector->data.data(); auto numElements = value->childrenSize; @@ -277,50 +277,62 @@ void ArrowRowBatch::templateCopyNonNullValue( for (auto i = currentNumBytesForChildValidity; i < numBytesForChildValidity; i++) { vector->childData[0]->validity.data()[i] = 0xFF; // Init each value to be valid (as 1). } - if (typeInfo.childrenTypesInfo[0]->typeID != LogicalTypeID::VAR_LIST) { + // If vector->childData[0] is a LIST, its data buffer will be resized when we add a new + // value into it + // If vector->childData[0] is an ARRAY, its data buffer is supposed to be empty, + // so we don't resize it here + if (typeInfo.childrenTypesInfo[0]->typeID != LogicalTypeID::LIST && + typeInfo.childrenTypesInfo[0]->typeID != LogicalTypeID::ARRAY) { vector->childData[0]->data.resize( numChildElements * storage::StorageUtils::getDataTypeSize( LogicalType{typeInfo.childrenTypesInfo[0]->typeID})); } for (auto i = 0u; i < numElements; i++) { - appendValue( - vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], value->children[i].get()); + appendValue(vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], + value->children[i].get()); } } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos) { - auto numValuesPerList = value->childrenSize; - auto numValuesInChild = numValuesPerList * (pos + 1); +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos) { + auto numElements = value->childrenSize; + auto numChildElements = numElements * (pos + 1); auto currentNumBytesForChildValidity = vector->childData[0]->validity.size(); - auto numBytesForChildValidity = getNumBytesForBits(numValuesInChild); + auto numBytesForChildValidity = getNumBytesForBits(numChildElements); vector->childData[0]->validity.resize(numBytesForChildValidity); // Initialize validity mask which is used to mark each value is valid (non-null) or not (null). for (auto i = currentNumBytesForChildValidity; i < numBytesForChildValidity; i++) { vector->childData[0]->validity.data()[i] = 0xFF; // Init each value to be valid (as 1). } - vector->childData[0]->data.resize( - numValuesInChild * - storage::StorageUtils::getDataTypeSize(LogicalType{typeInfo.childrenTypesInfo[0]->typeID})); - for (auto i = 0u; i < numValuesPerList; i++) { - appendValue( - vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], value->children[i].get()); + // If vector->childData[0] is a LIST, its data buffer will be resized when we add a new + // value into it + // If vector->childData[0] is an ARRAY, its data buffer is supposed to be empty, + // so we don't resize it here + if (typeInfo.childrenTypesInfo[0]->typeID != LogicalTypeID::LIST && + typeInfo.childrenTypesInfo[0]->typeID != LogicalTypeID::ARRAY) { + vector->childData[0]->data.resize( + numChildElements * storage::StorageUtils::getDataTypeSize( + LogicalType{typeInfo.childrenTypesInfo[0]->typeID})); + } + for (auto i = 0u; i < numElements; i++) { + appendValue(vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], + value->children[i].get()); } } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { for (auto i = 0u; i < value->childrenSize; i++) { - appendValue( - vector->childData[i].get(), *typeInfo.childrenTypesInfo[i], value->children[i].get()); + appendValue(vector->childData[i].get(), *typeInfo.childrenTypesInfo[i], + value->children[i].get()); } } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { auto nodeID = value->getValue(); Value offsetVal((std::int64_t)nodeID.offset); Value tableIDVal((std::int64_t)nodeID.tableID); @@ -329,43 +341,43 @@ void ArrowRowBatch::templateCopyNonNullValue( } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { - appendValue( - vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], NodeVal::getNodeIDVal(value)); - appendValue( - vector->childData[1].get(), *typeInfo.childrenTypesInfo[1], NodeVal::getLabelVal(value)); +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { + appendValue(vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], + NodeVal::getNodeIDVal(value)); + appendValue(vector->childData[1].get(), *typeInfo.childrenTypesInfo[1], + NodeVal::getLabelVal(value)); std::int64_t propertyId = 2; auto numProperties = NodeVal::getNumProperties(value); for (auto i = 0u; i < numProperties; i++) { auto name = NodeVal::getPropertyName(value, i); auto val = NodeVal::getPropertyVal(value, i); - appendValue( - vector->childData[propertyId].get(), *typeInfo.childrenTypesInfo[propertyId], val); + appendValue(vector->childData[propertyId].get(), *typeInfo.childrenTypesInfo[propertyId], + val); propertyId++; } } template<> -void ArrowRowBatch::templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { - appendValue( - vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], RelVal::getSrcNodeIDVal(value)); - appendValue( - vector->childData[1].get(), *typeInfo.childrenTypesInfo[1], RelVal::getDstNodeIDVal(value)); +void ArrowRowBatch::templateCopyNonNullValue(ArrowVector* vector, + const main::DataTypeInfo& typeInfo, Value* value, std::int64_t /*pos*/) { + appendValue(vector->childData[0].get(), *typeInfo.childrenTypesInfo[0], + RelVal::getSrcNodeIDVal(value)); + appendValue(vector->childData[1].get(), *typeInfo.childrenTypesInfo[1], + RelVal::getDstNodeIDVal(value)); std::int64_t propertyId = 2; auto numProperties = NodeVal::getNumProperties(value); for (auto i = 0u; i < numProperties; i++) { auto name = NodeVal::getPropertyName(value, i); auto val = NodeVal::getPropertyVal(value, i); - appendValue( - vector->childData[propertyId].get(), *typeInfo.childrenTypesInfo[propertyId], val); + appendValue(vector->childData[propertyId].get(), *typeInfo.childrenTypesInfo[propertyId], + val); propertyId++; } } -void ArrowRowBatch::copyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos) { +void ArrowRowBatch::copyNonNullValue(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + Value* value, std::int64_t pos) { switch (typeInfo.typeID) { case LogicalTypeID::BOOL: { templateCopyNonNullValue(vector, typeInfo, value, pos); @@ -430,11 +442,11 @@ void ArrowRowBatch::copyNonNullValue( case LogicalTypeID::STRING: { templateCopyNonNullValue(vector, typeInfo, value, pos); } break; - case LogicalTypeID::VAR_LIST: { - templateCopyNonNullValue(vector, typeInfo, value, pos); + case LogicalTypeID::LIST: { + templateCopyNonNullValue(vector, typeInfo, value, pos); } break; - case LogicalTypeID::FIXED_LIST: { - templateCopyNonNullValue(vector, typeInfo, value, pos); + case LogicalTypeID::ARRAY: { + templateCopyNonNullValue(vector, typeInfo, value, pos); } break; case LogicalTypeID::STRUCT: { templateCopyNonNullValue(vector, typeInfo, value, pos); @@ -462,8 +474,8 @@ void ArrowRowBatch::templateCopyNullValue(ArrowVector* vector, std::int64_t pos) } template<> -void ArrowRowBatch::templateCopyNullValue( - ArrowVector* vector, std::int64_t pos) { +void ArrowRowBatch::templateCopyNullValue(ArrowVector* vector, + std::int64_t pos) { auto offsets = (std::uint32_t*)vector->data.data(); offsets[pos + 1] = offsets[pos]; setBitToZero(vector->validity.data(), pos); @@ -471,8 +483,8 @@ void ArrowRowBatch::templateCopyNullValue( } template<> -void ArrowRowBatch::templateCopyNullValue( - ArrowVector* vector, std::int64_t pos) { +void ArrowRowBatch::templateCopyNullValue(ArrowVector* vector, + std::int64_t pos) { auto offsets = (std::uint32_t*)vector->data.data(); offsets[pos + 1] = offsets[pos]; setBitToZero(vector->validity.data(), pos); @@ -480,15 +492,15 @@ void ArrowRowBatch::templateCopyNullValue( } template<> -void ArrowRowBatch::templateCopyNullValue( - ArrowVector* vector, std::int64_t pos) { +void ArrowRowBatch::templateCopyNullValue(ArrowVector* vector, + std::int64_t pos) { setBitToZero(vector->validity.data(), pos); vector->numNulls++; } template<> -void ArrowRowBatch::templateCopyNullValue( - ArrowVector* vector, std::int64_t pos) { +void ArrowRowBatch::templateCopyNullValue(ArrowVector* vector, + std::int64_t pos) { setBitToZero(vector->validity.data(), pos); vector->numNulls++; } @@ -556,8 +568,11 @@ void ArrowRowBatch::copyNullValue(ArrowVector* vector, Value* value, std::int64_ case LogicalTypeID::STRING: { templateCopyNullValue(vector, pos); } break; - case LogicalTypeID::VAR_LIST: { - templateCopyNullValue(vector, pos); + case LogicalTypeID::LIST: { + templateCopyNullValue(vector, pos); + } break; + case LogicalTypeID::ARRAY: { + templateCopyNullValue(vector, pos); } break; case LogicalTypeID::INTERNAL_ID: { templateCopyNullValue(vector, pos); @@ -606,16 +621,16 @@ static std::unique_ptr createArrayFromVector(ArrowVector& vector) { } template -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& /*typeInfo*/) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& /*typeInfo*/) { auto result = createArrayFromVector(vector); vector.array = std::move(result); return vector.array.get(); } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& /*typeInfo*/) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& /*typeInfo*/) { auto result = createArrayFromVector(vector); result->n_buffers = 3; result->buffers[2] = vector.overflow.data(); @@ -624,8 +639,8 @@ ArrowArray* ArrowRowBatch::templateCreateArray( } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { auto result = createArrayFromVector(vector); vector.childPointers.resize(1); result->children = vector.childPointers.data(); @@ -637,8 +652,8 @@ ArrowArray* ArrowRowBatch::templateCreateArray( } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { auto result = createArrayFromVector(vector); vector.childPointers.resize(1); result->n_buffers = 1; @@ -651,13 +666,13 @@ ArrowArray* ArrowRowBatch::templateCreateArray( } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { return convertStructVectorToArray(vector, typeInfo); } -ArrowArray* ArrowRowBatch::convertStructVectorToArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::convertStructVectorToArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { auto result = createArrayFromVector(vector); result->n_buffers = 1; vector.childPointers.resize(typeInfo.childrenTypesInfo.size()); @@ -672,25 +687,25 @@ ArrowArray* ArrowRowBatch::convertStructVectorToArray( } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { return convertStructVectorToArray(vector, typeInfo); } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { return convertStructVectorToArray(vector, typeInfo); } template<> -ArrowArray* ArrowRowBatch::templateCreateArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::templateCreateArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { return convertStructVectorToArray(vector, typeInfo); } -ArrowArray* ArrowRowBatch::convertVectorToArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo) { +ArrowArray* ArrowRowBatch::convertVectorToArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo) { switch (typeInfo.typeID) { case LogicalTypeID::BOOL: { return templateCreateArray(vector, typeInfo); @@ -753,11 +768,11 @@ ArrowArray* ArrowRowBatch::convertVectorToArray( case LogicalTypeID::STRING: { return templateCreateArray(vector, typeInfo); } - case LogicalTypeID::VAR_LIST: { - return templateCreateArray(vector, typeInfo); + case LogicalTypeID::LIST: { + return templateCreateArray(vector, typeInfo); } - case LogicalTypeID::FIXED_LIST: { - return templateCreateArray(vector, typeInfo); + case LogicalTypeID::ARRAY: { + return templateCreateArray(vector, typeInfo); } case LogicalTypeID::STRUCT: { return templateCreateArray(vector, typeInfo); diff --git a/src/common/arrow/arrow_type.cpp b/src/common/arrow/arrow_type.cpp new file mode 100644 index 00000000000..a1e4a692609 --- /dev/null +++ b/src/common/arrow/arrow_type.cpp @@ -0,0 +1,150 @@ +#include "common/arrow/arrow_converter.h" +#include "common/exception/not_implemented.h" +#include "common/exception/runtime.h" + +namespace kuzu { +namespace common { + +// pyarrow format string specifications can be found here +// https://arrow.apache.org/docs/format/CDataInterface.html#data-type-description-format-strings + +LogicalType ArrowConverter::fromArrowSchema(const ArrowSchema* schema) { + const char* arrowType = schema->format; + std::vector structFields; + // if we have a dictionary, then the logical type of the column is dependent upon the + // logical type of the dict + if (schema->dictionary != nullptr) { + return fromArrowSchema(schema->dictionary); + } + switch (arrowType[0]) { + case 'n': + return LogicalType(LogicalTypeID::ANY); + case 'b': + return LogicalType(LogicalTypeID::BOOL); + case 'c': + return LogicalType(LogicalTypeID::INT8); + case 'C': + return LogicalType(LogicalTypeID::UINT8); + case 's': + return LogicalType(LogicalTypeID::INT16); + case 'S': + return LogicalType(LogicalTypeID::UINT16); + case 'i': + return LogicalType(LogicalTypeID::INT32); + case 'I': + return LogicalType(LogicalTypeID::UINT32); + case 'l': + return LogicalType(LogicalTypeID::INT64); + case 'L': + return LogicalType(LogicalTypeID::UINT64); + case 'f': + return LogicalType(LogicalTypeID::FLOAT); + case 'g': + return LogicalType(LogicalTypeID::DOUBLE); + case 'z': + case 'Z': + return LogicalType(LogicalTypeID::BLOB); + case 'u': + case 'U': + return LogicalType(LogicalTypeID::STRING); + case 'v': + switch (arrowType[1]) { + case 'z': + return LogicalType(LogicalTypeID::BLOB); + case 'u': + return LogicalType(LogicalTypeID::STRING); + default: + KU_UNREACHABLE; + } + + case 'd': + throw NotImplementedException("Decimals are not supported"); + case 'w': + return LogicalType(LogicalTypeID::BLOB); // fixed width binary + case 't': + switch (arrowType[1]) { + case 'd': + if (arrowType[2] == 'D') { + return LogicalType(LogicalTypeID::DATE); + } else { + return LogicalType(LogicalTypeID::TIMESTAMP_MS); + } + case 't': + // TODO implement pure time type + throw NotImplementedException("Pure time types are not supported"); + case 's': + // TODO maxwell: timezone support + switch (arrowType[2]) { + case 's': + return LogicalType(LogicalTypeID::TIMESTAMP_SEC); + case 'm': + return LogicalType(LogicalTypeID::TIMESTAMP_MS); + case 'u': + return LogicalType(LogicalTypeID::TIMESTAMP); + case 'n': + return LogicalType(LogicalTypeID::TIMESTAMP_NS); + default: + KU_UNREACHABLE; + } + case 'D': + // duration + case 'i': + // interval + return LogicalType(LogicalTypeID::INTERVAL); + default: + KU_UNREACHABLE; + } + case '+': + KU_ASSERT(schema->n_children > 0); + switch (arrowType[1]) { + // complex types need a complementary ExtraTypeInfo object + case 'l': + case 'L': + return *LogicalType::LIST( + std::make_unique(fromArrowSchema(schema->children[0]))); + case 'w': + throw RuntimeException("Fixed list is currently WIP."); + // TODO Manh: Array Binding + // return *LogicalType::FIXED_LIST( + // std::make_unique(fromArrowSchema(schema->children[0])), + // std::stoi(arrowType+3)); + case 's': + for (int64_t i = 0; i < schema->n_children; i++) { + structFields.emplace_back(std::string(schema->children[i]->name), + std::make_unique(fromArrowSchema(schema->children[i]))); + } + return *LogicalType::STRUCT(std::move(structFields)); + case 'm': + return *LogicalType::MAP( + std::make_unique(fromArrowSchema(schema->children[0]->children[0])), + std::make_unique(fromArrowSchema(schema->children[0]->children[1]))); + case 'u': + throw RuntimeException("Unions are currently WIP."); + for (int64_t i = 0; i < schema->n_children; i++) { + structFields.emplace_back(std::string(schema->children[i]->name), + std::make_unique(fromArrowSchema(schema->children[i]))); + } + return *LogicalType::UNION(std::move(structFields)); + case 'v': + switch (arrowType[2]) { + case 'l': + case 'L': + return *LogicalType::LIST( + std::make_unique(fromArrowSchema(schema->children[0]))); + default: + KU_UNREACHABLE; + } + case 'r': + // logical type corresponds to second child + return fromArrowSchema(schema->children[1]); + default: + KU_UNREACHABLE; + } + default: + KU_UNREACHABLE; + } + // refer to arrow_converted.cpp:65 +} + +} // namespace common +} // namespace kuzu diff --git a/src/common/case_insensitive_map.cpp b/src/common/case_insensitive_map.cpp new file mode 100644 index 00000000000..33114da913e --- /dev/null +++ b/src/common/case_insensitive_map.cpp @@ -0,0 +1,18 @@ +#include "common/case_insensitive_map.h" + +#include "common/string_utils.h" + +namespace kuzu { +namespace common { + +uint64_t CaseInsensitiveStringHashFunction::operator()(const std::string& str) const { + return common::StringUtils::caseInsensitiveHash(str); +} + +bool CaseInsensitiveStringEquality::operator()(const std::string& lhs, + const std::string& rhs) const { + return common::StringUtils::caseInsensitiveEquals(lhs, rhs); +} + +} // namespace common +} // namespace kuzu diff --git a/src/common/copier_config/csv_reader_config.cpp b/src/common/copier_config/csv_reader_config.cpp index 4fffee643c7..cdfcbeb2d36 100644 --- a/src/common/copier_config/csv_reader_config.cpp +++ b/src/common/copier_config/csv_reader_config.cpp @@ -16,8 +16,8 @@ static char bindParsingOptionValue(std::string value) { return value[value.length() - 1]; } -static void bindBoolParsingOption( - CSVReaderConfig& config, const std::string& optionName, bool optionValue) { +static void bindBoolParsingOption(CSVReaderConfig& config, const std::string& optionName, + bool optionValue) { if (optionName == "HEADER") { config.option.hasHeader = optionValue; } else if (optionName == "PARALLEL") { @@ -25,8 +25,8 @@ static void bindBoolParsingOption( } } -static void bindStringParsingOption( - CSVReaderConfig& config, const std::string& optionName, const std::string& optionValue) { +static void bindStringParsingOption(CSVReaderConfig& config, const std::string& optionName, + const std::string& optionValue) { auto parsingOptionValue = bindParsingOptionValue(optionValue); if (optionName == "ESCAPE") { config.option.escapeChar = parsingOptionValue; diff --git a/src/common/data_chunk/data_chunk_collection.cpp b/src/common/data_chunk/data_chunk_collection.cpp index c0a142d8dd8..e3412313e1f 100644 --- a/src/common/data_chunk/data_chunk_collection.cpp +++ b/src/common/data_chunk/data_chunk_collection.cpp @@ -7,68 +7,59 @@ DataChunkCollection::DataChunkCollection(storage::MemoryManager* mm) : mm{mm} {} void DataChunkCollection::append(DataChunk& chunk) { auto numTuplesToAppend = chunk.state->selVector->selectedSize; - auto chunkToAppendInfo = chunks.empty() ? allocateChunk(chunk) : chunks.back().get(); auto numTuplesAppended = 0u; while (numTuplesAppended < numTuplesToAppend) { - if (chunkToAppendInfo->state->selVector->selectedSize == DEFAULT_VECTOR_CAPACITY) { - chunkToAppendInfo = allocateChunk(chunk); + if (chunks.empty() || + chunks.back().state->selVector->selectedSize == DEFAULT_VECTOR_CAPACITY) { + allocateChunk(chunk); } + auto& chunkToAppend = chunks.back(); auto numTuplesToCopy = std::min(numTuplesToAppend - numTuplesAppended, - DEFAULT_VECTOR_CAPACITY - chunkToAppendInfo->state->selVector->selectedSize); + DEFAULT_VECTOR_CAPACITY - chunkToAppend.state->selVector->selectedSize); for (auto vectorIdx = 0u; vectorIdx < chunk.getNumValueVectors(); vectorIdx++) { for (auto i = 0u; i < numTuplesToCopy; i++) { auto srcPos = chunk.state->selVector->selectedPositions[numTuplesAppended + i]; - auto dstPos = chunkToAppendInfo->state->selVector->selectedSize + i; - chunkToAppendInfo->getValueVector(vectorIdx)->copyFromVectorData( - dstPos, chunk.getValueVector(vectorIdx).get(), srcPos); + auto dstPos = chunkToAppend.state->selVector->selectedSize + i; + chunkToAppend.getValueVector(vectorIdx)->copyFromVectorData(dstPos, + chunk.getValueVector(vectorIdx).get(), srcPos); } } - chunkToAppendInfo->state->selVector->selectedSize += numTuplesToCopy; + chunkToAppend.state->selVector->selectedSize += numTuplesToCopy; numTuplesAppended += numTuplesToCopy; } } -void DataChunkCollection::append(std::unique_ptr chunk) { - KU_ASSERT(chunk); +void DataChunkCollection::merge(DataChunk chunk) { if (chunks.empty()) { - initTypes(*chunk); + initTypes(chunk); } - KU_ASSERT(chunk->getNumValueVectors() == types.size()); - for (auto vectorIdx = 0u; vectorIdx < chunk->getNumValueVectors(); vectorIdx++) { - KU_ASSERT(chunk->getValueVector(vectorIdx)->dataType == types[vectorIdx]); + KU_ASSERT(chunk.getNumValueVectors() == types.size()); + for (auto vectorIdx = 0u; vectorIdx < chunk.getNumValueVectors(); vectorIdx++) { + KU_ASSERT(chunk.getValueVector(vectorIdx)->dataType == types[vectorIdx]); } chunks.push_back(std::move(chunk)); } void DataChunkCollection::initTypes(DataChunk& chunk) { + types.clear(); types.reserve(chunk.getNumValueVectors()); for (auto vectorIdx = 0u; vectorIdx < chunk.getNumValueVectors(); vectorIdx++) { types.push_back(chunk.getValueVector(vectorIdx)->dataType); } } -std::vector DataChunkCollection::getChunks() const { - std::vector ret; - ret.reserve(chunks.size()); - for (auto& chunk : chunks) { - ret.push_back(chunk.get()); - } - return ret; -} - -DataChunk* DataChunkCollection::allocateChunk(DataChunk& chunk) { +void DataChunkCollection::allocateChunk(DataChunk& chunk) { if (chunks.empty()) { types.reserve(chunk.getNumValueVectors()); for (auto vectorIdx = 0u; vectorIdx < chunk.getNumValueVectors(); vectorIdx++) { types.push_back(chunk.getValueVector(vectorIdx)->dataType); } } - auto newChunk = std::make_unique(types.size(), std::make_shared()); + DataChunk newChunk(types.size(), std::make_shared()); for (auto i = 0u; i < types.size(); i++) { - newChunk->insert(i, std::make_shared(types[i], mm)); + newChunk.insert(i, std::make_shared(types[i], mm)); } chunks.push_back(std::move(newChunk)); - return chunks.back().get(); } } // namespace common diff --git a/src/common/data_chunk/data_chunk_state.cpp b/src/common/data_chunk/data_chunk_state.cpp index af5c739c7b1..8faecbccbe6 100644 --- a/src/common/data_chunk/data_chunk_state.cpp +++ b/src/common/data_chunk/data_chunk_state.cpp @@ -14,7 +14,7 @@ void DataChunkState::slice(offset_t offset) { // NOTE: this operation has performance penalty. Ideally we should directly modify selVector // instead of creating a new one. auto slicedSelVector = std::make_unique(DEFAULT_VECTOR_CAPACITY); - slicedSelVector->resetSelectorToValuePosBufferWithSize(selVector->selectedSize - offset); + slicedSelVector->setToFiltered(selVector->selectedSize - offset); for (auto i = 0u; i < slicedSelVector->selectedSize; i++) { slicedSelVector->selectedPositions[i] = selVector->selectedPositions[i + offset]; } diff --git a/src/common/exception/message.cpp b/src/common/exception/message.cpp index 73225116cd5..a57f873d8b6 100644 --- a/src/common/exception/message.cpp +++ b/src/common/exception/message.cpp @@ -21,6 +21,14 @@ std::string ExceptionMessage::invalidPKType(const std::string& type) { type); } +std::string ExceptionMessage::nullPKException() { + return "Found NULL, which violates the non-null constraint of the primary key column."; +} + +std::string ExceptionMessage::notAllowCopyOnNonEmptyTableException() { + return "COPY commands can only be executed once on a table."; +} + std::string ExceptionMessage::overLargeStringPKValueException(uint64_t length) { return stringFormat("The maximum length of primary key strings is 262144 bytes. The input " "string's length was {}.", @@ -40,16 +48,15 @@ std::string ExceptionMessage::violateDeleteNodeWithConnectedEdgesConstraint( offset, tableName, direction); } -std::string ExceptionMessage::violateRelMultiplicityConstraint( - const std::string& tableName, const std::string& offset, const std::string& direction) { +std::string ExceptionMessage::violateRelMultiplicityConstraint(const std::string& tableName, + const std::string& offset, const std::string& direction) { return stringFormat("Node(nodeOffset: {}) has more than one neighbour in table {} in the {} " "direction, which violates the rel multiplicity constraint.", offset, tableName, direction); } -std::string ExceptionMessage::validateCopyNpyNotForRelTablesException( - const std::string& tableName) { - return stringFormat("Copy from npy files to rel table {} is not supported yet.", tableName); +std::string ExceptionMessage::variableNotInScope(const std::string& varName) { + return stringFormat("Variable {} is not in scope.", varName); } } // namespace common diff --git a/src/common/expression_type.cpp b/src/common/expression_type.cpp index e24bb21c4ec..4e33b2e1574 100644 --- a/src/common/expression_type.cpp +++ b/src/common/expression_type.cpp @@ -1,6 +1,9 @@ #include "common/enums/expression_type.h" #include "common/assert.h" +#include "function/comparison/vector_comparison_functions.h" + +using namespace kuzu::function; namespace kuzu { namespace common { @@ -54,17 +57,17 @@ std::string expressionTypeToString(ExpressionType type) { case ExpressionType::NOT: return "NOT"; case ExpressionType::EQUALS: - return EQUALS_FUNC_NAME; + return EqualsFunction::name; case ExpressionType::NOT_EQUALS: - return NOT_EQUALS_FUNC_NAME; + return NotEqualsFunction::name; case ExpressionType::GREATER_THAN: - return GREATER_THAN_FUNC_NAME; + return GreaterThanFunction::name; case ExpressionType::GREATER_THAN_EQUALS: - return GREATER_THAN_EQUALS_FUNC_NAME; + return GreaterThanEqualsFunction::name; case ExpressionType::LESS_THAN: - return LESS_THAN_FUNC_NAME; + return LessThanFunction::name; case ExpressionType::LESS_THAN_EQUALS: - return LESS_THAN_EQUALS_FUNC_NAME; + return LessThanEqualsFunction::name; case ExpressionType::IS_NULL: return "IS_NULL"; case ExpressionType::IS_NOT_NULL: diff --git a/src/common/file_system/file_system.cpp b/src/common/file_system/file_system.cpp index 6bdca6dd631..4985ea99f41 100644 --- a/src/common/file_system/file_system.cpp +++ b/src/common/file_system/file_system.cpp @@ -7,6 +7,10 @@ void FileSystem::overwriteFile(const std::string& /*from*/, const std::string& / KU_UNREACHABLE; } +void FileSystem::copyFile(const std::string& /*from*/, const std::string& /*to*/) const { + KU_UNREACHABLE; +} + void FileSystem::createDir(const std::string& /*dir*/) const { KU_UNREACHABLE; } @@ -19,6 +23,11 @@ bool FileSystem::fileOrPathExists(const std::string& /*path*/) const { KU_UNREACHABLE; } +std::string FileSystem::expandPath(main::ClientContext* /*context*/, + const std::string& path) const { + return path; +} + std::string FileSystem::joinPath(const std::string& base, const std::string& part) { return (std::filesystem::path{base} / part).string(); } diff --git a/src/common/file_system/local_file_system.cpp b/src/common/file_system/local_file_system.cpp index 1f91d006b0c..723faa7c1a1 100644 --- a/src/common/file_system/local_file_system.cpp +++ b/src/common/file_system/local_file_system.cpp @@ -39,14 +39,9 @@ LocalFileInfo::~LocalFileInfo() { #endif } -std::unique_ptr LocalFileSystem::openFile( - const std::string& path, int flags, main::ClientContext* context, FileLockType lock_type) { - auto fullPath = path; - if (path.starts_with('~')) { - fullPath = - context->getCurrentSetting(main::HomeDirectorySetting::name).getValue() + - fullPath.substr(1); - } +std::unique_ptr LocalFileSystem::openFile(const std::string& path, int flags, + main::ClientContext* context, FileLockType lock_type) { + auto fullPath = expandPath(context, path); #if defined(_WIN32) auto dwDesiredAccess = 0ul; auto dwCreationDisposition = (flags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING; @@ -98,8 +93,8 @@ std::unique_ptr LocalFileSystem::openFile( #endif } -std::vector LocalFileSystem::glob( - main::ClientContext* context, const std::string& path) const { +std::vector LocalFileSystem::glob(main::ClientContext* context, + const std::string& path) const { if (path.empty()) { return std::vector(); } @@ -138,11 +133,23 @@ void LocalFileSystem::overwriteFile(const std::string& from, const std::string& if (!fileOrPathExists(from) || !fileOrPathExists(to)) return; std::error_code errorCode; - if (!std::filesystem::copy_file( - from, to, std::filesystem::copy_options::overwrite_existing, errorCode)) { + if (!std::filesystem::copy_file(from, to, std::filesystem::copy_options::overwrite_existing, + errorCode)) { // LCOV_EXCL_START - throw Exception(stringFormat( - "Error copying file {} to {}. ErrorMessage: {}", from, to, errorCode.message())); + throw Exception(stringFormat("Error copying file {} to {}. ErrorMessage: {}", from, to, + errorCode.message())); + // LCOV_EXCL_STOP + } +} + +void LocalFileSystem::copyFile(const std::string& from, const std::string& to) const { + if (!fileOrPathExists(from)) + return; + std::error_code errorCode; + if (!std::filesystem::copy_file(from, to, std::filesystem::copy_options::none, errorCode)) { + // LCOV_EXCL_START + throw Exception(stringFormat("Error copying file {} to {}. ErrorMessage: {}", from, to, + errorCode.message())); // LCOV_EXCL_STOP } } @@ -172,8 +179,8 @@ void LocalFileSystem::removeFileIfExists(const std::string& path) const { return; if (remove(path.c_str()) != 0) { // LCOV_EXCL_START - throw Exception(stringFormat( - "Error removing directory or file {}. Error Message: {}", path, posixErrMessage())); + throw Exception(stringFormat("Error removing directory or file {}. Error Message: {}", + path, posixErrMessage())); // LCOV_EXCL_STOP } } @@ -182,8 +189,19 @@ bool LocalFileSystem::fileOrPathExists(const std::string& path) const { return std::filesystem::exists(path); } -void LocalFileSystem::readFromFile( - FileInfo* fileInfo, void* buffer, uint64_t numBytes, uint64_t position) const { +std::string LocalFileSystem::expandPath(main::ClientContext* context, + const std::string& path) const { + auto fullPath = path; + if (path.starts_with('~')) { + fullPath = + context->getCurrentSetting(main::HomeDirectorySetting::name).getValue() + + fullPath.substr(1); + } + return fullPath; +} + +void LocalFileSystem::readFromFile(FileInfo* fileInfo, void* buffer, uint64_t numBytes, + uint64_t position) const { auto localFileInfo = ku_dynamic_cast(fileInfo); #if defined(_WIN32) DWORD numBytesRead; @@ -227,8 +245,8 @@ int64_t LocalFileSystem::readFile(FileInfo* fileInfo, void* buf, size_t nbyte) c #endif } -void LocalFileSystem::writeFile( - FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, uint64_t offset) const { +void LocalFileSystem::writeFile(FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, + uint64_t offset) const { auto localFileInfo = ku_dynamic_cast(fileInfo); uint64_t remainingNumBytesToWrite = numBytes; uint64_t bufferOffset = 0; diff --git a/src/common/file_system/virtual_file_system.cpp b/src/common/file_system/virtual_file_system.cpp index d54bbc7cf40..962f0c3a30d 100644 --- a/src/common/file_system/virtual_file_system.cpp +++ b/src/common/file_system/virtual_file_system.cpp @@ -15,13 +15,13 @@ void VirtualFileSystem::registerFileSystem(std::unique_ptr fileSyste subSystems.push_back(std::move(fileSystem)); } -std::unique_ptr VirtualFileSystem::openFile( - const std::string& path, int flags, main::ClientContext* context, FileLockType lockType) { +std::unique_ptr VirtualFileSystem::openFile(const std::string& path, int flags, + main::ClientContext* context, FileLockType lockType) { return findFileSystem(path)->openFile(path, flags, context, lockType); } -std::vector VirtualFileSystem::glob( - main::ClientContext* context, const std::string& path) const { +std::vector VirtualFileSystem::glob(main::ClientContext* context, + const std::string& path) const { return findFileSystem(path)->glob(context, path); } @@ -41,8 +41,13 @@ bool VirtualFileSystem::fileOrPathExists(const std::string& path) const { return findFileSystem(path)->fileOrPathExists(path); } -void VirtualFileSystem::readFromFile( - FileInfo* /*fileInfo*/, void* /*buffer*/, uint64_t /*numBytes*/, uint64_t /*position*/) const { +std::string VirtualFileSystem::expandPath(main::ClientContext* context, + const std::string& path) const { + return findFileSystem(path)->expandPath(context, path); +} + +void VirtualFileSystem::readFromFile(FileInfo* /*fileInfo*/, void* /*buffer*/, + uint64_t /*numBytes*/, uint64_t /*position*/) const { KU_UNREACHABLE; } diff --git a/src/common/null_mask.cpp b/src/common/null_mask.cpp index d611c6d3a6d..e328f541ec8 100644 --- a/src/common/null_mask.cpp +++ b/src/common/null_mask.cpp @@ -88,8 +88,8 @@ void NullMask::resize(uint64_t capacity) { } bool NullMask::copyFromNullBits(const uint64_t* srcNullEntries, uint64_t srcOffset, - uint64_t dstOffset, uint64_t numBitsToCopy) { - if (copyNullMask(srcNullEntries, srcOffset, this->data, dstOffset, numBitsToCopy)) { + uint64_t dstOffset, uint64_t numBitsToCopy, bool invert) { + if (copyNullMask(srcNullEntries, srcOffset, this->data, dstOffset, numBitsToCopy, invert)) { this->mayContainNulls = true; return true; } @@ -103,8 +103,8 @@ void NullMask::setNullFromRange(uint64_t offset, uint64_t numBitsToSet, bool isN setNullRange(data, offset, numBitsToSet, isNull); } -void NullMask::setNullRange( - uint64_t* nullEntries, uint64_t offset, uint64_t numBitsToSet, bool isNull) { +void NullMask::setNullRange(uint64_t* nullEntries, uint64_t offset, uint64_t numBitsToSet, + bool isNull) { auto [firstEntryPos, firstBitPos] = getNullEntryAndBitPos(offset); auto [lastEntryPos, lastBitPos] = getNullEntryAndBitPos(offset + numBitsToSet); diff --git a/src/common/string_utils.cpp b/src/common/string_utils.cpp index a88d9adff84..febea00544b 100644 --- a/src/common/string_utils.cpp +++ b/src/common/string_utils.cpp @@ -25,8 +25,8 @@ std::vector StringUtils::splitComma(const std::string& input) { return result; } -std::vector StringUtils::split( - const std::string& input, const std::string& delimiter, bool ignoreEmptyStringParts) { +std::vector StringUtils::split(const std::string& input, const std::string& delimiter, + bool ignoreEmptyStringParts) { auto result = std::vector(); auto prevPos = 0u; auto currentPos = input.find(delimiter, prevPos); @@ -62,8 +62,8 @@ void StringUtils::removeCStringWhiteSpaces(const char*& input, uint64_t& len) { } } -void StringUtils::replaceAll( - std::string& str, const std::string& search, const std::string& replacement) { +void StringUtils::replaceAll(std::string& str, const std::string& search, + const std::string& replacement) { size_t pos = 0; while ((pos = str.find(search, pos)) != std::string::npos) { str.replace(pos, search.length(), replacement); @@ -71,8 +71,8 @@ void StringUtils::replaceAll( } } -std::string StringUtils::extractStringBetween( - const std::string& input, char delimiterStart, char delimiterEnd, bool includeDelimiter) { +std::string StringUtils::extractStringBetween(const std::string& input, char delimiterStart, + char delimiterEnd, bool includeDelimiter) { std::string::size_type posStart = input.find_first_of(delimiterStart); std::string::size_type posEnd = input.find_last_of(delimiterEnd); if (posStart == std::string::npos || posEnd == std::string::npos || posStart >= posEnd) { @@ -127,8 +127,8 @@ bool StringUtils::caseInsensitiveEquals(const std::string& left, const std::stri } std::string StringUtils::join(const std::vector& input, const std::string& separator) { - return StringUtils::join( - input, input.size(), separator, [](const std::string& s) { return s; }); + return StringUtils::join(input, input.size(), separator, + [](const std::string& s) { return s; }); } template diff --git a/src/common/system_message.cpp b/src/common/system_message.cpp index fa74c0332d6..d6b81e28d55 100644 --- a/src/common/system_message.cpp +++ b/src/common/system_message.cpp @@ -17,8 +17,8 @@ std::string dlErrMessage() { } LPSTR messageBuffer = nullptr; - auto size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + auto size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); diff --git a/src/common/task_system/CMakeLists.txt b/src/common/task_system/CMakeLists.txt index df38eee19d4..af22989bfe4 100644 --- a/src/common/task_system/CMakeLists.txt +++ b/src/common/task_system/CMakeLists.txt @@ -1,7 +1,8 @@ add_library(kuzu_common_task_system OBJECT task.cpp - task_scheduler.cpp) + task_scheduler.cpp + progress_bar.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/common/task_system/progress_bar.cpp b/src/common/task_system/progress_bar.cpp new file mode 100644 index 00000000000..e332d618044 --- /dev/null +++ b/src/common/task_system/progress_bar.cpp @@ -0,0 +1,105 @@ +#include "common/task_system/progress_bar.h" + +namespace kuzu { +namespace common { + +void ProgressBar::startProgress() { + if (!trackProgress) { + return; + } + std::lock_guard lock(progressBarLock); + queryTimer->start(); + printProgressBar(0.0); +} + +void ProgressBar::endProgress() { + std::lock_guard lock(progressBarLock); + resetProgressBar(); + queryTimer = std::make_unique(true); +} + +void ProgressBar::addPipeline() { + if (!trackProgress) { + return; + } + numPipelines++; +} + +void ProgressBar::finishPipeline() { + if (!trackProgress) { + return; + } + numPipelinesFinished++; + if (printing) { + std::cout << "\033[1A\033[2K\033[1B"; + } + // This ensures that the progress bar is updated back to 0% after a pipeline is finished. + prevCurPipelineProgress = -0.01; + updateProgress(0.0); +} + +void ProgressBar::updateProgress(double curPipelineProgress) { + if (!trackProgress) { + return; + } + std::lock_guard lock(progressBarLock); + // Only update the progress bar if the progress has changed by at least 1%. + if (curPipelineProgress - prevCurPipelineProgress < 0.01) { + return; + } + prevCurPipelineProgress = curPipelineProgress; + if (printing) { + std::cout << "\033[2A"; + } + printProgressBar(curPipelineProgress); +} + +void ProgressBar::printProgressBar(double curPipelineProgress) { + if (!shouldPrintProgress()) { + return; + } + printing = true; + float pipelineProgress = 0.0; + if (numPipelines > 0) { + pipelineProgress = (float)numPipelinesFinished / (float)numPipelines; + } + setGreenFont(); + std::cout << "Pipelines Finished: " << int(pipelineProgress * 100.0) << "%" << "\n"; + std::cout << "Current Pipeline Progress: " << int(curPipelineProgress * 100.0) << "%" << "\n"; + std::cout.flush(); + setDefaultFont(); +} + +void ProgressBar::resetProgressBar() { + if (printing) { + std::cout << "\033[2A\033[2K\033[1B\033[2K\033[1A"; + std::cout.flush(); + } + numPipelines = 0; + numPipelinesFinished = 0; + prevCurPipelineProgress = 0.0; + printing = false; + if (queryTimer->isStarted) { + queryTimer->stop(); + } +} + +bool ProgressBar::shouldPrintProgress() const { + if (queryTimer->isStarted) { + queryTimer->stop(); + } + bool shouldPrint = queryTimer->getElapsedTimeMS() > showProgressAfter; + queryTimer->start(); + return shouldPrint; +} + +void ProgressBar::toggleProgressBarPrinting(bool enable) { + trackProgress = enable; +} + +void ProgressBar::setShowProgressAfter(uint64_t time) { + showProgressAfter = time; +} + +} // namespace common +} // namespace kuzu diff --git a/src/common/task_system/task.cpp b/src/common/task_system/task.cpp index 143d4139266..3d07ce04517 100644 --- a/src/common/task_system/task.cpp +++ b/src/common/task_system/task.cpp @@ -20,7 +20,9 @@ void Task::deRegisterThreadAndFinalizeTask() { if (!hasExceptionNoLock() && isCompletedNoLock()) { try { finalizeIfNecessary(); - } catch (std::exception& e) { setExceptionNoLock(std::current_exception()); } + } catch (std::exception& e) { + setExceptionNoLock(std::current_exception()); + } } if (isCompletedNoLock()) { lck.unlock(); diff --git a/src/common/task_system/task_scheduler.cpp b/src/common/task_system/task_scheduler.cpp index a01a4114584..c1c181f5b4d 100644 --- a/src/common/task_system/task_scheduler.cpp +++ b/src/common/task_system/task_scheduler.cpp @@ -21,8 +21,8 @@ TaskScheduler::~TaskScheduler() { } } -void TaskScheduler::scheduleTaskAndWaitOrError( - const std::shared_ptr& task, processor::ExecutionContext* context) { +void TaskScheduler::scheduleTaskAndWaitOrError(const std::shared_ptr& task, + processor::ExecutionContext* context) { for (auto& dependency : task->children) { scheduleTaskAndWaitOrError(dependency, context); } @@ -40,7 +40,7 @@ void TaskScheduler::scheduleTaskAndWaitOrError( taskLck.unlock(); break; } - if (context->clientContext->isTimeOutEnabled()) { + if (context->clientContext->hasTimeout()) { timeout = context->clientContext->getTimeoutRemainingInMS(); if (timeout == 0) { context->clientContext->interrupt(); diff --git a/src/common/type_utils.cpp b/src/common/type_utils.cpp index 8a4035e5c10..c1d0321fdc7 100644 --- a/src/common/type_utils.cpp +++ b/src/common/type_utils.cpp @@ -5,8 +5,8 @@ namespace kuzu { namespace common { -static std::string entryToString( - const LogicalType& dataType, const uint8_t* value, ValueVector* vector) { +static std::string entryToString(const LogicalType& dataType, const uint8_t* value, + ValueVector* vector) { auto valueVector = reinterpret_cast(vector); switch (dataType.getLogicalTypeID()) { case LogicalTypeID::BOOL: @@ -51,9 +51,8 @@ static std::string entryToString( return TypeUtils::toString(*reinterpret_cast(value)); case LogicalTypeID::INTERNAL_ID: return TypeUtils::toString(*reinterpret_cast(value)); - case LogicalTypeID::FIXED_LIST: - return TypeUtils::fixedListToString(value, dataType, valueVector); - case LogicalTypeID::VAR_LIST: + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: return TypeUtils::toString(*reinterpret_cast(value), valueVector); case LogicalTypeID::MAP: return TypeUtils::toString(*reinterpret_cast(value), valueVector); @@ -64,8 +63,8 @@ static std::string entryToString( case LogicalTypeID::UUID: return TypeUtils::toString(*reinterpret_cast(value)); case LogicalTypeID::NODE: - return TypeUtils::nodeToString( - *reinterpret_cast(value), valueVector); + return TypeUtils::nodeToString(*reinterpret_cast(value), + valueVector); case LogicalTypeID::REL: return TypeUtils::relToString(*reinterpret_cast(value), valueVector); default: @@ -77,24 +76,8 @@ static std::string entryToString(sel_t pos, ValueVector* vector) { if (vector->isNull(pos)) { return ""; } - return entryToString( - vector->dataType, vector->getData() + vector->getNumBytesPerValue() * pos, vector); -} - -std::string TypeUtils::fixedListToString( - const uint8_t* val, const LogicalType& type, ValueVector* dummyVector) { - std::string result = "["; - auto numValuesPerList = FixedListType::getNumValuesInList(&type); - auto childType = FixedListType::getChildType(&type); - for (auto i = 0u; i < numValuesPerList - 1; ++i) { - // Note: FixedList can only store numeric types and doesn't allow nulls. - result += entryToString(*childType, val, dummyVector); - result += ","; - val += PhysicalTypeUtils::getFixedTypeSize(childType->getPhysicalType()); - } - result += entryToString(*childType, val, dummyVector); - result += "]"; - return result; + return entryToString(vector->dataType, vector->getData() + vector->getNumBytesPerValue() * pos, + vector); } template<> @@ -179,8 +162,8 @@ std::string TypeUtils::toString(const list_entry_t& val, void* valueVector) { return result; } -static std::string getMapEntryStr( - sel_t pos, ValueVector* dataVector, ValueVector* keyVector, ValueVector* valVector) { +static std::string getMapEntryStr(sel_t pos, ValueVector* dataVector, ValueVector* keyVector, + ValueVector* valVector) { if (dataVector->isNull(pos)) { return ""; } diff --git a/src/common/types/date_t.cpp b/src/common/types/date_t.cpp index 7faa6426ad2..0abf2798357 100644 --- a/src/common/types/date_t.cpp +++ b/src/common/types/date_t.cpp @@ -115,10 +115,10 @@ date_t date_t::operator-(const int32_t& day) const { const int32_t Date::NORMAL_DAYS[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int32_t Date::LEAP_DAYS[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -const int32_t Date::CUMULATIVE_LEAP_DAYS[] = { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; -const int32_t Date::CUMULATIVE_DAYS[] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; +const int32_t Date::CUMULATIVE_LEAP_DAYS[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, + 366}; +const int32_t Date::CUMULATIVE_DAYS[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, + 365}; const int8_t Date::MONTH_PER_DAY_OF_YEAR[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, @@ -391,8 +391,8 @@ int32_t Date::monthDays(int32_t year, int32_t month) { } std::string Date::getDayName(date_t& date) { - std::string dayNames[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + std::string dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", + "Saturday"}; return dayNames[(date.days < 0 ? 7 - ((-date.days + 3) % 7) : ((date.days + 3) % 7) + 1) % 7]; } @@ -448,8 +448,8 @@ int32_t Date::getDatePart(DatePartSpecifier specifier, date_t& date) { date_t Date::trunc(DatePartSpecifier specifier, date_t& date) { switch (specifier) { case DatePartSpecifier::YEAR: - return Date::fromDate( - Date::getDatePart(DatePartSpecifier::YEAR, date), 1 /* month */, 1 /* day */); + return Date::fromDate(Date::getDatePart(DatePartSpecifier::YEAR, date), 1 /* month */, + 1 /* day */); case DatePartSpecifier::MONTH: return Date::fromDate(Date::getDatePart(DatePartSpecifier::YEAR, date), Date::getDatePart(DatePartSpecifier::MONTH, date), 1 /* day */); diff --git a/src/common/types/dtime_t.cpp b/src/common/types/dtime_t.cpp index ac11fc7a586..b0643cd9f8c 100644 --- a/src/common/types/dtime_t.cpp +++ b/src/common/types/dtime_t.cpp @@ -201,8 +201,8 @@ dtime_t Time::fromTimeInternal(int32_t hour, int32_t minute, int32_t second, int dtime_t Time::fromTime(int32_t hour, int32_t minute, int32_t second, int32_t microseconds) { if (!Time::isValid(hour, minute, second, microseconds)) { - throw ConversionException(stringFormat( - "Time field value out of range: {}:{}:{}[.{}].", hour, minute, second, microseconds)); + throw ConversionException(stringFormat("Time field value out of range: {}:{}:{}[.{}].", + hour, minute, second, microseconds)); } return Time::fromTimeInternal(hour, minute, second, microseconds); } diff --git a/src/common/types/interval_t.cpp b/src/common/types/interval_t.cpp index e2d41cb2c95..cd77cbccb2d 100644 --- a/src/common/types/interval_t.cpp +++ b/src/common/types/interval_t.cpp @@ -219,7 +219,7 @@ interval_t Interval::fromCString(const char* str, uint64_t len) { } goto interval_parse_identifier; -interval_parse_time : { +interval_parse_time: { // parse the remainder of the time as a Time type dtime_t time; uint64_t tmpPos; @@ -336,8 +336,8 @@ std::string Interval::toString(interval_t interval) { } // helper function of interval comparison -void Interval::normalizeIntervalEntries( - interval_t input, int64_t& months, int64_t& days, int64_t& micros) { +void Interval::normalizeIntervalEntries(interval_t input, int64_t& months, int64_t& days, + int64_t& micros) { int64_t extra_months_d = input.days / Interval::DAYS_PER_MONTH; int64_t extra_months_micros = input.micros / Interval::MICROS_PER_MONTH; input.days -= extra_months_d * Interval::DAYS_PER_MONTH; diff --git a/src/common/types/ku_list.cpp b/src/common/types/ku_list.cpp index f0d530d4d2b..f923339d9b7 100644 --- a/src/common/types/ku_list.cpp +++ b/src/common/types/ku_list.cpp @@ -9,7 +9,7 @@ namespace common { void ku_list_t::set(const uint8_t* values, const LogicalType& dataType) const { memcpy(reinterpret_cast(overflowPtr), values, - size * storage::StorageUtils::getDataTypeSize(*VarListType::getChildType(&dataType))); + size * storage::StorageUtils::getDataTypeSize(*ListType::getChildType(&dataType))); } void ku_list_t::set(const std::vector& parameters, LogicalTypeID childTypeId) { diff --git a/src/common/types/timestamp_t.cpp b/src/common/types/timestamp_t.cpp index b517929ce96..8a42fe00663 100644 --- a/src/common/types/timestamp_t.cpp +++ b/src/common/types/timestamp_t.cpp @@ -177,8 +177,8 @@ timestamp_t Timestamp::fromCString(const char* str, uint64_t len) { return result; } -bool Timestamp::tryParseUTCOffset( - const char* str, uint64_t& pos, uint64_t len, int& hour_offset, int& minute_offset) { +bool Timestamp::tryParseUTCOffset(const char* str, uint64_t& pos, uint64_t len, int& hour_offset, + int& minute_offset) { minute_offset = 0; uint64_t curpos = pos; // parse the next 3 characters @@ -318,11 +318,11 @@ timestamp_t Timestamp::trunc(DatePartSpecifier specifier, timestamp_t& timestamp case DatePartSpecifier::SECOND: return Timestamp::fromDateTime(date, Time::fromTime(hour, min, sec, 0 /* microseconds */)); case DatePartSpecifier::MINUTE: - return Timestamp::fromDateTime( - date, Time::fromTime(hour, min, 0 /* seconds */, 0 /* microseconds */)); + return Timestamp::fromDateTime(date, + Time::fromTime(hour, min, 0 /* seconds */, 0 /* microseconds */)); case DatePartSpecifier::HOUR: - return Timestamp::fromDateTime( - date, Time::fromTime(hour, 0 /* minutes */, 0 /* seconds */, 0 /* microseconds */)); + return Timestamp::fromDateTime(date, + Time::fromTime(hour, 0 /* minutes */, 0 /* seconds */, 0 /* microseconds */)); default: date_t date = getDate(timestamp); return fromDateTime(Date::trunc(specifier, date), dtime_t(0)); diff --git a/src/common/types/types.cpp b/src/common/types/types.cpp index 5931e80da4b..17df3754ef0 100644 --- a/src/common/types/types.cpp +++ b/src/common/types/types.cpp @@ -45,16 +45,14 @@ std::string PhysicalTypeUtils::physicalTypeToString(PhysicalTypeID physicalType) return "FLOAT"; case PhysicalTypeID::INTERVAL: return "INTERVAL"; - case PhysicalTypeID::FIXED_LIST: - return "FIXED_LIST"; case PhysicalTypeID::INTERNAL_ID: return "INTERNAL_ID"; case PhysicalTypeID::STRING: return "STRING"; case PhysicalTypeID::STRUCT: return "STRUCT"; - case PhysicalTypeID::VAR_LIST: - return "VAR_LIST"; + case PhysicalTypeID::LIST: + return "LIST"; case PhysicalTypeID::POINTER: return "POINTER"; default: @@ -98,40 +96,40 @@ uint32_t PhysicalTypeUtils::getFixedTypeSize(PhysicalTypeID physicalType) { } } -bool VarListTypeInfo::operator==(const VarListTypeInfo& other) const { +bool ListTypeInfo::operator==(const ListTypeInfo& other) const { return *childType == *other.childType; } -std::unique_ptr VarListTypeInfo::copy() const { - return std::make_unique(childType->copy()); +std::unique_ptr ListTypeInfo::copy() const { + return std::make_unique(childType->copy()); } -std::unique_ptr VarListTypeInfo::deserialize(Deserializer& deserializer) { - return std::make_unique(LogicalType::deserialize(deserializer)); +std::unique_ptr ListTypeInfo::deserialize(Deserializer& deserializer) { + return std::make_unique(LogicalType::deserialize(deserializer)); } -void VarListTypeInfo::serializeInternal(Serializer& serializer) const { +void ListTypeInfo::serializeInternal(Serializer& serializer) const { childType->serialize(serializer); } -bool FixedListTypeInfo::operator==(const FixedListTypeInfo& other) const { - return *childType == *other.childType && fixedNumElementsInList == other.fixedNumElementsInList; +bool ArrayTypeInfo::operator==(const ArrayTypeInfo& other) const { + return *childType == *other.childType && numElements == other.numElements; } -std::unique_ptr FixedListTypeInfo::deserialize(Deserializer& deserializer) { +std::unique_ptr ArrayTypeInfo::deserialize(Deserializer& deserializer) { auto childType = LogicalType::deserialize(deserializer); - uint64_t fixedNumElementsInList; - deserializer.deserializeValue(fixedNumElementsInList); - return std::make_unique(std::move(childType), fixedNumElementsInList); + uint64_t numElements; + deserializer.deserializeValue(numElements); + return std::make_unique(std::move(childType), numElements); } -std::unique_ptr FixedListTypeInfo::copy() const { - return std::make_unique(childType->copy(), fixedNumElementsInList); +std::unique_ptr ArrayTypeInfo::copy() const { + return std::make_unique(childType->copy(), numElements); } -void FixedListTypeInfo::serializeInternal(Serializer& serializer) const { - VarListTypeInfo::serializeInternal(serializer); - serializer.serializeValue(fixedNumElementsInList); +void ArrayTypeInfo::serializeInternal(Serializer& serializer) const { + ListTypeInfo::serializeInternal(serializer); + serializer.serializeValue(numElements); } bool StructField::operator==(const StructField& other) const { @@ -258,8 +256,7 @@ void StructTypeInfo::serializeInternal(Serializer& serializer) const { LogicalType::LogicalType(LogicalTypeID typeID) : typeID{typeID}, extraTypeInfo{nullptr} { physicalType = getPhysicalType(typeID); // Complex types should not use this constructor as they need extra type information - KU_ASSERT(physicalType != PhysicalTypeID::VAR_LIST); - KU_ASSERT(physicalType != PhysicalTypeID::FIXED_LIST); + KU_ASSERT(physicalType != PhysicalTypeID::LIST); // Node/Rel types are exempted due to some complex code in bind_graph_pattern.cpp KU_ASSERT(physicalType != PhysicalTypeID::STRUCT || typeID == LogicalTypeID::NODE || typeID == LogicalTypeID::REL || typeID == LogicalTypeID::RECURSIVE_REL); @@ -289,12 +286,14 @@ bool LogicalType::operator==(const LogicalType& other) const { return false; } switch (other.getPhysicalType()) { - case PhysicalTypeID::VAR_LIST: - return *ku_dynamic_cast(extraTypeInfo.get()) == - *ku_dynamic_cast(other.extraTypeInfo.get()); - case PhysicalTypeID::FIXED_LIST: - return *ku_dynamic_cast(extraTypeInfo.get()) == - *ku_dynamic_cast(other.extraTypeInfo.get()); + case PhysicalTypeID::LIST: + if (typeID == LogicalTypeID::ARRAY) { + return *ku_dynamic_cast(extraTypeInfo.get()) == + *ku_dynamic_cast(other.extraTypeInfo.get()); + } else { + return *ku_dynamic_cast(extraTypeInfo.get()) == + *ku_dynamic_cast(other.extraTypeInfo.get()); + } case PhysicalTypeID::STRUCT: return *ku_dynamic_cast(extraTypeInfo.get()) == *ku_dynamic_cast(other.extraTypeInfo.get()); @@ -311,20 +310,18 @@ std::string LogicalType::toString() const { switch (typeID) { case LogicalTypeID::MAP: { auto structType = - ku_dynamic_cast(extraTypeInfo.get())->getChildType(); + ku_dynamic_cast(extraTypeInfo.get())->getChildType(); auto fieldTypes = StructType::getFieldTypes(structType); return "MAP(" + fieldTypes[0]->toString() + ": " + fieldTypes[1]->toString() + ")"; } - case LogicalTypeID::VAR_LIST: { - auto varListTypeInfo = - ku_dynamic_cast(extraTypeInfo.get()); - return varListTypeInfo->getChildType()->toString() + "[]"; + case LogicalTypeID::LIST: { + auto listTypeInfo = ku_dynamic_cast(extraTypeInfo.get()); + return listTypeInfo->getChildType()->toString() + "[]"; } - case LogicalTypeID::FIXED_LIST: { - auto fixedListTypeInfo = - ku_dynamic_cast(extraTypeInfo.get()); - return fixedListTypeInfo->getChildType()->toString() + "[" + - std::to_string(fixedListTypeInfo->getNumValuesInList()) + "]"; + case LogicalTypeID::ARRAY: { + auto arrayTypeInfo = ku_dynamic_cast(extraTypeInfo.get()); + return arrayTypeInfo->getChildType()->toString() + "[" + + std::to_string(arrayTypeInfo->getNumElements()) + "]"; } case LogicalTypeID::UNION: { auto unionTypeInfo = ku_dynamic_cast(extraTypeInfo.get()); @@ -391,8 +388,7 @@ void LogicalType::serialize(Serializer& serializer) const { serializer.serializeValue(typeID); serializer.serializeValue(physicalType); switch (physicalType) { - case PhysicalTypeID::VAR_LIST: - case PhysicalTypeID::FIXED_LIST: + case PhysicalTypeID::LIST: case PhysicalTypeID::STRUCT: extraTypeInfo->serialize(serializer); default: @@ -407,11 +403,12 @@ std::unique_ptr LogicalType::deserialize(Deserializer& deserializer deserializer.deserializeValue(physicalType); std::unique_ptr extraTypeInfo; switch (physicalType) { - case PhysicalTypeID::VAR_LIST: { - extraTypeInfo = VarListTypeInfo::deserialize(deserializer); - } break; - case PhysicalTypeID::FIXED_LIST: { - extraTypeInfo = FixedListTypeInfo::deserialize(deserializer); + case PhysicalTypeID::LIST: { + if (typeID == LogicalTypeID::ARRAY) { + extraTypeInfo = ArrayTypeInfo::deserialize(deserializer); + } else { + extraTypeInfo = ListTypeInfo::deserialize(deserializer); + } } break; case PhysicalTypeID::STRUCT: { extraTypeInfo = StructTypeInfo::deserialize(deserializer); @@ -436,13 +433,30 @@ std::unique_ptr LogicalType::copy() const { std::vector> LogicalType::copy( const std::vector>& types) { std::vector> typesCopy; - typesCopy.reserve(types.size()); for (auto& type : types) { typesCopy.push_back(type->copy()); } return typesCopy; } +std::vector LogicalType::copy(const std::vector& types) { + std::vector typesCopy; + typesCopy.reserve(types.size()); + for (auto& type : types) { + typesCopy.push_back(*type.copy()); + } + return typesCopy; +} + +std::vector LogicalType::copy(const std::vector& types) { + std::vector typesCopy; + typesCopy.reserve(types.size()); + for (auto& type : types) { + typesCopy.push_back(*type->copy()); + } + return typesCopy; +} + PhysicalTypeID LogicalType::getPhysicalType(LogicalTypeID typeID) { switch (typeID) { case LogicalTypeID::ANY: { @@ -495,9 +509,6 @@ PhysicalTypeID LogicalType::getPhysicalType(LogicalTypeID typeID) { case LogicalTypeID::INTERVAL: { return PhysicalTypeID::INTERVAL; } break; - case LogicalTypeID::FIXED_LIST: { - return PhysicalTypeID::FIXED_LIST; - } break; case LogicalTypeID::INTERNAL_ID: { return PhysicalTypeID::INTERNAL_ID; } break; @@ -505,9 +516,10 @@ PhysicalTypeID LogicalType::getPhysicalType(LogicalTypeID typeID) { case LogicalTypeID::STRING: { return PhysicalTypeID::STRING; } break; + case LogicalTypeID::ARRAY: case LogicalTypeID::MAP: - case LogicalTypeID::VAR_LIST: { - return PhysicalTypeID::VAR_LIST; + case LogicalTypeID::LIST: { + return PhysicalTypeID::LIST; } break; case LogicalTypeID::NODE: case LogicalTypeID::REL: @@ -530,9 +542,9 @@ LogicalType LogicalTypeUtils::dataTypeFromString(const std::string& dataTypeStri auto trimmedStr = StringUtils::ltrim(StringUtils::rtrim(dataTypeString)); auto upperDataTypeString = StringUtils::getUpper(trimmedStr); if (upperDataTypeString.ends_with("[]")) { - dataType = *parseVarListType(trimmedStr); + dataType = *parseListType(trimmedStr); } else if (upperDataTypeString.ends_with("]")) { - dataType = *parseFixedListType(trimmedStr); + dataType = *parseArrayType(trimmedStr); } else if (upperDataTypeString.starts_with("STRUCT")) { dataType = *parseStructType(trimmedStr); } else if (upperDataTypeString.starts_with("MAP")) { @@ -658,10 +670,10 @@ std::string LogicalTypeUtils::toString(LogicalTypeID dataTypeID) { return "UUID"; case LogicalTypeID::STRING: return "STRING"; - case LogicalTypeID::VAR_LIST: - return "VAR_LIST"; - case LogicalTypeID::FIXED_LIST: - return "FIXED_LIST"; + case LogicalTypeID::LIST: + return "LIST"; + case LogicalTypeID::ARRAY: + return "ARRAY"; case LogicalTypeID::STRUCT: return "STRUCT"; case LogicalTypeID::RDF_VARIANT: @@ -681,12 +693,15 @@ std::string LogicalTypeUtils::toString(LogicalTypeID dataTypeID) { } std::string LogicalTypeUtils::toString(const std::vector& dataTypes) { - std::vector dataTypeIDs; - dataTypeIDs.reserve(dataTypes.size()); - for (auto& dataType : dataTypes) { - dataTypeIDs.push_back(dataType.typeID); + if (dataTypes.empty()) { + return {""}; } - return toString(dataTypeIDs); + std::string result = "(" + dataTypes[0].toString(); + for (auto i = 1u; i < dataTypes.size(); ++i) { + result += "," + dataTypes[i].toString(); + } + result += ")"; + return result; } std::string LogicalTypeUtils::toString(const std::vector& dataTypeIDs) { @@ -706,11 +721,7 @@ uint32_t LogicalTypeUtils::getRowLayoutSize(const LogicalType& type) { case PhysicalTypeID::STRING: { return sizeof(ku_string_t); } - case PhysicalTypeID::FIXED_LIST: { - return getRowLayoutSize(*FixedListType::getChildType(&type)) * - FixedListType::getNumValuesInList(&type); - } - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { return sizeof(ku_list_t); } case PhysicalTypeID::STRUCT: { @@ -754,8 +765,8 @@ bool LogicalTypeUtils::isNested(const LogicalType& dataType) { bool LogicalTypeUtils::isNested(kuzu::common::LogicalTypeID logicalTypeID) { switch (logicalTypeID) { case LogicalTypeID::STRUCT: - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: case LogicalTypeID::UNION: case LogicalTypeID::MAP: case LogicalTypeID::NODE: @@ -797,8 +808,8 @@ std::vector LogicalTypeUtils::getAllValidLogicTypes() { LogicalTypeID::INT128, LogicalTypeID::DOUBLE, LogicalTypeID::STRING, LogicalTypeID::BLOB, LogicalTypeID::UUID, LogicalTypeID::DATE, LogicalTypeID::TIMESTAMP, LogicalTypeID::TIMESTAMP_NS, LogicalTypeID::TIMESTAMP_MS, LogicalTypeID::TIMESTAMP_SEC, - LogicalTypeID::TIMESTAMP_TZ, LogicalTypeID::INTERVAL, LogicalTypeID::VAR_LIST, - LogicalTypeID::FIXED_LIST, LogicalTypeID::MAP, LogicalTypeID::FLOAT, LogicalTypeID::SERIAL, + LogicalTypeID::TIMESTAMP_TZ, LogicalTypeID::INTERVAL, LogicalTypeID::LIST, + LogicalTypeID::ARRAY, LogicalTypeID::MAP, LogicalTypeID::FLOAT, LogicalTypeID::SERIAL, LogicalTypeID::NODE, LogicalTypeID::REL, LogicalTypeID::STRUCT, LogicalTypeID::UNION, LogicalTypeID::RDF_VARIANT}; } @@ -834,19 +845,19 @@ std::vector LogicalTypeUtils::parseStructFields(const std::string& return structFieldsStr; } -std::unique_ptr LogicalTypeUtils::parseVarListType(const std::string& trimmedStr) { - return LogicalType::VAR_LIST(dataTypeFromString(trimmedStr.substr(0, trimmedStr.size() - 2))); +std::unique_ptr LogicalTypeUtils::parseListType(const std::string& trimmedStr) { + return LogicalType::LIST(dataTypeFromString(trimmedStr.substr(0, trimmedStr.size() - 2))); } -std::unique_ptr LogicalTypeUtils::parseFixedListType(const std::string& trimmedStr) { - auto leftBracketPos = trimmedStr.find('['); - auto rightBracketPos = trimmedStr.find(']'); +std::unique_ptr LogicalTypeUtils::parseArrayType(const std::string& trimmedStr) { + auto leftBracketPos = trimmedStr.find_last_of('['); + auto rightBracketPos = trimmedStr.find_last_of(']'); auto childType = std::make_unique(dataTypeFromString(trimmedStr.substr(0, leftBracketPos))); - auto fixedNumElementsInList = std::strtoll( + auto numElements = std::strtoll( trimmedStr.substr(leftBracketPos + 1, rightBracketPos - leftBracketPos - 1).c_str(), nullptr, 0 /* base */); - return LogicalType::FIXED_LIST(std::move(childType), fixedNumElementsInList); + return LogicalType::ARRAY(std::move(childType), numElements); } std::vector LogicalTypeUtils::parseStructTypeInfo(const std::string& structTypeStr) { @@ -864,8 +875,8 @@ std::vector LogicalTypeUtils::parseStructTypeInfo(const std::string auto pos = structFieldStr.find(' '); auto fieldName = structFieldStr.substr(0, pos); auto fieldTypeString = structFieldStr.substr(pos + 1); - structFields.emplace_back( - fieldName, std::make_unique(dataTypeFromString(fieldTypeString))); + structFields.emplace_back(fieldName, + std::make_unique(dataTypeFromString(fieldTypeString))); } return structFields; } @@ -882,21 +893,21 @@ std::unique_ptr LogicalTypeUtils::parseMapType(const std::string& t } auto mapTypeStr = trimmedStr.substr(leftBracketPos + 1, rightBracketPos - leftBracketPos - 1); auto keyValueTypes = StringUtils::splitComma(mapTypeStr); - return LogicalType::MAP( - dataTypeFromString(keyValueTypes[0]), dataTypeFromString(keyValueTypes[1])); + return LogicalType::MAP(dataTypeFromString(keyValueTypes[0]), + dataTypeFromString(keyValueTypes[1])); } std::unique_ptr LogicalTypeUtils::parseUnionType(const std::string& trimmedStr) { auto unionFields = parseStructTypeInfo(trimmedStr); - auto unionTagField = StructField( - UnionType::TAG_FIELD_NAME, std::make_unique(UnionType::TAG_FIELD_TYPE)); + auto unionTagField = StructField(UnionType::TAG_FIELD_NAME, + std::make_unique(UnionType::TAG_FIELD_TYPE)); unionFields.insert(unionFields.begin(), std::move(unionTagField)); return LogicalType::UNION(std::move(unionFields)); } std::unique_ptr LogicalType::STRUCT(std::vector&& fields) { - return std::unique_ptr(new LogicalType( - LogicalTypeID::STRUCT, std::make_unique(std::move(fields)))); + return std::unique_ptr(new LogicalType(LogicalTypeID::STRUCT, + std::make_unique(std::move(fields)))); } std::unique_ptr LogicalType::RECURSIVE_REL(std::unique_ptr typeInfo) { @@ -926,25 +937,25 @@ std::unique_ptr LogicalType::UNION(std::vector&& field new LogicalType(LogicalTypeID::UNION, std::make_unique(std::move(fields)))); } -std::unique_ptr LogicalType::VAR_LIST(std::unique_ptr childType) { - return std::unique_ptr(new LogicalType( - LogicalTypeID::VAR_LIST, std::make_unique(std::move(childType)))); +std::unique_ptr LogicalType::LIST(std::unique_ptr childType) { + return std::unique_ptr( + new LogicalType(LogicalTypeID::LIST, std::make_unique(std::move(childType)))); } -std::unique_ptr LogicalType::MAP( - std::unique_ptr keyType, std::unique_ptr valueType) { +std::unique_ptr LogicalType::MAP(std::unique_ptr keyType, + std::unique_ptr valueType) { std::vector structFields; structFields.emplace_back(InternalKeyword::MAP_KEY, std::move(keyType)); structFields.emplace_back(InternalKeyword::MAP_VALUE, std::move(valueType)); auto mapStructType = LogicalType::STRUCT(std::move(structFields)); - return std::unique_ptr(new LogicalType( - LogicalTypeID::MAP, std::make_unique(std::move(mapStructType)))); + return std::unique_ptr(new LogicalType(LogicalTypeID::MAP, + std::make_unique(std::move(mapStructType)))); } -std::unique_ptr LogicalType::FIXED_LIST( - std::unique_ptr childType, uint64_t fixedNumElementsInList) { - return std::unique_ptr(new LogicalType(LogicalTypeID::FIXED_LIST, - std::make_unique(std::move(childType), fixedNumElementsInList))); +std::unique_ptr LogicalType::ARRAY(std::unique_ptr childType, + uint64_t numElements) { + return std::unique_ptr(new LogicalType(LogicalTypeID::ARRAY, + std::make_unique(std::move(childType), numElements))); } } // namespace common diff --git a/src/common/types/uuid.cpp b/src/common/types/uuid.cpp index eaad41fb329..0ab63269e6b 100644 --- a/src/common/types/uuid.cpp +++ b/src/common/types/uuid.cpp @@ -1,5 +1,6 @@ #include "common/types/uuid.h" +#include "common/exception/conversion.h" #include "common/random_engine.h" namespace kuzu { @@ -44,7 +45,7 @@ bool UUID::fromString(std::string str, int128_t& result) { result.low = 0; result.high = 0; uint32_t count = 0; - for (uint32_t i = numBrackets; i < str.size() - numBrackets; ++i) { + for (auto i = numBrackets; i < str.size() - numBrackets; ++i) { if (str[i] == '-') { continue; } @@ -65,7 +66,9 @@ bool UUID::fromString(std::string str, int128_t& result) { int128_t UUID::fromString(std::string str) { int128_t result; - fromString(str, result); + if (!fromString(str, result)) { + throw ConversionException("Invalid UUID: " + str); + } return result; } diff --git a/src/common/types/value/recursive_rel.cpp b/src/common/types/value/recursive_rel.cpp index 1d791ebb998..6bdcda5d299 100644 --- a/src/common/types/value/recursive_rel.cpp +++ b/src/common/types/value/recursive_rel.cpp @@ -21,8 +21,8 @@ Value* RecursiveRelVal::getRels(const Value* val) { void RecursiveRelVal::throwIfNotRecursiveRel(const Value* val) { // LCOV_EXCL_START if (val->dataType->getLogicalTypeID() != LogicalTypeID::RECURSIVE_REL) { - throw Exception(stringFormat( - "Expected RECURSIVE_REL type, but got {} type", val->dataType->toString())); + throw Exception(stringFormat("Expected RECURSIVE_REL type, but got {} type", + val->dataType->toString())); } // LCOV_EXCL_STOP } diff --git a/src/common/types/value/value.cpp b/src/common/types/value/value.cpp index 2b4a73912c1..8911e70b63f 100644 --- a/src/common/types/value/value.cpp +++ b/src/common/types/value/value.cpp @@ -96,18 +96,18 @@ Value Value::createDefaultValue(const LogicalType& dataType) { return Value(LogicalType::STRING(), std::string("")); case LogicalTypeID::FLOAT: return Value((float)0); - case LogicalTypeID::FIXED_LIST: { + case LogicalTypeID::ARRAY: { std::vector> children; - auto childType = FixedListType::getChildType(&dataType); - auto listSize = FixedListType::getNumValuesInList(&dataType); - children.reserve(listSize); - for (auto i = 0u; i < listSize; ++i) { + auto childType = ArrayType::getChildType(&dataType); + auto arraySize = ArrayType::getNumElements(&dataType); + children.reserve(arraySize); + for (auto i = 0u; i < arraySize; ++i) { children.push_back(std::make_unique(createDefaultValue(*childType))); } return Value(dataType.copy(), std::move(children)); } case LogicalTypeID::MAP: - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::LIST: { return Value(dataType.copy(), std::vector>{}); } case LogicalTypeID::UNION: { @@ -330,11 +330,11 @@ void Value::copyValueFrom(const uint8_t* value) { strVal = ((ku_string_t*)value)->getAsString(); } break; case LogicalTypeID::MAP: - case LogicalTypeID::VAR_LIST: { - copyFromVarList(*(ku_list_t*)value, *VarListType::getChildType(dataType.get())); + case LogicalTypeID::LIST: { + copyFromList(*(ku_list_t*)value, *ListType::getChildType(dataType.get())); } break; - case LogicalTypeID::FIXED_LIST: { - copyFromFixedList(value); + case LogicalTypeID::ARRAY: { + copyFromList(*(ku_list_t*)value, *ArrayType::getChildType(dataType.get())); } break; case LogicalTypeID::UNION: { copyFromUnion(value); @@ -407,8 +407,7 @@ void Value::copyValueFrom(const Value& other) { case PhysicalTypeID::STRING: { strVal = other.strVal; } break; - case PhysicalTypeID::VAR_LIST: - case PhysicalTypeID::FIXED_LIST: + case PhysicalTypeID::LIST: case PhysicalTypeID::STRUCT: { for (auto& child : other.children) { children.push_back(child->copy()); @@ -481,8 +480,8 @@ std::string Value::toString() const { case LogicalTypeID::MAP: { return mapToString(); } - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: { + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: { return listToString(); } case LogicalTypeID::UNION: { @@ -513,16 +512,7 @@ Value::Value(const LogicalType& dataType_) : isNull_{true} { dataType = dataType_.copy(); } -void Value::copyFromFixedList(const uint8_t* fixedList) { - auto numBytesPerElement = - storage::StorageUtils::getDataTypeSize(*FixedListType::getChildType(dataType.get())); - for (auto i = 0u; i < childrenSize; ++i) { - auto childValue = children[i].get(); - childValue->copyValueFrom(fixedList + i * numBytesPerElement); - } -} - -void Value::copyFromVarList(ku_list_t& list, const LogicalType& childType) { +void Value::copyFromList(ku_list_t& list, const LogicalType& childType) { if (list.size > children.size()) { children.reserve(list.size); for (auto i = children.size(); i < list.size; ++i) { @@ -634,8 +624,7 @@ void Value::serialize(Serializer& serializer) const { case PhysicalTypeID::STRING: { serializer.serializeValue(strVal); } break; - case PhysicalTypeID::VAR_LIST: - case PhysicalTypeID::FIXED_LIST: + case PhysicalTypeID::LIST: case PhysicalTypeID::STRUCT: { for (auto i = 0u; i < childrenSize; ++i) { children[i]->serialize(serializer); @@ -699,8 +688,7 @@ std::unique_ptr Value::deserialize(Deserializer& deserializer) { case PhysicalTypeID::STRING: { deserializer.deserializeValue(val->strVal); } break; - case PhysicalTypeID::VAR_LIST: - case PhysicalTypeID::FIXED_LIST: + case PhysicalTypeID::LIST: case PhysicalTypeID::STRUCT: { deserializer.deserializeVectorOfPtrs(val->children); } break; diff --git a/src/common/vector/auxiliary_buffer.cpp b/src/common/vector/auxiliary_buffer.cpp index 27e0bc91c37..e40f021c950 100644 --- a/src/common/vector/auxiliary_buffer.cpp +++ b/src/common/vector/auxiliary_buffer.cpp @@ -5,8 +5,8 @@ namespace kuzu { namespace common { -StructAuxiliaryBuffer::StructAuxiliaryBuffer( - const LogicalType& type, storage::MemoryManager* memoryManager) { +StructAuxiliaryBuffer::StructAuxiliaryBuffer(const LogicalType& type, + storage::MemoryManager* memoryManager) { auto fieldTypes = StructType::getFieldTypes(&type); childrenVectors.reserve(fieldTypes.size()); for (auto fieldType : fieldTypes) { @@ -14,12 +14,12 @@ StructAuxiliaryBuffer::StructAuxiliaryBuffer( } } -ListAuxiliaryBuffer::ListAuxiliaryBuffer( - const LogicalType& dataVectorType, storage::MemoryManager* memoryManager) - : capacity{DEFAULT_VECTOR_CAPACITY}, size{0}, dataVector{std::make_shared( - dataVectorType, memoryManager)} {} +ListAuxiliaryBuffer::ListAuxiliaryBuffer(const LogicalType& dataVectorType, + storage::MemoryManager* memoryManager) + : capacity{DEFAULT_VECTOR_CAPACITY}, size{0}, + dataVector{std::make_shared(dataVectorType, memoryManager)} {} -list_entry_t ListAuxiliaryBuffer::addList(uint64_t listSize) { +list_entry_t ListAuxiliaryBuffer::addList(list_size_t listSize) { auto listEntry = list_entry_t{size, listSize}; bool needResizeDataVector = size + listSize > capacity; while (size + listSize > capacity) { @@ -52,7 +52,8 @@ void ListAuxiliaryBuffer::resizeDataVector(ValueVector* dataVector) { auto buffer = std::make_unique(capacity * dataVector->getNumBytesPerValue()); memcpy(buffer.get(), dataVector->valueBuffer.get(), size * dataVector->getNumBytesPerValue()); dataVector->valueBuffer = std::move(buffer); - dataVector->nullMask->resize(capacity); + dataVector->nullMask->resize((capacity + NullMask::NUM_BITS_PER_NULL_ENTRY - 1) >> + NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2); // If the dataVector is a struct vector, we need to resize its field vectors. if (dataVector->dataType.getPhysicalType() == PhysicalTypeID::STRUCT) { resizeStructDataVector(dataVector); @@ -71,16 +72,15 @@ void ListAuxiliaryBuffer::resizeStructDataVector(ValueVector* dataVector) { } } -std::unique_ptr AuxiliaryBufferFactory::getAuxiliaryBuffer( - LogicalType& type, storage::MemoryManager* memoryManager) { +std::unique_ptr AuxiliaryBufferFactory::getAuxiliaryBuffer(LogicalType& type, + storage::MemoryManager* memoryManager) { switch (type.getPhysicalType()) { case PhysicalTypeID::STRING: return std::make_unique(memoryManager); case PhysicalTypeID::STRUCT: return std::make_unique(type, memoryManager); - case PhysicalTypeID::VAR_LIST: - return std::make_unique( - *VarListType::getChildType(&type), memoryManager); + case PhysicalTypeID::LIST: + return std::make_unique(*ListType::getChildType(&type), memoryManager); default: return nullptr; } diff --git a/src/common/vector/value_vector.cpp b/src/common/vector/value_vector.cpp index ef06921fd6b..78491f972e1 100644 --- a/src/common/vector/value_vector.cpp +++ b/src/common/vector/value_vector.cpp @@ -12,6 +12,13 @@ namespace common { ValueVector::ValueVector(LogicalType dataType, storage::MemoryManager* memoryManager) : dataType{std::move(dataType)} { + if (this->dataType.getLogicalTypeID() == LogicalTypeID::ANY) { + // LCOV_EXCL_START + // Alternatively we can assign + throw RuntimeException("Trying to a create a vector with ANY type. This should not happen. " + "Data type is expected to be resolved during binding."); + // LCOV_EXCL_STOP + } numBytesPerValue = getDataTypeSize(this->dataType); initializeValueBuffer(); nullMask = std::make_unique(); @@ -34,11 +41,12 @@ bool ValueVector::discardNull(ValueVector& vector) { } else { auto selectedPos = 0u; if (vector.state->selVector->isUnfiltered()) { - vector.state->selVector->resetSelectorToValuePosBuffer(); + auto buffer = vector.state->selVector->getMultableBuffer(); for (auto i = 0u; i < vector.state->selVector->selectedSize; i++) { - vector.state->selVector->selectedPositions[selectedPos] = i; + buffer[selectedPos] = i; selectedPos += !vector.isNull(i); } + vector.state->selVector->setToFiltered(); } else { for (auto i = 0u; i < vector.state->selVector->selectedSize; i++) { auto pos = vector.state->selVector->selectedPositions[i]; @@ -52,8 +60,8 @@ bool ValueVector::discardNull(ValueVector& vector) { } bool ValueVector::setNullFromBits(const uint64_t* srcNullEntries, uint64_t srcOffset, - uint64_t dstOffset, uint64_t numBitsToCopy) { - return nullMask->copyFromNullBits(srcNullEntries, srcOffset, dstOffset, numBitsToCopy); + uint64_t dstOffset, uint64_t numBitsToCopy, bool invert) { + return nullMask->copyFromNullBits(srcNullEntries, srcOffset, dstOffset, numBitsToCopy, invert); } template @@ -66,7 +74,7 @@ void ValueVector::copyFromRowData(uint32_t pos, const uint8_t* rowData) { case PhysicalTypeID::STRUCT: { StructVector::copyFromRowData(this, pos, rowData); } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { ListVector::copyFromRowData(this, pos, rowData); } break; case PhysicalTypeID::STRING: { @@ -79,13 +87,13 @@ void ValueVector::copyFromRowData(uint32_t pos, const uint8_t* rowData) { } } -void ValueVector::copyToRowData( - uint32_t pos, uint8_t* rowData, InMemOverflowBuffer* rowOverflowBuffer) const { +void ValueVector::copyToRowData(uint32_t pos, uint8_t* rowData, + InMemOverflowBuffer* rowOverflowBuffer) const { switch (dataType.getPhysicalType()) { case PhysicalTypeID::STRUCT: { StructVector::copyToRowData(this, pos, rowData, rowOverflowBuffer); } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { ListVector::copyToRowData(this, pos, rowData, rowOverflowBuffer); } break; case PhysicalTypeID::STRING: { @@ -98,14 +106,14 @@ void ValueVector::copyToRowData( } } -void ValueVector::copyFromVectorData( - uint8_t* dstData, const ValueVector* srcVector, const uint8_t* srcVectorData) { +void ValueVector::copyFromVectorData(uint8_t* dstData, const ValueVector* srcVector, + const uint8_t* srcVectorData) { KU_ASSERT(srcVector->dataType.getPhysicalType() == dataType.getPhysicalType()); switch (srcVector->dataType.getPhysicalType()) { case PhysicalTypeID::STRUCT: { StructVector::copyFromVectorData(this, dstData, srcVector, srcVectorData); } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { ListVector::copyFromVectorData(this, dstData, srcVector, srcVectorData); } break; case PhysicalTypeID::STRING: { @@ -117,8 +125,8 @@ void ValueVector::copyFromVectorData( } } -void ValueVector::copyFromVectorData( - uint64_t dstPos, const ValueVector* srcVector, uint64_t srcPos) { +void ValueVector::copyFromVectorData(uint64_t dstPos, const ValueVector* srcVector, + uint64_t srcPos) { setNull(dstPos, srcVector->isNull(srcPos)); if (!isNull(dstPos)) { copyFromVectorData(getData() + dstPos * getNumBytesPerValue(), srcVector, @@ -174,10 +182,10 @@ void ValueVector::copyFromValue(uint64_t pos, const Value& value) { memcpy(dstValue, &value.val.intervalVal, numBytesPerValue); } break; case PhysicalTypeID::STRING: { - StringVector::addString( - this, *(ku_string_t*)dstValue, value.strVal.data(), value.strVal.length()); + StringVector::addString(this, *(ku_string_t*)dstValue, value.strVal.data(), + value.strVal.length()); } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { auto listEntry = reinterpret_cast(dstValue); auto numValues = NestedVal::getChildrenSize(&value); *listEntry = ListVector::addList(this, numValues); @@ -186,39 +194,9 @@ void ValueVector::copyFromValue(uint64_t pos, const Value& value) { auto childVal = NestedVal::getChildVal(&value, i); dstDataVector->setNull(listEntry->offset + i, childVal->isNull()); if (!childVal->isNull()) { - dstDataVector->copyFromValue( - listEntry->offset + i, *NestedVal::getChildVal(&value, i)); - } - } - } break; - case PhysicalTypeID::FIXED_LIST: { - auto numValues = NestedVal::getChildrenSize(&value); - auto childType = FixedListType::getChildType(value.getDataType()); - auto numBytesPerChildValue = getDataTypeSize(*childType); - auto bufferToWrite = valueBuffer.get() + pos * numBytesPerValue; - for (auto i = 0u; i < numValues; i++) { - auto val = NestedVal::getChildVal(&value, i); - switch (childType->getPhysicalType()) { - case PhysicalTypeID::INT64: { - memcpy(bufferToWrite, &val->getValueReference(), numBytesPerChildValue); - } break; - case PhysicalTypeID::INT32: { - memcpy(bufferToWrite, &val->getValueReference(), numBytesPerChildValue); - } break; - case PhysicalTypeID::INT16: { - memcpy(bufferToWrite, &val->getValueReference(), numBytesPerChildValue); - } break; - case PhysicalTypeID::DOUBLE: { - memcpy(bufferToWrite, &val->getValueReference(), numBytesPerChildValue); - } break; - case PhysicalTypeID::FLOAT: { - memcpy(bufferToWrite, &val->getValueReference(), numBytesPerChildValue); - } break; - default: { - KU_UNREACHABLE; - } + dstDataVector->copyFromValue(listEntry->offset + i, + *NestedVal::getChildVal(&value, i)); } - bufferToWrite += numBytesPerChildValue; } } break; case PhysicalTypeID::STRUCT: { @@ -233,7 +211,7 @@ void ValueVector::copyFromValue(uint64_t pos, const Value& value) { } } -std::unique_ptr ValueVector::getAsValue(uint64_t pos) { +std::unique_ptr ValueVector::getAsValue(uint64_t pos) const { if (isNull(pos)) { return Value::createNullValue(dataType).copy(); } @@ -281,7 +259,7 @@ std::unique_ptr ValueVector::getAsValue(uint64_t pos) { case PhysicalTypeID::STRING: { value->strVal = getValue(pos).getAsString(); } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { auto dataVector = ListVector::getDataVector(this); auto listEntry = getValue(pos); std::vector> children; @@ -292,33 +270,6 @@ std::unique_ptr ValueVector::getAsValue(uint64_t pos) { value->childrenSize = children.size(); value->children = std::move(children); } break; - case PhysicalTypeID::FIXED_LIST: { - auto childDataType = FixedListType::getChildType(&dataType); - auto numElements = FixedListType::getNumValuesInList(&dataType); - std::vector> children; - children.reserve(numElements); - switch (childDataType->getPhysicalType()) { - case PhysicalTypeID::INT64: { - FixedListVector::getAsValue(this, children, pos, numElements); - } break; - case PhysicalTypeID::INT32: { - FixedListVector::getAsValue(this, children, pos, numElements); - } break; - case PhysicalTypeID::INT16: { - FixedListVector::getAsValue(this, children, pos, numElements); - } break; - case PhysicalTypeID::DOUBLE: { - FixedListVector::getAsValue(this, children, pos, numElements); - } break; - case PhysicalTypeID::FLOAT: { - FixedListVector::getAsValue(this, children, pos, numElements); - } break; - default: - KU_UNREACHABLE; - } - value->childrenSize = numElements; - value->children = std::move(children); - } break; case PhysicalTypeID::STRUCT: { auto& fieldVectors = StructVector::getFieldVectors(this); std::vector> children; @@ -343,7 +294,7 @@ void ValueVector::resetAuxiliaryBuffer() { ->resetOverflowBuffer(); return; } - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { auto listAuxiliaryBuffer = ku_dynamic_cast(auxiliaryBuffer.get()); listAuxiliaryBuffer->resetSize(); @@ -368,14 +319,10 @@ uint32_t ValueVector::getDataTypeSize(const LogicalType& type) { case PhysicalTypeID::STRING: { return sizeof(ku_string_t); } - case PhysicalTypeID::FIXED_LIST: { - return getDataTypeSize(*FixedListType::getChildType(&type)) * - FixedListType::getNumValuesInList(&type); - } case PhysicalTypeID::STRUCT: { return sizeof(struct_entry_t); } - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { return sizeof(list_entry_t); } default: { @@ -423,6 +370,10 @@ template<> void ValueVector::setValue(uint32_t pos, std::string val) { StringVector::addString(this, pos, val.data(), val.length()); } +template<> +void ValueVector::setValue(uint32_t pos, std::string_view val) { + StringVector::addString(this, pos, val.data(), val.length()); +} void ValueVector::setNull(uint32_t pos, bool isNull) { nullMask->setNull(pos, isNull); @@ -448,8 +399,8 @@ void StringVector::addString(ValueVector* vector, uint32_t vectorPos, ku_string_ } } -void StringVector::addString( - ValueVector* vector, uint32_t vectorPos, const char* srcStr, uint64_t length) { +void StringVector::addString(ValueVector* vector, uint32_t vectorPos, const char* srcStr, + uint64_t length) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); auto stringBuffer = ku_dynamic_cast(vector->auxiliaryBuffer.get()); @@ -485,6 +436,16 @@ ku_string_t& StringVector::reserveString(ValueVector* vector, uint32_t vectorPos return dstStr; } +void StringVector::reserveString(ValueVector* vector, ku_string_t& dstStr, uint64_t length) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); + auto stringBuffer = + ku_dynamic_cast(vector->auxiliaryBuffer.get()); + dstStr.len = length; + if (!ku_string_t::isShortString(length)) { + dstStr.overflowPtr = reinterpret_cast(stringBuffer->allocateOverflow(length)); + } +} + void StringVector::addString(ValueVector* vector, ku_string_t& dstStr, ku_string_t& srcStr) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); auto stringBuffer = @@ -504,8 +465,8 @@ void StringVector::addString(ValueVector* vector, ku_string_t& dstStr, ku_string } } -void StringVector::addString( - ValueVector* vector, ku_string_t& dstStr, const char* srcStr, uint64_t length) { +void StringVector::addString(ValueVector* vector, ku_string_t& dstStr, const char* srcStr, + uint64_t length) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); auto stringBuffer = ku_dynamic_cast(vector->auxiliaryBuffer.get()); @@ -524,8 +485,8 @@ void StringVector::addString( } } -void StringVector::addString( - kuzu::common::ValueVector* vector, ku_string_t& dstStr, const std::string& srcStr) { +void StringVector::addString(kuzu::common::ValueVector* vector, ku_string_t& dstStr, + const std::string& srcStr) { addString(vector, dstStr, srcStr.data(), srcStr.length()); } @@ -543,7 +504,7 @@ void StringVector::copyToRowData(const ValueVector* vector, uint32_t pos, uint8_ } void ListVector::copyFromRowData(ValueVector* vector, uint32_t pos, const uint8_t* rowData) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); auto& srcKuList = *(ku_list_t*)rowData; auto srcNullBytes = reinterpret_cast(srcKuList.overflowPtr); auto srcListValues = srcNullBytes + NullBuffer::getNumBytesForNullValues(srcKuList.size); @@ -580,8 +541,8 @@ void ListVector::copyToRowData(const ValueVector* vector, uint32_t pos, uint8_t* if (srcListDataVector->isNull(srcListEntry.offset + i)) { NullBuffer::setNull(dstListOverflow, i); } else { - srcListDataVector->copyToRowData( - srcListEntry.offset + i, dstListValues, rowOverflowBuffer); + srcListDataVector->copyToRowData(srcListEntry.offset + i, dstListValues, + rowOverflowBuffer); } dstListValues += dataRowLayoutSize; } @@ -620,57 +581,6 @@ void ListVector::sliceDataVector(ValueVector* vectorToSlice, uint64_t offset, ui } } -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements) { - for (auto i = 0u; i < numElements; ++i) { - children.push_back(Value::createDefaultValue(LogicalType{LogicalTypeID::INT64}).copy()); - children[i]->val.int64Val = - reinterpret_cast(vector->getData() + vector->getNumBytesPerValue() * pos)[i]; - } -} - -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements) { - for (auto i = 0u; i < numElements; ++i) { - children.push_back(Value::createDefaultValue(LogicalType{LogicalTypeID::INT32}).copy()); - children[i]->val.int32Val = - reinterpret_cast(vector->getData() + vector->getNumBytesPerValue() * pos)[i]; - } -} - -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements) { - for (auto i = 0u; i < numElements; ++i) { - children.push_back(Value::createDefaultValue(LogicalType{LogicalTypeID::INT16}).copy()); - children[i]->val.int16Val = - reinterpret_cast(vector->getData() + vector->getNumBytesPerValue() * pos)[i]; - } -} - -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements) { - for (auto i = 0u; i < numElements; ++i) { - children.push_back(Value::createDefaultValue(LogicalType{LogicalTypeID::FLOAT}).copy()); - children[i]->val.floatVal = - reinterpret_cast(vector->getData() + vector->getNumBytesPerValue() * pos)[i]; - } -} - -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements) { - // default: int64 - for (auto i = 0u; i < numElements; ++i) { - children.push_back(Value::createDefaultValue(LogicalType{LogicalTypeID::DOUBLE}).copy()); - children[i]->val.doubleVal = - reinterpret_cast(vector->getData() + vector->getNumBytesPerValue() * pos)[i]; - } -} - void StructVector::copyFromRowData(ValueVector* vector, uint32_t pos, const uint8_t* rowData) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRUCT); auto& structFields = getFieldVectors(vector); @@ -724,8 +634,8 @@ void RdfVariantVector::addString(ValueVector* vector, sel_t pos, ku_string_t str addString(vector, pos, (const char*)str.getData(), str.len); } -void RdfVariantVector::addString( - ValueVector* vector, common::sel_t pos, const char* str, uint32_t length) { +void RdfVariantVector::addString(ValueVector* vector, common::sel_t pos, const char* str, + uint32_t length) { auto typeVector = StructVector::getFieldVector(vector, 0).get(); auto valVector = StructVector::getFieldVector(vector, 1).get(); typeVector->setValue(pos, static_cast(LogicalTypeID::STRING)); diff --git a/src/expression_evaluator/case_evaluator.cpp b/src/expression_evaluator/case_evaluator.cpp index 24c622d28ac..40ef2db71de 100644 --- a/src/expression_evaluator/case_evaluator.cpp +++ b/src/expression_evaluator/case_evaluator.cpp @@ -12,7 +12,7 @@ void CaseAlternativeEvaluator::init(const ResultSet& resultSet, MemoryManager* m whenEvaluator->init(resultSet, memoryManager); thenEvaluator->init(resultSet, memoryManager); whenSelVector = std::make_unique(DEFAULT_VECTOR_CAPACITY); - whenSelVector->resetSelectorToValuePosBuffer(); + whenSelVector->setToFiltered(); } void CaseExpressionEvaluator::init(const ResultSet& resultSet, MemoryManager* memoryManager) { @@ -51,7 +51,7 @@ bool CaseExpressionEvaluator::select(SelectionVector& selVector, ClientContext* evaluate(clientContext); KU_ASSERT(resultVector->state->selVector->selectedSize == selVector.selectedSize); auto numSelectedValues = 0u; - auto selectedPosBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPosBuffer = selVector.getMultableBuffer(); for (auto i = 0u; i < selVector.selectedSize; ++i) { auto selVectorPos = selVector.selectedPositions[i]; auto resultVectorPos = resultVector->state->selVector->selectedPositions[i]; @@ -68,12 +68,12 @@ std::unique_ptr CaseExpressionEvaluator::clone() { for (auto& alternative : alternativeEvaluators) { clonedAlternativeEvaluators.push_back(alternative->clone()); } - return make_unique( - expression, std::move(clonedAlternativeEvaluators), elseEvaluator->clone()); + return make_unique(expression, std::move(clonedAlternativeEvaluators), + elseEvaluator->clone()); } -void CaseExpressionEvaluator::resolveResultVector( - const ResultSet& /*resultSet*/, MemoryManager* memoryManager) { +void CaseExpressionEvaluator::resolveResultVector(const ResultSet& /*resultSet*/, + MemoryManager* memoryManager) { resultVector = std::make_shared(expression->dataType, memoryManager); std::vector inputEvaluators; for (auto& alternative : alternativeEvaluators) { @@ -84,8 +84,8 @@ void CaseExpressionEvaluator::resolveResultVector( resolveResultStateFromChildren(inputEvaluators); } -void CaseExpressionEvaluator::fillSelected( - const SelectionVector& selVector, ValueVector* srcVector) { +void CaseExpressionEvaluator::fillSelected(const SelectionVector& selVector, + ValueVector* srcVector) { for (auto i = 0u; i < selVector.selectedSize; ++i) { auto resultPos = selVector.selectedPositions[i]; fillEntry(resultPos, srcVector); diff --git a/src/expression_evaluator/expression_evaluator.cpp b/src/expression_evaluator/expression_evaluator.cpp index 2f205be1f71..97349f01487 100644 --- a/src/expression_evaluator/expression_evaluator.cpp +++ b/src/expression_evaluator/expression_evaluator.cpp @@ -5,8 +5,8 @@ using namespace kuzu::common; namespace kuzu { namespace evaluator { -void ExpressionEvaluator::init( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) { +void ExpressionEvaluator::init(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) { for (auto& child : children) { child->init(resultSet, memoryManager); } diff --git a/src/expression_evaluator/function_evaluator.cpp b/src/expression_evaluator/function_evaluator.cpp index f6664e44d99..95d1c1fb23d 100644 --- a/src/expression_evaluator/function_evaluator.cpp +++ b/src/expression_evaluator/function_evaluator.cpp @@ -1,6 +1,7 @@ #include "expression_evaluator/function_evaluator.h" #include "binder/expression/function_expression.h" +#include "function/cast/vector_cast_functions.h" using namespace kuzu::common; using namespace kuzu::processor; @@ -24,7 +25,7 @@ void FunctionExpressionEvaluator::evaluate(ClientContext* clientContext) { } auto expr = ku_dynamic_cast(expression.get()); - if (expr->getFunctionName() == CAST_FUNC_NAME) { + if (expr->getFunctionName() == function::CastAnyFunction::name) { execFunc(parameters, *resultVector, expr->getBindData()); return; } @@ -33,8 +34,8 @@ void FunctionExpressionEvaluator::evaluate(ClientContext* clientContext) { } } -bool FunctionExpressionEvaluator::select( - SelectionVector& selVector, ClientContext* /*ClientContext*/) { +bool FunctionExpressionEvaluator::select(SelectionVector& selVector, + ClientContext* /*ClientContext*/) { for (auto& child : children) { child->evaluate(nullptr); } @@ -46,7 +47,7 @@ bool FunctionExpressionEvaluator::select( auto numSelectedValues = 0u; for (auto i = 0u; i < resultVector->state->selVector->selectedSize; ++i) { auto pos = resultVector->state->selVector->selectedPositions[i]; - auto selectedPosBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPosBuffer = selVector.getMultableBuffer(); selectedPosBuffer[numSelectedValues] = pos; numSelectedValues += resultVector->getValue(pos); } @@ -65,8 +66,8 @@ std::unique_ptr FunctionExpressionEvaluator::clone() { return make_unique(expression, std::move(clonedChildren)); } -void FunctionExpressionEvaluator::resolveResultVector( - const ResultSet& /*resultSet*/, MemoryManager* memoryManager) { +void FunctionExpressionEvaluator::resolveResultVector(const ResultSet& /*resultSet*/, + MemoryManager* memoryManager) { resultVector = std::make_shared(expression->dataType, memoryManager); std::vector inputEvaluators; inputEvaluators.reserve(children.size()); diff --git a/src/expression_evaluator/literal_evaluator.cpp b/src/expression_evaluator/literal_evaluator.cpp index 34ef154c907..b94b7146298 100644 --- a/src/expression_evaluator/literal_evaluator.cpp +++ b/src/expression_evaluator/literal_evaluator.cpp @@ -9,16 +9,16 @@ using namespace kuzu::main; namespace kuzu { namespace evaluator { -bool LiteralExpressionEvaluator::select( - SelectionVector& /*selVector*/, ClientContext* /*clientContext*/) { +bool LiteralExpressionEvaluator::select(SelectionVector& /*selVector*/, + ClientContext* /*clientContext*/) { KU_ASSERT(resultVector->dataType.getLogicalTypeID() == LogicalTypeID::BOOL); auto pos = resultVector->state->selVector->selectedPositions[0]; KU_ASSERT(pos == 0u); return resultVector->getValue(pos) && (!resultVector->isNull(pos)); } -void LiteralExpressionEvaluator::resolveResultVector( - const processor::ResultSet& /*resultSet*/, MemoryManager* memoryManager) { +void LiteralExpressionEvaluator::resolveResultVector(const processor::ResultSet& /*resultSet*/, + MemoryManager* memoryManager) { resultVector = std::make_shared(*value->getDataType(), memoryManager); resultVector->setState(DataChunkState::getSingleValueDataChunkState()); if (value->isNull()) { diff --git a/src/expression_evaluator/node_rel_evaluator.cpp b/src/expression_evaluator/node_rel_evaluator.cpp index 59dddd658de..27324e724f7 100644 --- a/src/expression_evaluator/node_rel_evaluator.cpp +++ b/src/expression_evaluator/node_rel_evaluator.cpp @@ -24,8 +24,8 @@ void NodeRelExpressionEvaluator::evaluate(ClientContext* clientContext) { } } -void NodeRelExpressionEvaluator::resolveResultVector( - const processor::ResultSet& /*resultSet*/, storage::MemoryManager* memoryManager) { +void NodeRelExpressionEvaluator::resolveResultVector(const processor::ResultSet& /*resultSet*/, + storage::MemoryManager* memoryManager) { resultVector = std::make_shared(nodeOrRel->getDataType(), memoryManager); std::vector inputEvaluators; inputEvaluators.reserve(children.size()); diff --git a/src/expression_evaluator/path_evaluator.cpp b/src/expression_evaluator/path_evaluator.cpp index 87a7a298157..baa514c083d 100644 --- a/src/expression_evaluator/path_evaluator.cpp +++ b/src/expression_evaluator/path_evaluator.cpp @@ -12,8 +12,8 @@ namespace kuzu { namespace evaluator { // For each result field vector, find its corresponding input field vector if exist. -static std::vector getFieldVectors( - const LogicalType& inputType, const LogicalType& resultType, ValueVector* inputVector) { +static std::vector getFieldVectors(const LogicalType& inputType, + const LogicalType& resultType, ValueVector* inputVector) { std::vector result; for (auto field : StructType::getFields(&resultType)) { auto fieldName = StringUtils::getUpper(field->getName()); @@ -27,8 +27,8 @@ static std::vector getFieldVectors( return result; } -void PathExpressionEvaluator::init( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) { +void PathExpressionEvaluator::init(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) { ExpressionEvaluator::init(resultSet, memoryManager); auto resultNodesIdx = StructType::getFieldIdx(&resultVector->dataType, InternalKeyword::NODES); resultNodesVector = StructVector::getFieldVector(resultVector.get(), resultNodesIdx).get(); @@ -63,14 +63,14 @@ void PathExpressionEvaluator::init( auto nodeFieldIdx = StructType::getFieldIdx(&child->dataType, InternalKeyword::NODES); vectors->nodesInput = StructVector::getFieldVector(vectors->input, nodeFieldIdx).get(); vectors->nodesDataInput = ListVector::getDataVector(vectors->nodesInput); - vectors->nodeFieldVectors = getFieldVectors( - recursiveNode->dataType, *pathExpression->getNodeType(), vectors->nodesDataInput); + vectors->nodeFieldVectors = getFieldVectors(recursiveNode->dataType, + *pathExpression->getNodeType(), vectors->nodesDataInput); auto relFieldIdx = StructType::getFieldIdx(&vectors->input->dataType, InternalKeyword::RELS); vectors->relsInput = StructVector::getFieldVector(vectors->input, relFieldIdx).get(); vectors->relsDataInput = ListVector::getDataVector(vectors->relsInput); - vectors->relFieldVectors = getFieldVectors( - recursiveRel->dataType, *pathExpression->getRelType(), vectors->relsDataInput); + vectors->relFieldVectors = getFieldVectors(recursiveRel->dataType, + *pathExpression->getRelType(), vectors->relsDataInput); } break; default: KU_UNREACHABLE; @@ -132,8 +132,8 @@ void PathExpressionEvaluator::copyNodes(sel_t resultPos, bool isEmptyRels) { auto inputPos = getCurrentPos(vectors->input, resultPos); switch (child->dataType.getLogicalTypeID()) { case LogicalTypeID::NODE: { - copyFieldVectors( - inputPos, vectors->nodeFieldVectors, resultDataPos, resultNodesFieldVectors); + copyFieldVectors(inputPos, vectors->nodeFieldVectors, resultDataPos, + resultNodesFieldVectors); } break; case LogicalTypeID::RECURSIVE_REL: { auto& listEntry = vectors->nodesInput->getValue(inputPos); @@ -177,8 +177,8 @@ uint64_t PathExpressionEvaluator::copyRels(sel_t resultPos) { auto inputPos = getCurrentPos(vectors->input, resultPos); switch (child->dataType.getLogicalTypeID()) { case LogicalTypeID::REL: { - copyFieldVectors( - inputPos, vectors->relFieldVectors, resultDataPos, resultRelsFieldVectors); + copyFieldVectors(inputPos, vectors->relFieldVectors, resultDataPos, + resultRelsFieldVectors); } break; case LogicalTypeID::RECURSIVE_REL: { auto& listEntry = vectors->relsInput->getValue(inputPos); @@ -212,8 +212,8 @@ void PathExpressionEvaluator::copyFieldVectors(offset_t inputVectorPos, resultVectorPos++; } -void PathExpressionEvaluator::resolveResultVector( - const processor::ResultSet& /*resultSet*/, storage::MemoryManager* memoryManager) { +void PathExpressionEvaluator::resolveResultVector(const processor::ResultSet& /*resultSet*/, + storage::MemoryManager* memoryManager) { resultVector = std::make_shared(expression->getDataType(), memoryManager); std::vector inputEvaluators; inputEvaluators.reserve(children.size()); diff --git a/src/expression_evaluator/reference_evaluator.cpp b/src/expression_evaluator/reference_evaluator.cpp index 6b863a5a621..2a52d633d27 100644 --- a/src/expression_evaluator/reference_evaluator.cpp +++ b/src/expression_evaluator/reference_evaluator.cpp @@ -11,10 +11,10 @@ inline static bool isTrue(ValueVector& vector, uint64_t pos) { return !vector.isNull(pos) && vector.getValue(pos); } -bool ReferenceExpressionEvaluator::select( - SelectionVector& selVector, ClientContext* /*clientContext*/) { +bool ReferenceExpressionEvaluator::select(SelectionVector& selVector, + ClientContext* /*clientContext*/) { uint64_t numSelectedValues = 0; - auto selectedBuffer = resultVector->state->selVector->getSelectedPositionsBuffer(); + auto selectedBuffer = resultVector->state->selVector->getMultableBuffer(); if (resultVector->state->selVector->isUnfiltered()) { for (auto i = 0u; i < resultVector->state->selVector->selectedSize; i++) { selectedBuffer[numSelectedValues] = i; diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp index f6abb8f621d..7838c419098 100644 --- a/src/extension/extension.cpp +++ b/src/extension/extension.cpp @@ -35,8 +35,8 @@ std::string getPlatform() { return getOS() + "_" + getArch(); } -std::string ExtensionUtils::getExtensionPath( - const std::string& extensionDir, const std::string& name) { +std::string ExtensionUtils::getExtensionPath(const std::string& extensionDir, + const std::string& name) { return common::stringFormat("{}/lib{}.kuzu_extension", extensionDir, name); } @@ -56,8 +56,8 @@ ExtensionRepoInfo ExtensionUtils::getExtensionRepoInfo(const std::string& extens return {hostPath, hostURL, extensionURL}; } -void ExtensionOptions::addExtensionOption( - std::string name, common::LogicalTypeID type, common::Value defaultValue) { +void ExtensionOptions::addExtensionOption(std::string name, common::LogicalTypeID type, + common::Value defaultValue) { common::StringUtils::toLower(name); extensionOptions.emplace(name, main::ExtensionOption{name, type, std::move(defaultValue)}); } @@ -67,9 +67,5 @@ main::ExtensionOption* ExtensionOptions::getExtensionOption(std::string name) { return extensionOptions.contains(name) ? &extensionOptions.at(name) : nullptr; } -std::unordered_map& ExtensionOptions::getExtensionOptions() { - return extensionOptions; -} - } // namespace extension } // namespace kuzu diff --git a/src/function/CMakeLists.txt b/src/function/CMakeLists.txt index e7315706c84..f782566ac1c 100644 --- a/src/function/CMakeLists.txt +++ b/src/function/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(aggregate) add_subdirectory(arithmetic) add_subdirectory(cast) +add_subdirectory(pattern) add_subdirectory(table) add_library(kuzu_function @@ -12,8 +13,10 @@ add_library(kuzu_function cast_from_string_functions.cpp comparison_functions.cpp find_function.cpp + function_collection.cpp scalar_macro_function.cpp vector_arithmetic_functions.cpp + vector_array_functions.cpp vector_boolean_functions.cpp vector_cast_functions.cpp vector_date_functions.cpp diff --git a/src/function/aggregate/CMakeLists.txt b/src/function/aggregate/CMakeLists.txt index 23afd10af8e..5345162fe71 100644 --- a/src/function/aggregate/CMakeLists.txt +++ b/src/function/aggregate/CMakeLists.txt @@ -1,6 +1,8 @@ add_library(kuzu_function_aggregate OBJECT - count.cpp) + count.cpp + count_star.cpp + collect.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/function/aggregate/collect.cpp b/src/function/aggregate/collect.cpp new file mode 100644 index 00000000000..184398367b4 --- /dev/null +++ b/src/function/aggregate/collect.cpp @@ -0,0 +1,99 @@ +#include "function/aggregate/collect.h" + +#include "storage/storage_utils.h" + +using namespace kuzu::binder; +using namespace kuzu::common; +using namespace kuzu::storage; +using namespace kuzu::processor; + +namespace kuzu { +namespace function { + +std::unique_ptr CollectFunction::initialize() { + return std::make_unique(); +} + +void CollectFunction::updateAll(uint8_t* state_, ValueVector* input, uint64_t multiplicity, + MemoryManager* memoryManager) { + KU_ASSERT(!input->state->isFlat()); + auto state = reinterpret_cast(state_); + if (input->hasNoNullsGuarantee()) { + for (auto i = 0u; i < input->state->selVector->selectedSize; ++i) { + auto pos = input->state->selVector->selectedPositions[i]; + updateSingleValue(state, input, pos, multiplicity, memoryManager); + } + } else { + for (auto i = 0u; i < input->state->selVector->selectedSize; ++i) { + auto pos = input->state->selVector->selectedPositions[i]; + if (!input->isNull(pos)) { + updateSingleValue(state, input, pos, multiplicity, memoryManager); + } + } + } +} + +void CollectFunction::updatePos(uint8_t* state_, ValueVector* input, uint64_t multiplicity, + uint32_t pos, MemoryManager* memoryManager) { + auto state = reinterpret_cast(state_); + updateSingleValue(state, input, pos, multiplicity, memoryManager); +} + +void CollectFunction::initCollectStateIfNecessary(CollectState* state, MemoryManager* memoryManager, + LogicalType& dataType) { + if (state->factorizedTable == nullptr) { + auto tableSchema = std::make_unique(); + tableSchema->appendColumn(std::make_unique(false /* isUnflat */, + 0 /* dataChunkPos */, StorageUtils::getDataTypeSize(dataType))); + state->factorizedTable = + std::make_unique(memoryManager, std::move(tableSchema)); + } +} + +void CollectFunction::updateSingleValue(CollectState* state, ValueVector* input, uint32_t pos, + uint64_t multiplicity, MemoryManager* memoryManager) { + initCollectStateIfNecessary(state, memoryManager, input->dataType); + for (auto i = 0u; i < multiplicity; ++i) { + auto tuple = state->factorizedTable->appendEmptyTuple(); + state->isNull = false; + input->copyToRowData(pos, tuple, state->factorizedTable->getInMemOverflowBuffer()); + } +} + +void CollectFunction::combine(uint8_t* state_, uint8_t* otherState_, + MemoryManager* /*memoryManager*/) { + auto otherState = reinterpret_cast(otherState_); + if (otherState->isNull) { + return; + } + auto state = reinterpret_cast(state_); + if (state->isNull) { + state->factorizedTable = std::move(otherState->factorizedTable); + state->isNull = false; + } else { + state->factorizedTable->merge(*otherState->factorizedTable); + } + otherState->factorizedTable.reset(); +} + +std::unique_ptr CollectFunction::bindFunc(const expression_vector& arguments, + Function* definition) { + KU_ASSERT(arguments.size() == 1); + auto aggFuncDefinition = reinterpret_cast(definition); + aggFuncDefinition->parameterTypeIDs[0] = arguments[0]->dataType.getLogicalTypeID(); + auto returnType = LogicalType::LIST(std::make_unique(arguments[0]->dataType)); + return std::make_unique(std::move(returnType)); +} + +function_set CollectFunction::getFunctionSet() { + function_set result; + for (auto isDistinct : std::vector{true, false}) { + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::ANY}, LogicalTypeID::LIST, initialize, + updateAll, updatePos, combine, finalize, isDistinct, bindFunc)); + } + return result; +} + +} // namespace function +} // namespace kuzu diff --git a/src/function/aggregate/count.cpp b/src/function/aggregate/count.cpp index 5658b7e3589..3c2ddf2529f 100644 --- a/src/function/aggregate/count.cpp +++ b/src/function/aggregate/count.cpp @@ -11,8 +11,8 @@ using namespace kuzu::binder; namespace kuzu { namespace function { -void CountFunction::updateAll( - uint8_t* state_, ValueVector* input, uint64_t multiplicity, MemoryManager* /*memoryManager*/) { +void CountFunction::updateAll(uint8_t* state_, ValueVector* input, uint64_t multiplicity, + MemoryManager* /*memoryManager*/) { auto state = reinterpret_cast(state_); if (input->hasNoNullsGuarantee()) { for (auto i = 0u; i < input->state->selVector->selectedSize; ++i) { @@ -39,5 +39,16 @@ void CountFunction::paramRewriteFunc(binder::expression_vector& arguments) { } } +function_set CountFunction::getFunctionSet() { + function_set result; + for (auto& type : LogicalTypeUtils::getAllValidLogicTypes()) { + for (auto isDistinct : std::vector{true, false}) { + result.push_back(AggregateFunctionUtil::getAggFunc(name, type, + LogicalTypeID::INT64, isDistinct, paramRewriteFunc)); + } + } + return result; +} + } // namespace function } // namespace kuzu diff --git a/src/function/aggregate/count_star.cpp b/src/function/aggregate/count_star.cpp new file mode 100644 index 00000000000..e883f85f0e7 --- /dev/null +++ b/src/function/aggregate/count_star.cpp @@ -0,0 +1,33 @@ +#include "function/aggregate/count_star.h" + +using namespace kuzu::common; +using namespace kuzu::storage; + +namespace kuzu { +namespace function { + +void CountStarFunction::updateAll(uint8_t* state_, ValueVector* input, uint64_t multiplicity, + MemoryManager* /*memoryManager*/) { + auto state = reinterpret_cast(state_); + KU_ASSERT(input == nullptr); + (void)input; + state->count += multiplicity; +} + +void CountStarFunction::updatePos(uint8_t* state_, ValueVector* input, uint64_t multiplicity, + uint32_t /*pos*/, MemoryManager* /*memoryManager*/) { + auto state = reinterpret_cast(state_); + KU_ASSERT(input == nullptr); + (void)input; + state->count += multiplicity; +} + +function_set CountStarFunction::getFunctionSet() { + function_set result; + result.push_back(std::make_unique(name, std::vector{}, + LogicalTypeID::INT64, initialize, updateAll, updatePos, combine, finalize, false)); + return result; +} + +} // namespace function +} // namespace kuzu diff --git a/src/function/aggregate_function.cpp b/src/function/aggregate_function.cpp index 850a9ae0392..62fc00c91fe 100644 --- a/src/function/aggregate_function.cpp +++ b/src/function/aggregate_function.cpp @@ -16,8 +16,8 @@ std::unique_ptr AggregateFunctionUtil::getSumFunc(std::string common::LogicalTypeID inputType, common::LogicalTypeID resultType, bool isDistinct) { switch (inputType) { case common::LogicalTypeID::INT128: - return getAggFunc>( - std::move(name), inputType, resultType, isDistinct); + return getAggFunc>(std::move(name), inputType, resultType, + isDistinct); case common::LogicalTypeID::SERIAL: case common::LogicalTypeID::INT64: return getAggFunc>(name, inputType, resultType, isDistinct); @@ -48,8 +48,8 @@ std::unique_ptr AggregateFunctionUtil::getAvgFunc(std::string common::LogicalTypeID inputType, common::LogicalTypeID resultType, bool isDistinct) { switch (inputType) { case common::LogicalTypeID::INT128: - return getAggFunc>( - std::move(name), inputType, resultType, isDistinct); + return getAggFunc>(std::move(name), inputType, resultType, + isDistinct); case common::LogicalTypeID::SERIAL: case common::LogicalTypeID::INT64: return getAggFunc>(std::move(name), inputType, resultType, isDistinct); @@ -60,14 +60,14 @@ std::unique_ptr AggregateFunctionUtil::getAvgFunc(std::string case common::LogicalTypeID::INT8: return getAggFunc>(std::move(name), inputType, resultType, isDistinct); case common::LogicalTypeID::UINT64: - return getAggFunc>( - std::move(name), inputType, resultType, isDistinct); + return getAggFunc>(std::move(name), inputType, resultType, + isDistinct); case common::LogicalTypeID::UINT32: - return getAggFunc>( - std::move(name), inputType, resultType, isDistinct); + return getAggFunc>(std::move(name), inputType, resultType, + isDistinct); case common::LogicalTypeID::UINT16: - return getAggFunc>( - std::move(name), inputType, resultType, isDistinct); + return getAggFunc>(std::move(name), inputType, resultType, + isDistinct); case common::LogicalTypeID::UINT8: return getAggFunc>(std::move(name), inputType, resultType, isDistinct); case common::LogicalTypeID::DOUBLE: @@ -79,16 +79,16 @@ std::unique_ptr AggregateFunctionUtil::getAvgFunc(std::string } } -std::unique_ptr AggregateFunctionUtil::getMinFunc( - LogicalTypeID inputType, bool isDistinct) { - return AggregateFunctionUtil::getMinMaxFunction( - MIN_FUNC_NAME, inputType, inputType, isDistinct); +std::unique_ptr AggregateFunctionUtil::getMinFunc(LogicalTypeID inputType, + bool isDistinct) { + return AggregateFunctionUtil::getMinMaxFunction(AggregateMinFunction::name, inputType, + inputType, isDistinct); } -std::unique_ptr AggregateFunctionUtil::getMaxFunc( - LogicalTypeID inputType, bool isDistinct) { - return AggregateFunctionUtil::getMinMaxFunction( - MAX_FUNC_NAME, inputType, inputType, isDistinct); +std::unique_ptr AggregateFunctionUtil::getMaxFunc(LogicalTypeID inputType, + bool isDistinct) { + return AggregateFunctionUtil::getMinMaxFunction(AggregateMaxFunction::name, + inputType, inputType, isDistinct); } template @@ -185,5 +185,46 @@ std::unique_ptr AggregateFunctionUtil::getMinMaxFunction(std: } } +function_set AggregateSumFunction::getFunctionSet() { + function_set result; + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + for (auto isDistinct : std::vector{true, false}) { + result.push_back(AggregateFunctionUtil::getSumFunc(name, typeID, typeID, isDistinct)); + } + } + return result; +} + +function_set AggregateAvgFunction::getFunctionSet() { + function_set result; + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + for (auto isDistinct : std::vector{true, false}) { + result.push_back( + AggregateFunctionUtil::getAvgFunc(name, typeID, LogicalTypeID::DOUBLE, isDistinct)); + } + } + return result; +} + +function_set AggregateMinFunction::getFunctionSet() { + function_set result; + for (auto& type : LogicalTypeUtils::getAllValidComparableLogicalTypes()) { + for (auto isDistinct : std::vector{true, false}) { + result.push_back(AggregateFunctionUtil::getMinFunc(type, isDistinct)); + } + } + return result; +} + +function_set AggregateMaxFunction::getFunctionSet() { + function_set result; + for (auto& type : LogicalTypeUtils::getAllValidComparableLogicalTypes()) { + for (auto isDistinct : std::vector{true, false}) { + result.push_back(AggregateFunctionUtil::getMaxFunc(type, isDistinct)); + } + } + return result; +} + } // namespace function } // namespace kuzu diff --git a/src/function/arithmetic/subtract.cpp b/src/function/arithmetic/subtract.cpp index 88cefcbbf2c..62613c0fc02 100644 --- a/src/function/arithmetic/subtract.cpp +++ b/src/function/arithmetic/subtract.cpp @@ -10,8 +10,8 @@ namespace function { // reference from duckDB subtract.cpp template -static inline bool SubtractInPlaceWithOverflowCheck( - SRC_TYPE left, SRC_TYPE right, SRC_TYPE& result) { +static inline bool SubtractInPlaceWithOverflowCheck(SRC_TYPE left, SRC_TYPE right, + SRC_TYPE& result) { DST_TYPE uresult; uresult = static_cast(left) - static_cast(right); if (uresult < NumericLimits::minimum() || diff --git a/src/function/base_lower_upper_operation.cpp b/src/function/base_lower_upper_operation.cpp index 5c1aec00894..2f4cdd66969 100644 --- a/src/function/base_lower_upper_operation.cpp +++ b/src/function/base_lower_upper_operation.cpp @@ -39,22 +39,27 @@ uint32_t BaseLowerUpperFunction::getResultLen(char* inputStr, uint32_t inputLen, return outputLength; } +uint64_t BaseLowerUpperFunction::convertCharCase(char* result, const char* input, int32_t charPos, + bool toUpper) { + if (input[charPos] & 0x80) { + int size = 0u, newSize = 0u; + auto codepoint = utf8proc_codepoint(input + charPos, size); + KU_ASSERT(codepoint >= 0); // Validity ensured by getResultLen. + int convertedCodepoint = + toUpper ? utf8proc_toupper(codepoint) : utf8proc_tolower(codepoint); + utf8proc_codepoint_to_utf8(convertedCodepoint, newSize, result); + return size; + } else { + *result = toUpper ? toupper(input[charPos]) : tolower(input[charPos]); + return 1; + } +} + void BaseLowerUpperFunction::convertCase(char* result, uint32_t len, char* input, bool toUpper) { for (auto i = 0u; i < len;) { - if (input[i] & 0x80) { - int size = 0, newSize = 0; - int codepoint = utf8proc_codepoint(input + i, size); - KU_ASSERT(codepoint >= 0); // Validity ensured by getResultLen. - int convertedCodepoint = - toUpper ? utf8proc_toupper(codepoint) : utf8proc_tolower(codepoint); - utf8proc_codepoint_to_utf8(convertedCodepoint, newSize, result); - result += newSize; - i += size; - } else { - *result = toUpper ? toupper(input[i]) : tolower(input[i]); - i++; - result++; - } + auto charWidth = convertCharCase(result, input, i, toUpper); + i += charWidth; + result += charWidth; } } diff --git a/src/function/built_in_function_utils.cpp b/src/function/built_in_function_utils.cpp index 726fd1f0eb9..a43ef52d365 100644 --- a/src/function/built_in_function_utils.cpp +++ b/src/function/built_in_function_utils.cpp @@ -1,38 +1,13 @@ #include "function/built_in_function_utils.h" -#include "catalog/catalog_entry/aggregate_function_catalog_entry.h" -#include "catalog/catalog_entry/scalar_function_catalog_entry.h" -#include "catalog/catalog_entry/table_function_catalog_entry.h" +#include "catalog/catalog_entry/function_catalog_entry.h" #include "catalog/catalog_set.h" #include "common/exception/binder.h" #include "common/exception/catalog.h" -#include "function/aggregate/collect.h" -#include "function/aggregate/count.h" -#include "function/aggregate/count_star.h" #include "function/aggregate_function.h" #include "function/arithmetic/vector_arithmetic_functions.h" -#include "function/blob/vector_blob_functions.h" -#include "function/cast/vector_cast_functions.h" -#include "function/comparison/vector_comparison_functions.h" -#include "function/date/vector_date_functions.h" -#include "function/interval/vector_interval_functions.h" -#include "function/list/vector_list_functions.h" -#include "function/map/vector_map_functions.h" -#include "function/path/vector_path_functions.h" -#include "function/rdf/vector_rdf_functions.h" -#include "function/schema/vector_node_rel_functions.h" -#include "function/string/vector_string_functions.h" -#include "function/struct/vector_struct_functions.h" -#include "function/table/call_functions.h" -#include "function/timestamp/vector_timestamp_functions.h" -#include "function/union/vector_union_functions.h" -#include "function/uuid/vector_uuid_functions.h" -#include "processor/operator/persistent/reader/csv/parallel_csv_reader.h" -#include "processor/operator/persistent/reader/csv/serial_csv_reader.h" -#include "processor/operator/persistent/reader/npy/npy_reader.h" -#include "processor/operator/persistent/reader/parquet/parquet_reader.h" -#include "processor/operator/persistent/reader/rdf/rdf_scan.h" -#include "processor/operator/table_scan/ftable_scan_function.h" +#include "function/function_collection.h" +#include "function/scalar_function.h" using namespace kuzu::common; using namespace kuzu::catalog; @@ -41,39 +16,20 @@ using namespace kuzu::processor; namespace kuzu { namespace function { -void BuiltInFunctionsUtils::createFunctions(CatalogSet* catalogSet) { - registerScalarFunctions(catalogSet); - registerAggregateFunctions(catalogSet); - registerTableFunctions(catalogSet); -} +static void validateNonEmptyCandidateFunctions(std::vector& candidateFunctions, + const std::string& name, const std::vector& inputTypes, bool isDistinct, + function::function_set& set); +static void validateNonEmptyCandidateFunctions(std::vector& candidateFunctions, + const std::string& name, const std::vector& inputTypes, + function::function_set& set); -void BuiltInFunctionsUtils::registerScalarFunctions(CatalogSet* catalogSet) { - registerComparisonFunctions(catalogSet); - registerArithmeticFunctions(catalogSet); - registerDateFunctions(catalogSet); - registerTimestampFunctions(catalogSet); - registerIntervalFunctions(catalogSet); - registerStringFunctions(catalogSet); - registerCastFunctions(catalogSet); - registerListFunctions(catalogSet); - registerStructFunctions(catalogSet); - registerMapFunctions(catalogSet); - registerUnionFunctions(catalogSet); - registerNodeRelFunctions(catalogSet); - registerPathFunctions(catalogSet); - registerBlobFunctions(catalogSet); - registerUUIDFunctions(catalogSet); - registerRdfFunctions(catalogSet); -} - -void BuiltInFunctionsUtils::registerAggregateFunctions(CatalogSet* catalogSet) { - registerCountStar(catalogSet); - registerCount(catalogSet); - registerSum(catalogSet); - registerAvg(catalogSet); - registerMin(catalogSet); - registerMax(catalogSet); - registerCollect(catalogSet); +void BuiltInFunctionsUtils::createFunctions(CatalogSet* catalogSet) { + auto functions = FunctionCollection::getFunctions(); + for (auto i = 0u; functions[i].name != nullptr; ++i) { + auto functionSet = functions[i].getFunctionSetFunc(); + catalogSet->createEntry(std::make_unique( + functions[i].catalogEntryType, functions[i].name, std::move(functionSet))); + } } Function* BuiltInFunctionsUtils::matchFunction(const std::string& name, CatalogSet* catalogSet) { @@ -92,9 +48,6 @@ Function* BuiltInFunctionsUtils::matchFunction(const std::string& name, uint32_t minCost = UINT32_MAX; for (auto& function : functionSet) { auto func = reinterpret_cast(function.get()); - if (name == CAST_FUNC_NAME) { - return func; - } auto cost = getFunctionCost(inputTypes, func, isOverload); if (cost == UINT32_MAX) { continue; @@ -128,8 +81,8 @@ AggregateFunction* BuiltInFunctionsUtils::matchAggregateFunction(const std::stri } candidateFunctions.push_back(aggregateFunction); } - validateNonEmptyCandidateFunctions( - candidateFunctions, name, inputTypes, isDistinct, functionSet); + validateNonEmptyCandidateFunctions(candidateFunctions, name, inputTypes, isDistinct, + functionSet); KU_ASSERT(candidateFunctions.size() == 1); return candidateFunctions[0]; } @@ -206,8 +159,8 @@ uint32_t BuiltInFunctionsUtils::getTargetTypeCost(LogicalTypeID typeID) { return 149; case LogicalTypeID::STRUCT: case LogicalTypeID::MAP: - case LogicalTypeID::FIXED_LIST: - case LogicalTypeID::VAR_LIST: + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: case LogicalTypeID::UNION: return 160; case LogicalTypeID::RDF_VARIANT: @@ -401,8 +354,8 @@ uint32_t BuiltInFunctionsUtils::castFromString(LogicalTypeID inputTypeID) { uint32_t BuiltInFunctionsUtils::castFromRDFVariant(LogicalTypeID inputTypeID) { switch (inputTypeID) { case LogicalTypeID::STRUCT: - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: case LogicalTypeID::UNION: case LogicalTypeID::MAP: case LogicalTypeID::NODE: @@ -444,8 +397,8 @@ Function* BuiltInFunctionsUtils::getBestMatch(std::vector& functionsT return result; } -uint32_t BuiltInFunctionsUtils::getFunctionCost( - const std::vector& inputTypes, Function* function, bool isOverload) { +uint32_t BuiltInFunctionsUtils::getFunctionCost(const std::vector& inputTypes, + Function* function, bool isOverload) { switch (function->type) { case FunctionType::SCALAR: { auto scalarFunction = ku_dynamic_cast(function); @@ -456,15 +409,13 @@ uint32_t BuiltInFunctionsUtils::getFunctionCost( return matchParameters(inputTypes, function->parameterTypeIDs, isOverload); } } - case FunctionType::TABLE: - return matchParameters(inputTypes, function->parameterTypeIDs, isOverload); default: - KU_UNREACHABLE; + return matchParameters(inputTypes, function->parameterTypeIDs, isOverload); } } -uint32_t BuiltInFunctionsUtils::getAggregateFunctionCost( - const std::vector& inputTypes, bool isDistinct, AggregateFunction* function) { +uint32_t BuiltInFunctionsUtils::getAggregateFunctionCost(const std::vector& inputTypes, + bool isDistinct, AggregateFunction* function) { if (inputTypes.size() != function->parameterTypeIDs.size() || isDistinct != function->isDistinct) { return UINT32_MAX; @@ -495,8 +446,8 @@ uint32_t BuiltInFunctionsUtils::matchParameters(const std::vector& return cost; } -uint32_t BuiltInFunctionsUtils::matchVarLengthParameters( - const std::vector& inputTypes, LogicalTypeID targetTypeID, bool /*isOverload*/) { +uint32_t BuiltInFunctionsUtils::matchVarLengthParameters(const std::vector& inputTypes, + LogicalTypeID targetTypeID, bool /*isOverload*/) { auto cost = 0u; for (auto inputType : inputTypes) { auto castCost = getCastCost(inputType.getLogicalTypeID(), targetTypeID); @@ -512,7 +463,7 @@ void BuiltInFunctionsUtils::validateSpecialCases(std::vector& candida const std::string& name, const std::vector& inputTypes, function::function_set& set) { // special case for add func - if (name == ADD_FUNC_NAME) { + if (name == AddFunction::name) { auto targetType0 = candidateFunctions[0]->parameterTypeIDs[0]; auto targetType1 = candidateFunctions[0]->parameterTypeIDs[1]; auto inputType0 = inputTypes[0].getLogicalTypeID(); @@ -534,531 +485,6 @@ void BuiltInFunctionsUtils::validateSpecialCases(std::vector& candida } } -void BuiltInFunctionsUtils::registerComparisonFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - EQUALS_FUNC_NAME, EqualsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - NOT_EQUALS_FUNC_NAME, NotEqualsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - GREATER_THAN_FUNC_NAME, GreaterThanFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - GREATER_THAN_EQUALS_FUNC_NAME, GreaterThanEqualsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LESS_THAN_FUNC_NAME, LessThanFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LESS_THAN_EQUALS_FUNC_NAME, LessThanEqualsFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerArithmeticFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry( - std::make_unique(ADD_FUNC_NAME, AddFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SUBTRACT_FUNC_NAME, SubtractFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MULTIPLY_FUNC_NAME, MultiplyFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DIVIDE_FUNC_NAME, DivideFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MODULO_FUNC_NAME, ModuloFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - POWER_FUNC_NAME, PowerFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(ABS_FUNC_NAME, AbsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ACOS_FUNC_NAME, AcosFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ASIN_FUNC_NAME, AsinFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ATAN_FUNC_NAME, AtanFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ATAN2_FUNC_NAME, Atan2Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - BITWISE_XOR_FUNC_NAME, BitwiseXorFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - BITWISE_AND_FUNC_NAME, BitwiseAndFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - BITWISE_OR_FUNC_NAME, BitwiseOrFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - BITSHIFT_LEFT_FUNC_NAME, BitShiftLeftFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - BITSHIFT_RIGHT_FUNC_NAME, BitShiftRightFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CBRT_FUNC_NAME, CbrtFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CEIL_FUNC_NAME, CeilFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CEILING_FUNC_NAME, CeilFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(COS_FUNC_NAME, CosFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(COT_FUNC_NAME, CotFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DEGREES_FUNC_NAME, DegreesFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - EVEN_FUNC_NAME, EvenFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - FACTORIAL_FUNC_NAME, FactorialFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - FLOOR_FUNC_NAME, FloorFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - GAMMA_FUNC_NAME, GammaFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LGAMMA_FUNC_NAME, LgammaFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(LN_FUNC_NAME, LnFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(LOG_FUNC_NAME, LogFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LOG2_FUNC_NAME, Log2Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LOG10_FUNC_NAME, LogFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - NEGATE_FUNC_NAME, NegateFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(PI_FUNC_NAME, PiFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - POW_FUNC_NAME, PowerFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - RADIANS_FUNC_NAME, RadiansFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ROUND_FUNC_NAME, RoundFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(SIN_FUNC_NAME, SinFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SIGN_FUNC_NAME, SignFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SQRT_FUNC_NAME, SqrtFunction::getFunctionSet())); - catalogSet->createEntry( - std::make_unique(TAN_FUNC_NAME, TanFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerDateFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - DATE_PART_FUNC_NAME, DatePartFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DATEPART_FUNC_NAME, DatePartFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DATE_TRUNC_FUNC_NAME, DateTruncFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DATETRUNC_FUNC_NAME, DateTruncFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DAYNAME_FUNC_NAME, DayNameFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - GREATEST_FUNC_NAME, GreatestFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LAST_DAY_FUNC_NAME, LastDayFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LEAST_FUNC_NAME, LeastFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MAKE_DATE_FUNC_NAME, MakeDateFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MONTHNAME_FUNC_NAME, MonthNameFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerTimestampFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - CENTURY_FUNC_NAME, CenturyFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - EPOCH_MS_FUNC_NAME, EpochMsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_TIMESTAMP_FUNC_NAME, ToTimestampFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerIntervalFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - TO_YEARS_FUNC_NAME, ToYearsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_MONTHS_FUNC_NAME, ToMonthsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_DAYS_FUNC_NAME, ToDaysFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_HOURS_FUNC_NAME, ToHoursFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_MINUTES_FUNC_NAME, ToMinutesFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_SECONDS_FUNC_NAME, ToSecondsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_MILLISECONDS_FUNC_NAME, ToMillisecondsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TO_MICROSECONDS_FUNC_NAME, ToMicrosecondsFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerBlobFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - OCTET_LENGTH_FUNC_NAME, OctetLengthFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ENCODE_FUNC_NAME, EncodeFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DECODE_FUNC_NAME, DecodeFunctions::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerUUIDFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - GEN_RANDOM_UUID_FUNC_NAME, GenRandomUUIDFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerStringFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - ARRAY_EXTRACT_FUNC_NAME, ArrayExtractFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CONCAT_FUNC_NAME, ConcatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CONTAINS_FUNC_NAME, ContainsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ENDS_WITH_FUNC_NAME, EndsWithFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LCASE_FUNC_NAME, LowerFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LEFT_FUNC_NAME, LeftFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LOWER_FUNC_NAME, LowerFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LPAD_FUNC_NAME, LpadFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LTRIM_FUNC_NAME, LtrimFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - PREFIX_FUNC_NAME, StartsWithFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REPEAT_FUNC_NAME, RepeatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REVERSE_FUNC_NAME, ReverseFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - RIGHT_FUNC_NAME, RightFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - RPAD_FUNC_NAME, RpadFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - RTRIM_FUNC_NAME, RtrimFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - STARTS_WITH_FUNC_NAME, StartsWithFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SUBSTR_FUNC_NAME, SubStrFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SUBSTRING_FUNC_NAME, SubStrFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SUFFIX_FUNC_NAME, EndsWithFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TRIM_FUNC_NAME, TrimFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - UCASE_FUNC_NAME, UpperFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - UPPER_FUNC_NAME, UpperFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REGEXP_FULL_MATCH_FUNC_NAME, RegexpFullMatchFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REGEXP_MATCHES_FUNC_NAME, RegexpMatchesFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REGEXP_REPLACE_FUNC_NAME, RegexpReplaceFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REGEXP_EXTRACT_FUNC_NAME, RegexpExtractFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - REGEXP_EXTRACT_ALL_FUNC_NAME, RegexpExtractAllFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LEVENSHTEIN_FUNC_NAME, LevenshteinFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerCastFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - CAST_DATE_FUNC_NAME, CastToDateFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_DATE_FUNC_NAME, CastToDateFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_TIMESTAMP_FUNC_NAME, CastToTimestampFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_INTERVAL_FUNC_NAME, CastToIntervalFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_INTERVAL_FUNC_NAME, CastToIntervalFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_STRING_FUNC_NAME, CastToStringFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_STRING_FUNC_NAME, CastToStringFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_BLOB_FUNC_NAME, CastToBlobFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_BLOB_FUNC_NAME, CastToBlobFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_UUID_FUNC_NAME, CastToUUIDFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_UUID_FUNC_NAME, CastToUUIDFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_DOUBLE_FUNC_NAME, CastToDoubleFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_FLOAT_FUNC_NAME, CastToFloatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_SERIAL_FUNC_NAME, CastToSerialFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_INT64_FUNC_NAME, CastToInt64Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_INT32_FUNC_NAME, CastToInt32Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_INT16_FUNC_NAME, CastToInt16Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_INT8_FUNC_NAME, CastToInt8Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_UINT64_FUNC_NAME, CastToUInt64Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_UINT32_FUNC_NAME, CastToUInt32Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_UINT16_FUNC_NAME, CastToUInt16Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_UINT8_FUNC_NAME, CastToUInt8Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_INT128_FUNC_NAME, CastToInt128Function::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_TO_BOOL_FUNC_NAME, CastToBoolFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CAST_FUNC_NAME, CastAnyFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerListFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - LIST_CREATION_FUNC_NAME, ListCreationFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_RANGE_FUNC_NAME, ListRangeFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SIZE_FUNC_NAME, SizeFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_EXTRACT_FUNC_NAME, ListExtractFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_ELEMENT_FUNC_NAME, ListExtractFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_CONCAT_FUNC_NAME, ListConcatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_CAT_FUNC_NAME, ListConcatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_CONCAT_FUNC_NAME, ListConcatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_CAT_FUNC_NAME, ListConcatFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_APPEND_FUNC_NAME, ListAppendFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_APPEND_FUNC_NAME, ListAppendFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_PUSH_BACK_FUNC_NAME, ListAppendFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_PREPEND_FUNC_NAME, ListPrependFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_PREPEND_FUNC_NAME, ListPrependFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_PUSH_FRONT_FUNC_NAME, ListPrependFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_POSITION_FUNC_NAME, ListPositionFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_POSITION_FUNC_NAME, ListPositionFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_INDEXOF_FUNC_NAME, ListPositionFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_INDEXOF_FUNC_NAME, ListPositionFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_CONTAINS_FUNC_NAME, ListContainsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_HAS_FUNC_NAME, ListContainsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_CONTAINS_FUNC_NAME, ListContainsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_HAS_FUNC_NAME, ListContainsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_SLICE_FUNC_NAME, ListSliceFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ARRAY_SLICE_FUNC_NAME, ListSliceFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_SORT_FUNC_NAME, ListSortFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_REVERSE_SORT_FUNC_NAME, ListReverseSortFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_SUM_FUNC_NAME, ListSumFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_PRODUCT_FUNC_NAME, ListProductFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_DISTINCT_FUNC_NAME, ListDistinctFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_UNIQUE_FUNC_NAME, ListUniqueFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_ANY_VALUE_FUNC_NAME, ListAnyValueFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - LIST_REVERSE_FUNC_NAME, ListReverseFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerStructFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - STRUCT_PACK_FUNC_NAME, StructPackFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - STRUCT_EXTRACT_FUNC_NAME, StructExtractFunctions::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerMapFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - MAP_CREATION_FUNC_NAME, MapCreationFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MAP_EXTRACT_FUNC_NAME, MapExtractFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - ELEMENT_AT_FUNC_NAME, MapExtractFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - CARDINALITY_FUNC_NAME, SizeFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MAP_KEYS_FUNC_NAME, MapKeysFunctions::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - MAP_VALUES_FUNC_NAME, MapValuesFunctions::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerUnionFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - UNION_VALUE_FUNC_NAME, UnionValueFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - UNION_TAG_FUNC_NAME, UnionTagFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - UNION_EXTRACT_FUNC_NAME, UnionExtractFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerNodeRelFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - OFFSET_FUNC_NAME, OffsetFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerPathFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - NODES_FUNC_NAME, NodesFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - RELS_FUNC_NAME, RelsFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - PROPERTIES_FUNC_NAME, PropertiesFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - IS_TRAIL_FUNC_NAME, IsTrailFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - IS_ACYCLIC_FUNC_NAME, IsACyclicFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerRdfFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - TYPE_FUNC_NAME, RDFTypeFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - VALIDATE_PREDICATE_FUNC_NAME, ValidatePredicateFunction::getFunctionSet())); -} - -void BuiltInFunctionsUtils::registerCountStar(CatalogSet* catalogSet) { - function_set functionSet; - functionSet.push_back(std::make_unique(COUNT_STAR_FUNC_NAME, - std::vector{}, LogicalTypeID::INT64, CountStarFunction::initialize, - CountStarFunction::updateAll, CountStarFunction::updatePos, CountStarFunction::combine, - CountStarFunction::finalize, false)); - catalogSet->createEntry(std::make_unique( - COUNT_STAR_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerCount(CatalogSet* catalogSet) { - function_set functionSet; - for (auto& type : LogicalTypeUtils::getAllValidLogicTypes()) { - for (auto isDistinct : std::vector{true, false}) { - functionSet.push_back(AggregateFunctionUtil::getAggFunc(COUNT_FUNC_NAME, - type, LogicalTypeID::INT64, isDistinct, CountFunction::paramRewriteFunc)); - } - } - catalogSet->createEntry( - std::make_unique(COUNT_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerSum(CatalogSet* catalogSet) { - function_set functionSet; - for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - for (auto isDistinct : std::vector{true, false}) { - functionSet.push_back( - AggregateFunctionUtil::getSumFunc(SUM_FUNC_NAME, typeID, typeID, isDistinct)); - } - } - catalogSet->createEntry( - std::make_unique(SUM_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerAvg(CatalogSet* catalogSet) { - function_set functionSet; - for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - for (auto isDistinct : std::vector{true, false}) { - functionSet.push_back(AggregateFunctionUtil::getAvgFunc( - AVG_FUNC_NAME, typeID, LogicalTypeID::DOUBLE, isDistinct)); - } - } - catalogSet->createEntry( - std::make_unique(AVG_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerMin(CatalogSet* catalogSet) { - function_set functionSet; - for (auto& type : LogicalTypeUtils::getAllValidComparableLogicalTypes()) { - for (auto isDistinct : std::vector{true, false}) { - functionSet.push_back(AggregateFunctionUtil::getMinFunc(type, isDistinct)); - } - } - catalogSet->createEntry( - std::make_unique(MIN_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerMax(CatalogSet* catalogSet) { - function_set functionSet; - for (auto& type : LogicalTypeUtils::getAllValidComparableLogicalTypes()) { - for (auto isDistinct : std::vector{true, false}) { - functionSet.push_back(AggregateFunctionUtil::getMaxFunc(type, isDistinct)); - } - } - catalogSet->createEntry( - std::make_unique(MAX_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerCollect(CatalogSet* catalogSet) { - function_set functionSet; - for (auto isDistinct : std::vector{true, false}) { - functionSet.push_back(std::make_unique(COLLECT_FUNC_NAME, - std::vector{common::LogicalTypeID::ANY}, LogicalTypeID::VAR_LIST, - CollectFunction::initialize, CollectFunction::updateAll, CollectFunction::updatePos, - CollectFunction::combine, CollectFunction::finalize, isDistinct, - CollectFunction::bindFunc)); - } - catalogSet->createEntry( - std::make_unique(COLLECT_FUNC_NAME, std::move(functionSet))); -} - -void BuiltInFunctionsUtils::registerTableFunctions(CatalogSet* catalogSet) { - catalogSet->createEntry(std::make_unique( - CURRENT_SETTING_FUNC_NAME, CurrentSettingFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - DB_VERSION_FUNC_NAME, DBVersionFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SHOW_TABLES_FUNC_NAME, ShowTablesFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - TABLE_INFO_FUNC_NAME, TableInfoFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - SHOW_CONNECTION_FUNC_NAME, ShowConnectionFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - STORAGE_INFO_FUNC_NAME, StorageInfoFunction::getFunctionSet())); - // Read functions - catalogSet->createEntry(std::make_unique( - READ_PARQUET_FUNC_NAME, ParquetScanFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_NPY_FUNC_NAME, NpyScanFunction::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_CSV_SERIAL_FUNC_NAME, SerialCSVScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_CSV_PARALLEL_FUNC_NAME, ParallelCSVScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_RDF_RESOURCE_FUNC_NAME, RdfResourceScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_RDF_LITERAL_FUNC_NAME, RdfLiteralScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_RDF_RESOURCE_TRIPLE_FUNC_NAME, RdfResourceTripleScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_RDF_LITERAL_TRIPLE_FUNC_NAME, RdfLiteralTripleScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_RDF_ALL_TRIPLE_FUNC_NAME, RdfAllTripleScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - IN_MEM_READ_RDF_RESOURCE_FUNC_NAME, RdfResourceInMemScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - IN_MEM_READ_RDF_LITERAL_FUNC_NAME, RdfLiteralInMemScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - IN_MEM_READ_RDF_RESOURCE_TRIPLE_FUNC_NAME, RdfResourceTripleInMemScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - IN_MEM_READ_RDF_LITERAL_TRIPLE_FUNC_NAME, RdfLiteralTripleInMemScan::getFunctionSet())); - catalogSet->createEntry(std::make_unique( - READ_FTABLE_FUNC_NAME, FTableScan::getFunctionSet())); -} - static std::string getFunctionMatchFailureMsg(const std::string name, const std::vector& inputTypes, const std::string& supportedInputs, bool isDistinct = false) { @@ -1072,9 +498,9 @@ static std::string getFunctionMatchFailureMsg(const std::string name, return result; } -void BuiltInFunctionsUtils::validateNonEmptyCandidateFunctions( - std::vector& candidateFunctions, const std::string& name, - const std::vector& inputTypes, bool isDistinct, function::function_set& set) { +void validateNonEmptyCandidateFunctions(std::vector& candidateFunctions, + const std::string& name, const std::vector& inputTypes, bool isDistinct, + function::function_set& set) { if (candidateFunctions.empty()) { std::string supportedInputsString; for (auto& function : set) { @@ -1089,9 +515,9 @@ void BuiltInFunctionsUtils::validateNonEmptyCandidateFunctions( } } -void BuiltInFunctionsUtils::validateNonEmptyCandidateFunctions( - std::vector& candidateFunctions, const std::string& name, - const std::vector& inputTypes, function::function_set& set) { +void validateNonEmptyCandidateFunctions(std::vector& candidateFunctions, + const std::string& name, const std::vector& inputTypes, + function::function_set& set) { if (candidateFunctions.empty()) { std::string supportedInputsString; for (auto& function : set) { diff --git a/src/function/cast/CMakeLists.txt b/src/function/cast/CMakeLists.txt index 2280180a29c..a1c9d7c6bb8 100644 --- a/src/function/cast/CMakeLists.txt +++ b/src/function/cast/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(kuzu_function_cast OBJECT cast_rdf_variant.cpp - cast_fixed_list.cpp) + cast_array.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/function/cast/cast_array.cpp b/src/function/cast/cast_array.cpp new file mode 100644 index 00000000000..2131da1c2e4 --- /dev/null +++ b/src/function/cast/cast_array.cpp @@ -0,0 +1,132 @@ +#include "function/cast/functions/cast_array.h" + +#include "common/exception/conversion.h" +#include "common/type_utils.h" + +namespace kuzu { +namespace function { + +bool CastArrayHelper::checkCompatibleNestedTypes(LogicalTypeID sourceTypeID, + LogicalTypeID targetTypeID) { + switch (sourceTypeID) { + case LogicalTypeID::LIST: { + if (targetTypeID == LogicalTypeID::ARRAY || targetTypeID == LogicalTypeID::LIST) { + return true; + } + } + case LogicalTypeID::MAP: + case LogicalTypeID::STRUCT: { + if (sourceTypeID == targetTypeID) { + return true; + } + } + case LogicalTypeID::ARRAY: { + if (targetTypeID == LogicalTypeID::LIST || targetTypeID == LogicalTypeID::ARRAY) { + return true; + } + } + default: + return false; + } + return false; +} + +bool CastArrayHelper::containsListToArray(const LogicalType* srcType, const LogicalType* dstType) { + if ((srcType->getLogicalTypeID() == LogicalTypeID::LIST || + srcType->getLogicalTypeID() == LogicalTypeID::ARRAY) && + dstType->getLogicalTypeID() == LogicalTypeID::ARRAY) { + return true; + } + + if (checkCompatibleNestedTypes(srcType->getLogicalTypeID(), dstType->getLogicalTypeID())) { + switch (srcType->getPhysicalType()) { + case PhysicalTypeID::LIST: { + auto srcChildType = (srcType->getLogicalTypeID() == LogicalTypeID::ARRAY) ? + ArrayType::getChildType(srcType) : + ListType::getChildType(srcType); + auto dstChildType = (dstType->getLogicalTypeID() == LogicalTypeID::ARRAY) ? + ArrayType::getChildType(dstType) : + ListType::getChildType(dstType); + return containsListToArray(srcChildType, dstChildType); + } + case PhysicalTypeID::STRUCT: { + auto srcFieldTypes = StructType::getFieldTypes(srcType); + auto dstFieldTypes = StructType::getFieldTypes(dstType); + if (srcFieldTypes.size() != dstFieldTypes.size()) { + throw ConversionException{ + stringFormat("Unsupported casting function from {} to {}.", srcType->toString(), + dstType->toString())}; + } + + for (auto i = 0u; i < srcFieldTypes.size(); i++) { + if (containsListToArray(srcFieldTypes[i], dstFieldTypes[i])) { + return true; + } + } + } + default: + return false; + } + } + return false; +} + +void CastArrayHelper::validateListEntry(ValueVector* inputVector, LogicalType* resultType, + uint64_t pos) { + if (inputVector->isNull(pos)) { + return; + } + auto inputType = inputVector->dataType; + + switch (resultType->getPhysicalType()) { + case PhysicalTypeID::LIST: { + if (inputType.getPhysicalType() == PhysicalTypeID::LIST) { + if (inputType.getLogicalTypeID() == LogicalTypeID::ARRAY && + resultType->getLogicalTypeID() == LogicalTypeID::ARRAY) { + if (ArrayType::getNumElements(&inputType) != + ArrayType::getNumElements(resultType)) { + throw ConversionException( + stringFormat("Unsupported casting function from {} to {}.", + inputType.toString(), resultType->toString())); + } + } + if (inputType.getLogicalTypeID() == LogicalTypeID::LIST && + resultType->getLogicalTypeID() == LogicalTypeID::ARRAY) { + auto listEntry = inputVector->getValue(pos); + if (listEntry.size != ArrayType::getNumElements(resultType)) { + throw ConversionException{ + stringFormat("Unsupported casting LIST with incorrect list entry to ARRAY. " + "Expected: {}, Actual: {}.", + ArrayType::getNumElements(resultType), + inputVector->getValue(pos).size)}; + } + } + auto listEntry = inputVector->getValue(pos); + auto inputChildVector = ListVector::getDataVector(inputVector); + auto resultChildType = (resultType->getLogicalTypeID() == LogicalTypeID::ARRAY) ? + ArrayType::getChildType(resultType) : + ListType::getChildType(resultType); + for (auto i = listEntry.offset; i < listEntry.offset + listEntry.size; i++) { + validateListEntry(inputChildVector, resultChildType, i); + } + } + } break; + case PhysicalTypeID::STRUCT: { + if (inputType.getPhysicalType() == PhysicalTypeID::STRUCT) { + auto fieldVectors = StructVector::getFieldVectors(inputVector); + auto fieldTypes = StructType::getFieldTypes(resultType); + + auto structEntry = inputVector->getValue(pos); + for (auto i = 0u; i < fieldVectors.size(); i++) { + validateListEntry(fieldVectors[i].get(), fieldTypes[i], structEntry.pos); + } + } + } break; + default: { + return; + } + } +} + +} // namespace function +} // namespace kuzu diff --git a/src/function/cast/cast_fixed_list.cpp b/src/function/cast/cast_fixed_list.cpp deleted file mode 100644 index f5185d0aff3..00000000000 --- a/src/function/cast/cast_fixed_list.cpp +++ /dev/null @@ -1,387 +0,0 @@ -#include "function/cast/functions/cast_fixed_list.h" - -#include "common/exception/conversion.h" -#include "common/type_utils.h" -#include "function/cast/functions/cast_from_string_functions.h" -#include "function/cast/functions/cast_functions.h" - -namespace kuzu { -namespace function { - -bool CastFixedListHelper::containsListToFixedList( - const LogicalType* srcType, const LogicalType* dstType) { - if (srcType->getLogicalTypeID() == LogicalTypeID::VAR_LIST && - dstType->getLogicalTypeID() == LogicalTypeID::FIXED_LIST) { - return true; - } - - while (srcType->getLogicalTypeID() == dstType->getLogicalTypeID()) { - switch (srcType->getPhysicalType()) { - case PhysicalTypeID::VAR_LIST: { - return containsListToFixedList( - VarListType::getChildType(srcType), VarListType::getChildType(dstType)); - } - case PhysicalTypeID::STRUCT: { - auto srcFieldTypes = StructType::getFieldTypes(srcType); - auto dstFieldTypes = StructType::getFieldTypes(dstType); - if (srcFieldTypes.size() != dstFieldTypes.size()) { - throw ConversionException{ - stringFormat("Unsupported casting function from {} to {}.", srcType->toString(), - dstType->toString())}; - } - - std::vector fields; - for (auto i = 0u; i < srcFieldTypes.size(); i++) { - if (containsListToFixedList(srcFieldTypes[i], dstFieldTypes[i])) { - return true; - } - } - } - default: - return false; - } - } - return false; -} - -void CastFixedListHelper::validateListEntry( - ValueVector* inputVector, LogicalType* resultType, uint64_t pos) { - if (inputVector->isNull(pos)) { - return; - } - auto inputTypeID = inputVector->dataType.getPhysicalType(); - - switch (resultType->getPhysicalType()) { - case PhysicalTypeID::FIXED_LIST: { - if (inputTypeID == PhysicalTypeID::VAR_LIST) { - auto listEntry = inputVector->getValue(pos); - if (listEntry.size != FixedListType::getNumValuesInList(resultType)) { - throw ConversionException{stringFormat( - "Unsupported casting VAR_LIST with incorrect list entry to FIXED_LIST. " - "Expected: {}, Actual: {}.", - FixedListType::getNumValuesInList(resultType), - inputVector->getValue(pos).size)}; - } - - auto inputChildVector = ListVector::getDataVector(inputVector); - for (auto i = listEntry.offset; i < listEntry.offset + listEntry.size; i++) { - if (inputChildVector->isNull(i)) { - throw ConversionException("Cast failed. NULL is not allowed for FIXED_LIST."); - } - } - } - } break; - case PhysicalTypeID::VAR_LIST: { - if (inputTypeID == PhysicalTypeID::VAR_LIST) { - auto listEntry = inputVector->getValue(pos); - for (auto i = listEntry.offset; i < listEntry.offset + listEntry.size; i++) { - validateListEntry(ListVector::getDataVector(inputVector), - VarListType::getChildType(resultType), i); - } - } - } break; - case PhysicalTypeID::STRUCT: { - if (inputTypeID == PhysicalTypeID::STRUCT) { - auto fieldVectors = StructVector::getFieldVectors(inputVector); - auto fieldTypes = StructType::getFieldTypes(resultType); - - auto structEntry = inputVector->getValue(pos); - for (auto i = 0u; i < fieldVectors.size(); i++) { - validateListEntry(fieldVectors[i].get(), fieldTypes[i], structEntry.pos); - } - } - } break; - default: { - return; - } - } -} - -static void CastFixedListToString( - ValueVector& param, uint64_t pos, ValueVector& resultVector, uint64_t resultPos) { - resultVector.setNull(resultPos, param.isNull(pos)); - if (param.isNull(pos)) { - return; - } - auto value = param.getData() + pos * param.getNumBytesPerValue(); - auto result = TypeUtils::fixedListToString(value, param.dataType, ¶m); - StringVector::addString(&resultVector, resultPos, result); -} - -template<> -void CastFixedList::fixedListToStringCastExecFunction( - const std::vector>& params, ValueVector& result, - void* /*dataPtr*/) { - KU_ASSERT(params.size() == 1); - const auto& param = params[0]; - if (param->state->isFlat()) { - CastFixedListToString(*param, param->state->selVector->selectedPositions[0], result, - result.state->selVector->selectedPositions[0]); - } else if (param->state->selVector->isUnfiltered()) { - for (auto i = 0u; i < param->state->selVector->selectedSize; i++) { - CastFixedListToString(*param, i, result, i); - } - } else { - for (auto i = 0u; i < param->state->selVector->selectedSize; i++) { - CastFixedListToString(*param, param->state->selVector->selectedPositions[i], result, - result.state->selVector->selectedPositions[i]); - } - } -} - -// LCOV_EXCL_START -template<> -void CastFixedList::fixedListToStringCastExecFunction( - const std::vector>& /*params*/, ValueVector& /*result*/, - void* /*dataPtr*/) { - KU_UNREACHABLE; -} -// LCOV_EXCL_STOP - -template<> -void CastFixedList::fixedListToStringCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - KU_ASSERT(params.size() == 1); - - auto inputVector = params[0].get(); - auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; - for (auto i = 0u; i < numOfEntries; i++) { - CastFixedListToString(*inputVector, i, result, i); - } -} - -template<> -void CastFixedList::stringtoFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - KU_ASSERT(params.size() == 1); - const auto& param = params[0]; - auto option = &reinterpret_cast(dataPtr)->csvConfig.option; - if (param->state->isFlat()) { - auto inputPos = param->state->selVector->selectedPositions[0]; - auto resultPos = result.state->selVector->selectedPositions[0]; - result.setNull(resultPos, param->isNull(inputPos)); - if (!result.isNull(inputPos)) { - CastString::castToFixedList( - param->getValue(inputPos), &result, resultPos, option); - } - } else if (param->state->selVector->isUnfiltered()) { - for (auto i = 0u; i < param->state->selVector->selectedSize; i++) { - result.setNull(i, param->isNull(i)); - if (!result.isNull(i)) { - CastString::castToFixedList(param->getValue(i), &result, i, option); - } - } - } else { - for (auto i = 0u; i < param->state->selVector->selectedSize; i++) { - auto pos = param->state->selVector->selectedPositions[i]; - result.setNull(pos, param->isNull(pos)); - if (!result.isNull(pos)) { - CastString::castToFixedList( - param->getValue(pos), &result, pos, option); - } - } - } -} - -// LCOV_EXCL_START -template<> -void CastFixedList::stringtoFixedListCastExecFunction( - const std::vector>& /*params*/, ValueVector& /*result*/, - void* /*dataPtr*/) { - KU_UNREACHABLE; -} -// LCOV_EXCL_STOP - -template<> -void CastFixedList::stringtoFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - KU_ASSERT(params.size() == 1); - auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; - auto option = &reinterpret_cast(dataPtr)->csvConfig.option; - auto inputVector = params[0].get(); - for (auto i = 0u; i < numOfEntries; i++) { - result.setNull(i, inputVector->isNull(i)); - if (!result.isNull(i)) { - CastString::castToFixedList(inputVector->getValue(i), &result, i, option); - } - } -} - -template<> -void CastFixedList::listToFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - KU_ASSERT(params.size() == 1); - const auto& inputVector = params[0]; - - for (auto i = 0u; i < inputVector->state->selVector->selectedSize; i++) { - auto pos = inputVector->state->selVector->selectedPositions[i]; - CastFixedListHelper::validateListEntry(inputVector.get(), &result.dataType, pos); - } - - auto numOfEntries = inputVector->state->selVector - ->selectedPositions[inputVector->state->selVector->selectedSize - 1] + - 1; - reinterpret_cast(dataPtr)->numOfEntries = numOfEntries; - listToFixedListCastExecFunction(params, result, dataPtr); -} - -// LCOV_EXCL_START -template<> -void CastFixedList::listToFixedListCastExecFunction( - const std::vector>& /*params*/, ValueVector& /*result*/, - void* /*dataPtr*/) { - KU_UNREACHABLE; -} -// LCOV_EXCL_STOP - -using scalar_cast_func = std::function; - -template -static void getFixedListChildFuncHelper(scalar_cast_func& func, LogicalTypeID inputTypeID) { - switch (inputTypeID) { - case LogicalTypeID::STRING: { - func = UnaryCastStringFunctionWrapper::operation; - } break; - case LogicalTypeID::INT128: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::INT64: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::INT32: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::INT16: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::INT8: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::UINT8: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::UINT16: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::UINT32: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::UINT64: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::FLOAT: { - func = UnaryFunctionWrapper::operation; - } break; - case LogicalTypeID::DOUBLE: { - func = UnaryFunctionWrapper::operation; - } break; - default: { - throw ConversionException{ - stringFormat("Unsupported casting function from {} to numerical type.", - LogicalTypeUtils::toString(inputTypeID))}; - } - } -} - -static void getFixedListChildCastFunc( - scalar_cast_func& func, LogicalTypeID inputType, LogicalTypeID resultType) { - // only support limited Fixed List Types - switch (resultType) { - case LogicalTypeID::INT64: { - return getFixedListChildFuncHelper(func, inputType); - } - case LogicalTypeID::INT32: { - return getFixedListChildFuncHelper(func, inputType); - } - case LogicalTypeID::INT16: { - return getFixedListChildFuncHelper(func, inputType); - } - case LogicalTypeID::DOUBLE: { - return getFixedListChildFuncHelper(func, inputType); - } - case LogicalTypeID::FLOAT: { - return getFixedListChildFuncHelper(func, inputType); - } - default: { - throw RuntimeException("Unsupported FIXED_LIST type: Function::getFixedListChildCastFunc"); - } - } -} - -template<> -void CastFixedList::listToFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - const auto& inputVector = params[0]; - auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; - - auto inputChildId = VarListType::getChildType(&inputVector->dataType)->getLogicalTypeID(); - auto outputChildId = FixedListType::getChildType(&result.dataType)->getLogicalTypeID(); - auto numValuesPerList = FixedListType::getNumValuesInList(&result.dataType); - scalar_cast_func func; - getFixedListChildCastFunc(func, inputChildId, outputChildId); - - result.setNullFromBits(inputVector->getNullMaskData(), 0, 0, numOfEntries); - auto inputChildVector = ListVector::getDataVector(inputVector.get()); - for (auto i = 0u; i < numOfEntries; i++) { - if (!result.isNull(i)) { - auto listEntry = inputVector->getValue(i); - if (listEntry.size == numValuesPerList) { - for (auto j = 0u; j < listEntry.size; j++) { - func((void*)(inputChildVector), listEntry.offset + j, (void*)(&result), - i * numValuesPerList + j, nullptr); - } - } - } - } -} - -template<> -void CastFixedList::castBetweenFixedListExecFunc( - const std::vector>& params, ValueVector& result, void* dataPtr) { - const auto& inputVector = params[0]; - auto numOfEntries = inputVector->state->selVector - ->selectedPositions[inputVector->state->selVector->selectedSize - 1] + - 1; - reinterpret_cast(dataPtr)->numOfEntries = numOfEntries; - castBetweenFixedListExecFunc(params, result, dataPtr); -} - -// LCOV_EXCL_START -template<> -void CastFixedList::castBetweenFixedListExecFunc( - const std::vector>& /*params*/, ValueVector& /*result*/, - void* /*dataPtr*/) { - KU_UNREACHABLE; -} -// LCOV_EXCL_STOP - -template<> -void CastFixedList::castBetweenFixedListExecFunc( - const std::vector>& params, ValueVector& result, void* dataPtr) { - const auto& inputVector = params[0]; - auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; - - auto inputChildId = FixedListType::getChildType(&inputVector->dataType)->getLogicalTypeID(); - auto outputChildId = FixedListType::getChildType(&result.dataType)->getLogicalTypeID(); - auto numValuesPerList = FixedListType::getNumValuesInList(&result.dataType); - if (FixedListType::getNumValuesInList(&inputVector->dataType) != numValuesPerList) { - throw ConversionException(stringFormat("Unsupported casting function from {} to {}.", - inputVector->dataType.toString(), result.dataType.toString())); - } - - scalar_cast_func func; - getFixedListChildCastFunc(func, inputChildId, outputChildId); - - result.setNullFromBits(inputVector->getNullMaskData(), 0, 0, numOfEntries); - for (auto i = 0u; i < numOfEntries; i++) { - if (!result.isNull(i)) { - for (auto j = 0u; j < numValuesPerList; j++) { - func((void*)(inputVector.get()), i * numValuesPerList + j, (void*)(&result), - i * numValuesPerList + j, nullptr); - } - } - } -} - -} // namespace function -} // namespace kuzu diff --git a/src/function/cast_from_string_functions.cpp b/src/function/cast_from_string_functions.cpp index eae769bb370..1d4e7574e15 100644 --- a/src/function/cast_from_string_functions.cpp +++ b/src/function/cast_from_string_functions.cpp @@ -1,7 +1,6 @@ #include "function/cast/functions/cast_from_string_functions.h" #include "common/exception/copy.h" -#include "common/exception/not_implemented.h" #include "common/exception/parser.h" #include "common/string_format.h" #include "common/types/blob.h" @@ -19,9 +18,6 @@ struct CastStringHelper { uint64_t /*rowToAdd*/ = 0, const CSVOption* /*option*/ = nullptr) { simpleIntegerCast(input, len, result, LogicalTypeID::INT64); } - - static void castToFixedList(const char* input, uint64_t len, ValueVector* vector, - uint64_t rowToAdd, const CSVOption* option); }; template<> @@ -111,8 +107,8 @@ inline void CastStringHelper::cast(const char* input, uint64_t len, timestamp_ns template<> inline void CastStringHelper::cast(const char* input, uint64_t len, timestamp_sec_t& result, ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - TryCastStringToTimestamp::cast( - input, len, result, LogicalTypeID::TIMESTAMP_SEC); + TryCastStringToTimestamp::cast(input, len, result, + LogicalTypeID::TIMESTAMP_SEC); } template<> @@ -145,8 +141,8 @@ void CastString::operation(const ku_string_t& input, blob_t& result, ValueVector Blob::fromString(reinterpret_cast(input.getData()), input.len, overflowPtr); memcpy(result.value.prefix, overflowPtr, ku_string_t::PREFIX_LENGTH); } else { - Blob::fromString( - reinterpret_cast(input.getData()), input.len, result.value.prefix); + Blob::fromString(reinterpret_cast(input.getData()), input.len, + result.value.prefix); } } @@ -208,8 +204,8 @@ static bool skipToCloseQuotes(const char*& input, const char* end) { return false; } -static bool skipToClose( - const char*& input, const char* end, uint64_t& lvl, char target, const CSVOption* option) { +static bool skipToClose(const char*& input, const char* end, uint64_t& lvl, char target, + const CSVOption* option) { input++; while (input != end) { if (*input == '\'') { @@ -256,16 +252,16 @@ static bool isNull(std::string_view& str) { return false; } -// ---------------------- cast String to Varlist ------------------------------ // +// ---------------------- cast String to List Helper ------------------------------ // struct CountPartOperation { uint64_t count = 0; - static inline bool handleKey( - const char* /*start*/, const char* /*end*/, const CSVOption* /*config*/) { + static inline bool handleKey(const char* /*start*/, const char* /*end*/, + const CSVOption* /*config*/) { return true; } - inline void handleValue( - const char* /*start*/, const char* /*end*/, const CSVOption* /*config*/) { + inline void handleValue(const char* /*start*/, const char* /*end*/, + const CSVOption* /*config*/) { count++; } }; @@ -280,8 +276,8 @@ struct SplitStringListOperation { void handleValue(const char* start, const char* end, const CSVOption* option) { skipWhitespace(start, end); trimRightWhitespace(start, end); - CastString::copyStringToVector( - resultVector, offset, std::string_view{start, (uint32_t)(end - start)}, option); + CastString::copyStringToVector(resultVector, offset, + std::string_view{start, (uint32_t)(end - start)}, option); offset++; } }; @@ -334,20 +330,36 @@ static bool splitCStringList(const char* input, uint64_t len, T& state, const CS } template -static inline void startListCast( - const char* input, uint64_t len, T split, const CSVOption* option, ValueVector* vector) { +static inline void startListCast(const char* input, uint64_t len, T split, const CSVOption* option, + ValueVector* vector) { if (!splitCStringList(input, len, split, option)) { throw ConversionException("Cast failed. " + std::string{input, len} + " is not in " + vector->dataType.toString() + " range."); } } +// ---------------------- cast String to Array Helper ------------------------------ // +static void validateNumElementsInArray(uint64_t numElementsRead, const LogicalType& type) { + auto numElementsInArray = ArrayType::getNumElements(&type); + if (numElementsRead != numElementsInArray) { + throw CopyException(stringFormat( + "Each array should have fixed number of elements. Expected: {}, Actual: {}.", + numElementsInArray, numElementsRead)); + } +} + +// ---------------------- cast String to List/Array ------------------------------ // template<> void CastStringHelper::cast(const char* input, uint64_t len, list_entry_t& /*result*/, ValueVector* vector, uint64_t rowToAdd, const CSVOption* option) { + auto logicalTypeID = vector->dataType.getLogicalTypeID(); + // calculate the number of elements in array CountPartOperation state; splitCStringList(input, len, state, option); + if (logicalTypeID == LogicalTypeID::ARRAY) { + validateNumElementsInArray(state.count, vector->dataType); + } auto list_entry = ListVector::addList(vector, state.count); vector->setValue(rowToAdd, list_entry); @@ -364,81 +376,6 @@ void CastString::operation(const ku_string_t& input, list_entry_t& result, resultVector, rowToAdd, option); } -// ---------------------- cast String to FixedList ------------------------------ // -template -struct SplitStringFixedListOperation { - SplitStringFixedListOperation(uint64_t& offset, ValueVector* resultVector) - : offset(offset), resultVector(resultVector) {} - - uint64_t& offset; - ValueVector* resultVector; - - void handleValue(const char* start, const char* end, const CSVOption* /*option*/) { - T value; - auto str = std::string_view{start, (uint32_t)(end - start)}; - if (str.empty() || isNull(str)) { - throw ConversionException("Cast failed. NULL is not allowed for FIXED_LIST."); - } - CastStringHelper::cast(start, str.length(), value); - resultVector->setValue(offset, value); - offset++; - } -}; - -static void validateNumElementsInList(uint64_t numElementsRead, const LogicalType& type) { - auto numElementsInList = FixedListType::getNumValuesInList(&type); - if (numElementsRead != numElementsInList) { - throw CopyException(stringFormat( - "Each fixed list should have fixed number of elements. Expected: {}, Actual: {}.", - numElementsInList, numElementsRead)); - } -} - -void CastStringHelper::castToFixedList(const char* input, uint64_t len, ValueVector* vector, - uint64_t rowToAdd, const CSVOption* option) { - KU_ASSERT(vector->dataType.getLogicalTypeID() == LogicalTypeID::FIXED_LIST); - auto childDataType = FixedListType::getChildType(&vector->dataType); - - // calculate the number of elements in array - CountPartOperation state; - splitCStringList(input, len, state, option); - validateNumElementsInList(state.count, vector->dataType); - - auto startOffset = state.count * rowToAdd; - switch (childDataType->getLogicalTypeID()) { - // TODO(Kebing): currently only allow these type - case LogicalTypeID::INT64: { - SplitStringFixedListOperation split{startOffset, vector}; - startListCast(input, len, split, option, vector); - } break; - case LogicalTypeID::INT32: { - SplitStringFixedListOperation split{startOffset, vector}; - startListCast(input, len, split, option, vector); - } break; - case LogicalTypeID::INT16: { - SplitStringFixedListOperation split{startOffset, vector}; - startListCast(input, len, split, option, vector); - } break; - case LogicalTypeID::FLOAT: { - SplitStringFixedListOperation split{startOffset, vector}; - startListCast(input, len, split, option, vector); - } break; - case LogicalTypeID::DOUBLE: { - SplitStringFixedListOperation split{startOffset, vector}; - startListCast(input, len, split, option, vector); - } break; - default: { - throw NotImplementedException("Unsupported data type: Function::castStringToFixedList"); - } - } -} - -void CastString::castToFixedList(const ku_string_t& input, ValueVector* resultVector, - uint64_t rowToAdd, const CSVOption* option) { - CastStringHelper::castToFixedList( - reinterpret_cast(input.getData()), input.len, resultVector, rowToAdd, option); -} - // ---------------------- cast String to Map ------------------------------ // struct SplitStringMapOperation { SplitStringMapOperation(uint64_t& offset, ValueVector* resultVector) @@ -566,8 +503,8 @@ static bool parseStructFieldName(const char*& input, const char* end) { return false; } -static bool parseStructFieldValue( - const char*& input, const char* end, const CSVOption* option, bool& closeBrack) { +static bool parseStructFieldValue(const char*& input, const char* end, const CSVOption* option, + bool& closeBrack) { uint64_t lvl = 0; while (input < end) { if (*input == '"' || *input == '\'') { @@ -677,8 +614,8 @@ static inline void testAndSetValue(ValueVector* vector, uint64_t rowToAdd, T res } } -static bool tryCastUnionField( - ValueVector* vector, uint64_t rowToAdd, const char* input, uint64_t len) { +static bool tryCastUnionField(ValueVector* vector, uint64_t rowToAdd, const char* input, + uint64_t len) { auto& targetType = vector->dataType; bool success = false; switch (targetType.getLogicalTypeID()) { @@ -806,8 +743,8 @@ void CastStringHelper::cast(const char* input, uint64_t len, union_entry_t& /*re } if (selectedFieldIdx == INVALID_STRUCT_FIELD_IDX) { - throw ConversionException{stringFormat( - "Could not convert to union type {}: {}.", type.toString(), std::string{input, len})}; + throw ConversionException{stringFormat("Could not convert to union type {}: {}.", + type.toString(), std::string{input, len})}; } StructVector::getFieldVector(vector, UnionType::TAG_FIELD_IDX) ->setValue(rowToAdd, selectedFieldIdx); @@ -822,145 +759,141 @@ void CastString::operation(const ku_string_t& input, union_entry_t& result, resultVector, rowToAdd, CSVOption); } -void CastString::copyStringToVector( - ValueVector* vector, uint64_t rowToAdd, std::string_view strVal, const CSVOption* option) { +void CastString::copyStringToVector(ValueVector* vector, uint64_t vectorPos, + std::string_view strVal, const CSVOption* option) { auto& type = vector->dataType; - if (strVal.empty() || isNull(strVal)) { - vector->setNull(rowToAdd, true /* isNull */); + vector->setNull(vectorPos, true /* isNull */); return; - } else { - vector->setNull(rowToAdd, false /* isNull */); } + vector->setNull(vectorPos, false /* isNull */); switch (type.getLogicalTypeID()) { case LogicalTypeID::INT128: { int128_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::INT64: { int64_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::INT32: { int32_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::INT16: { int16_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::INT8: { int8_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::UINT64: { uint64_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::UINT32: { uint32_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::UINT16: { uint16_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::UINT8: { uint8_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::FLOAT: { float val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::DOUBLE: { double val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::BOOL: { bool val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::BLOB: { blob_t val; - CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, rowToAdd, option); + CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, vectorPos, option); } break; case LogicalTypeID::UUID: { ku_uuid_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val.value); + vector->setValue(vectorPos, val.value); } break; case LogicalTypeID::STRING: { if (!utf8proc::Utf8Proc::isValid(strVal.data(), strVal.length())) { throw CopyException{"Invalid UTF8-encoded string."}; } - StringVector::addString(vector, rowToAdd, strVal.data(), strVal.length()); + StringVector::addString(vector, vectorPos, strVal.data(), strVal.length()); } break; case LogicalTypeID::DATE: { date_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::TIMESTAMP_NS: { timestamp_ns_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::TIMESTAMP_MS: { timestamp_ms_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::TIMESTAMP_SEC: { timestamp_sec_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::TIMESTAMP_TZ: { timestamp_tz_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::TIMESTAMP: { timestamp_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::INTERVAL: { interval_t val; CastStringHelper::cast(strVal.data(), strVal.length(), val); - vector->setValue(rowToAdd, val); + vector->setValue(vectorPos, val); } break; case LogicalTypeID::MAP: { map_entry_t val; - CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, rowToAdd, option); + CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, vectorPos, option); } break; - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: { list_entry_t val; - CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, rowToAdd, option); - } break; - case LogicalTypeID::FIXED_LIST: { - CastStringHelper::castToFixedList(strVal.data(), strVal.length(), vector, rowToAdd, option); + CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, vectorPos, option); } break; case LogicalTypeID::STRUCT: { struct_entry_t val; - CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, rowToAdd, option); + CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, vectorPos, option); } break; case LogicalTypeID::UNION: { union_entry_t val; - CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, rowToAdd, option); + CastStringHelper::cast(strVal.data(), strVal.length(), val, vector, vectorPos, option); } break; default: { KU_UNREACHABLE; diff --git a/src/function/cast_string_non_nested_functions.cpp b/src/function/cast_string_non_nested_functions.cpp index 02ce6458fd6..5ec298a8bb8 100644 --- a/src/function/cast_string_non_nested_functions.cpp +++ b/src/function/cast_string_non_nested_functions.cpp @@ -54,8 +54,8 @@ void castStringToBool(const char* input, uint64_t len, bool& result) { } template<> -bool TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result) { +bool TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result) { if (!Timestamp::tryConvertTimestamp(input, len, result)) { return false; } @@ -64,8 +64,8 @@ bool TryCastStringToTimestamp::tryCast( } template<> -bool TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result) { +bool TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result) { if (!Timestamp::tryConvertTimestamp(input, len, result)) { return false; } @@ -74,8 +74,8 @@ bool TryCastStringToTimestamp::tryCast( } template<> -bool TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result) { +bool TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result) { if (!Timestamp::tryConvertTimestamp(input, len, result)) { return false; } diff --git a/src/function/comparison_functions.cpp b/src/function/comparison_functions.cpp index 304a7e899e8..12cb9fcd106 100644 --- a/src/function/comparison_functions.cpp +++ b/src/function/comparison_functions.cpp @@ -86,7 +86,7 @@ static void executeNestedOperation(uint8_t& result, ValueVector* leftVector, rightVector->getValue(rightPos), result, nullptr /* left */, nullptr /* right */); } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { OP::operation(leftVector->getValue(leftPos), rightVector->getValue(rightPos), result, leftVector, rightVector); } break; @@ -160,11 +160,11 @@ static void executeNestedGreaterThan(uint8_t& isGreaterThan, uint8_t& isEqual, isGreaterThan = !isRightNull; isEqual = (isLeftNull == isRightNull); } else { - executeNestedOperation( - isGreaterThan, leftDataVector, rightDataVector, leftPos, rightPos); + executeNestedOperation(isGreaterThan, leftDataVector, rightDataVector, leftPos, + rightPos); if (!isGreaterThan) { - executeNestedOperation( - isEqual, leftDataVector, rightDataVector, leftPos, rightPos); + executeNestedOperation(isEqual, leftDataVector, rightDataVector, leftPos, + rightPos); } else { isEqual = false; } @@ -182,8 +182,8 @@ void GreaterThan::operation(const list_entry_t& left, const list_entry_t& right, for (auto i = 0u; i < commonLength; i++) { auto leftPos = left.offset + i; auto rightPos = right.offset + i; - executeNestedGreaterThan( - result, isEqual, leftDataVector, rightDataVector, leftPos, rightPos); + executeNestedGreaterThan(result, isEqual, leftDataVector, rightDataVector, leftPos, + rightPos); if (result || (!result && !isEqual)) { return; } diff --git a/src/function/find_function.cpp b/src/function/find_function.cpp index df9f58fedaf..7714d826cd2 100644 --- a/src/function/find_function.cpp +++ b/src/function/find_function.cpp @@ -92,8 +92,8 @@ int64_t Find::genericFind(const uint8_t* haystack, uint32_t haystackLen, const u // Returns the position of the first occurrence of needle in the haystack. If haystack doesn't // contain needle, it returns -1. -int64_t Find::find( - const uint8_t* haystack, uint32_t haystackLen, const uint8_t* needle, uint32_t needleLen) { +int64_t Find::find(const uint8_t* haystack, uint32_t haystackLen, const uint8_t* needle, + uint32_t needleLen) { auto firstMatchCharPos = (uint8_t*)memchr(haystack, needle[0], haystackLen); if (firstMatchCharPos == nullptr) { return -1; @@ -104,25 +104,25 @@ int64_t Find::find( case 1: return firstMatchCharOffset; case 2: - return alignedNeedleSizeFind( - firstMatchCharPos, numCharsToMatch, needle, firstMatchCharOffset); + return alignedNeedleSizeFind(firstMatchCharPos, numCharsToMatch, needle, + firstMatchCharOffset); case 3: - return unalignedNeedleSizeFind( - firstMatchCharPos, numCharsToMatch, needle, 3, firstMatchCharOffset); + return unalignedNeedleSizeFind(firstMatchCharPos, numCharsToMatch, needle, 3, + firstMatchCharOffset); case 4: - return alignedNeedleSizeFind( - firstMatchCharPos, numCharsToMatch, needle, firstMatchCharOffset); + return alignedNeedleSizeFind(firstMatchCharPos, numCharsToMatch, needle, + firstMatchCharOffset); case 5: case 6: case 7: - return unalignedNeedleSizeFind( - firstMatchCharPos, numCharsToMatch, needle, needleLen, firstMatchCharOffset); + return unalignedNeedleSizeFind(firstMatchCharPos, numCharsToMatch, needle, + needleLen, firstMatchCharOffset); case 8: - return alignedNeedleSizeFind( - firstMatchCharPos, numCharsToMatch, needle, firstMatchCharOffset); + return alignedNeedleSizeFind(firstMatchCharPos, numCharsToMatch, needle, + firstMatchCharOffset); default: - return genericFind( - firstMatchCharPos, numCharsToMatch, needle, needleLen, firstMatchCharOffset); + return genericFind(firstMatchCharPos, numCharsToMatch, needle, needleLen, + firstMatchCharOffset); } } diff --git a/src/function/function_collection.cpp b/src/function/function_collection.cpp new file mode 100644 index 00000000000..60179cadedc --- /dev/null +++ b/src/function/function_collection.cpp @@ -0,0 +1,208 @@ +#include "function/function_collection.h" + +#include "function/aggregate/collect.h" +#include "function/aggregate/count.h" +#include "function/aggregate/count_star.h" +#include "function/arithmetic/vector_arithmetic_functions.h" +#include "function/array/vector_array_functions.h" +#include "function/blob/vector_blob_functions.h" +#include "function/cast/vector_cast_functions.h" +#include "function/comparison/vector_comparison_functions.h" +#include "function/date/vector_date_functions.h" +#include "function/interval/vector_interval_functions.h" +#include "function/list/vector_list_functions.h" +#include "function/map/vector_map_functions.h" +#include "function/path/vector_path_functions.h" +#include "function/rdf/vector_rdf_functions.h" +#include "function/schema/vector_node_rel_functions.h" +#include "function/string/vector_string_functions.h" +#include "function/struct/vector_struct_functions.h" +#include "function/table/call_functions.h" +#include "function/timestamp/vector_timestamp_functions.h" +#include "function/union/vector_union_functions.h" +#include "function/uuid/vector_uuid_functions.h" +#include "processor/operator/persistent/reader/csv/parallel_csv_reader.h" +#include "processor/operator/persistent/reader/csv/serial_csv_reader.h" +#include "processor/operator/persistent/reader/npy/npy_reader.h" +#include "processor/operator/persistent/reader/parquet/parquet_reader.h" +#include "processor/operator/persistent/reader/rdf/rdf_scan.h" +#include "processor/operator/table_scan/ftable_scan_function.h" + +using namespace kuzu::processor; + +namespace kuzu { +namespace function { + +#define SCALAR_FUNCTION(_PARAM) \ + { _PARAM::getFunctionSet, _PARAM::name, CatalogEntryType::SCALAR_FUNCTION_ENTRY } +#define SCALAR_FUNCTION_ALIAS(_PARAM) \ + { _PARAM::getFunctionSet, _PARAM::alias, CatalogEntryType::SCALAR_FUNCTION_ENTRY } +#define REWRITE_FUNCTION(_PARAM) \ + { _PARAM::getFunctionSet, _PARAM::name, CatalogEntryType::REWRITE_FUNCTION_ENTRY } +#define AGGREGATE_FUNCTION(_PARAM) \ + { _PARAM::getFunctionSet, _PARAM::name, CatalogEntryType::AGGREGATE_FUNCTION_ENTRY } +#define TABLE_FUNCTION(_PARAM) \ + { _PARAM::getFunctionSet, _PARAM::name, CatalogEntryType::TABLE_FUNCTION_ENTRY } +#define FINAL_FUNCTION \ + { nullptr, nullptr, CatalogEntryType::SCALAR_FUNCTION_ENTRY } + +FunctionCollection* FunctionCollection::getFunctions() { + static FunctionCollection functions[] = { + + // Arithmetic Functions + SCALAR_FUNCTION(AddFunction), SCALAR_FUNCTION(SubtractFunction), + SCALAR_FUNCTION(MultiplyFunction), SCALAR_FUNCTION(DivideFunction), + SCALAR_FUNCTION(ModuloFunction), SCALAR_FUNCTION(PowerFunction), + SCALAR_FUNCTION(AbsFunction), SCALAR_FUNCTION(AcosFunction), SCALAR_FUNCTION(AsinFunction), + SCALAR_FUNCTION(AtanFunction), SCALAR_FUNCTION(Atan2Function), + SCALAR_FUNCTION(BitwiseXorFunction), SCALAR_FUNCTION(BitwiseAndFunction), + SCALAR_FUNCTION(BitwiseOrFunction), SCALAR_FUNCTION(BitShiftLeftFunction), + SCALAR_FUNCTION(BitShiftRightFunction), SCALAR_FUNCTION(CbrtFunction), + SCALAR_FUNCTION(CeilFunction), SCALAR_FUNCTION_ALIAS(CeilFunction), + SCALAR_FUNCTION(CosFunction), SCALAR_FUNCTION(CotFunction), + SCALAR_FUNCTION(DegreesFunction), SCALAR_FUNCTION(EvenFunction), + SCALAR_FUNCTION(FactorialFunction), SCALAR_FUNCTION(FloorFunction), + SCALAR_FUNCTION(GammaFunction), SCALAR_FUNCTION(LgammaFunction), + SCALAR_FUNCTION(LnFunction), SCALAR_FUNCTION(LogFunction), + SCALAR_FUNCTION_ALIAS(LogFunction), SCALAR_FUNCTION(Log2Function), + SCALAR_FUNCTION(NegateFunction), SCALAR_FUNCTION(PiFunction), + SCALAR_FUNCTION_ALIAS(PowerFunction), SCALAR_FUNCTION(RadiansFunction), + SCALAR_FUNCTION(RoundFunction), SCALAR_FUNCTION(SinFunction), SCALAR_FUNCTION(SignFunction), + SCALAR_FUNCTION(SqrtFunction), SCALAR_FUNCTION(TanFunction), + + // String Functions + SCALAR_FUNCTION(ArrayExtractFunction), SCALAR_FUNCTION(ConcatFunction), + SCALAR_FUNCTION(ContainsFunction), SCALAR_FUNCTION(LowerFunction), + SCALAR_FUNCTION_ALIAS(LowerFunction), SCALAR_FUNCTION(LeftFunction), + SCALAR_FUNCTION(LpadFunction), SCALAR_FUNCTION(LtrimFunction), + SCALAR_FUNCTION(StartsWithFunction), SCALAR_FUNCTION_ALIAS(StartsWithFunction), + SCALAR_FUNCTION(RepeatFunction), SCALAR_FUNCTION(ReverseFunction), + SCALAR_FUNCTION(RightFunction), SCALAR_FUNCTION(RpadFunction), + SCALAR_FUNCTION(RtrimFunction), SCALAR_FUNCTION(SubStrFunction), + SCALAR_FUNCTION_ALIAS(SubStrFunction), SCALAR_FUNCTION(EndsWithFunction), + SCALAR_FUNCTION_ALIAS(EndsWithFunction), SCALAR_FUNCTION(TrimFunction), + SCALAR_FUNCTION(UpperFunction), SCALAR_FUNCTION_ALIAS(UpperFunction), + SCALAR_FUNCTION(RegexpFullMatchFunction), SCALAR_FUNCTION(RegexpMatchesFunction), + SCALAR_FUNCTION(RegexpReplaceFunction), SCALAR_FUNCTION(RegexpExtractFunction), + SCALAR_FUNCTION(RegexpExtractAllFunction), SCALAR_FUNCTION(LevenshteinFunction), + SCALAR_FUNCTION(InitcapFunction), + + // Array Functions + SCALAR_FUNCTION(ArrayValueFunction), SCALAR_FUNCTION(ArrayCrossProductFunction), + SCALAR_FUNCTION(ArrayCosineSimilarityFunction), SCALAR_FUNCTION(ArrayDistanceFunction), + SCALAR_FUNCTION(ArrayInnerProductFunction), SCALAR_FUNCTION(ArrayDotProductFunction), + + // List functions + SCALAR_FUNCTION(ListCreationFunction), SCALAR_FUNCTION(ListRangeFunction), + SCALAR_FUNCTION(ListExtractFunction), SCALAR_FUNCTION_ALIAS(ListExtractFunction), + SCALAR_FUNCTION(ListConcatFunction), SCALAR_FUNCTION_ALIAS(ListConcatFunction), + SCALAR_FUNCTION(ArrayConcatFunction), SCALAR_FUNCTION_ALIAS(ArrayConcatFunction), + SCALAR_FUNCTION(ListAppendFunction), SCALAR_FUNCTION(ArrayAppendFunction), + SCALAR_FUNCTION_ALIAS(ArrayAppendFunction), SCALAR_FUNCTION(ListPrependFunction), + SCALAR_FUNCTION(ArrayPrependFunction), SCALAR_FUNCTION_ALIAS(ArrayPrependFunction), + SCALAR_FUNCTION(ListPositionFunction), SCALAR_FUNCTION_ALIAS(ListPositionFunction), + SCALAR_FUNCTION(ArrayPositionFunction), SCALAR_FUNCTION_ALIAS(ArrayPositionFunction), + SCALAR_FUNCTION(ListContainsFunction), SCALAR_FUNCTION_ALIAS(ListContainsFunction), + SCALAR_FUNCTION(ArrayContainsFunction), SCALAR_FUNCTION_ALIAS(ArrayContainsFunction), + SCALAR_FUNCTION(ListSliceFunction), SCALAR_FUNCTION(ArraySliceFunction), + SCALAR_FUNCTION(ListSortFunction), SCALAR_FUNCTION(ListReverseSortFunction), + SCALAR_FUNCTION(ListSumFunction), SCALAR_FUNCTION(ListProductFunction), + SCALAR_FUNCTION(ListDistinctFunction), SCALAR_FUNCTION(ListUniqueFunction), + SCALAR_FUNCTION(ListAnyValueFunction), SCALAR_FUNCTION(ListReverseFunction), + SCALAR_FUNCTION(SizeFunction), + + // Cast functions + SCALAR_FUNCTION(CastToDateFunction), SCALAR_FUNCTION_ALIAS(CastToDateFunction), + SCALAR_FUNCTION(CastToTimestampFunction), SCALAR_FUNCTION(CastToIntervalFunction), + SCALAR_FUNCTION_ALIAS(CastToIntervalFunction), SCALAR_FUNCTION(CastToStringFunction), + SCALAR_FUNCTION_ALIAS(CastToStringFunction), SCALAR_FUNCTION(CastToBlobFunction), + SCALAR_FUNCTION_ALIAS(CastToBlobFunction), SCALAR_FUNCTION(CastToUUIDFunction), + SCALAR_FUNCTION_ALIAS(CastToUUIDFunction), SCALAR_FUNCTION(CastToDoubleFunction), + SCALAR_FUNCTION(CastToFloatFunction), SCALAR_FUNCTION(CastToSerialFunction), + SCALAR_FUNCTION(CastToInt64Function), SCALAR_FUNCTION(CastToInt32Function), + SCALAR_FUNCTION(CastToInt16Function), SCALAR_FUNCTION(CastToInt8Function), + SCALAR_FUNCTION(CastToUInt64Function), SCALAR_FUNCTION(CastToUInt32Function), + SCALAR_FUNCTION(CastToUInt16Function), SCALAR_FUNCTION(CastToUInt8Function), + SCALAR_FUNCTION(CastToInt128Function), SCALAR_FUNCTION(CastToBoolFunction), + SCALAR_FUNCTION(CastAnyFunction), + + // Comparison functions + SCALAR_FUNCTION(EqualsFunction), SCALAR_FUNCTION(NotEqualsFunction), + SCALAR_FUNCTION(GreaterThanFunction), SCALAR_FUNCTION(GreaterThanEqualsFunction), + SCALAR_FUNCTION(LessThanFunction), SCALAR_FUNCTION(LessThanEqualsFunction), + + // Date functions + SCALAR_FUNCTION(DatePartFunction), SCALAR_FUNCTION_ALIAS(DatePartFunction), + SCALAR_FUNCTION(DateTruncFunction), SCALAR_FUNCTION_ALIAS(DateTruncFunction), + SCALAR_FUNCTION(DayNameFunction), SCALAR_FUNCTION(GreatestFunction), + SCALAR_FUNCTION(LastDayFunction), SCALAR_FUNCTION(LeastFunction), + SCALAR_FUNCTION(MakeDateFunction), SCALAR_FUNCTION(MonthNameFunction), + + // Timestamp functions + SCALAR_FUNCTION(CenturyFunction), SCALAR_FUNCTION(EpochMsFunction), + SCALAR_FUNCTION(ToTimestampFunction), + + // Interval functions + SCALAR_FUNCTION(ToYearsFunction), SCALAR_FUNCTION(ToMonthsFunction), + SCALAR_FUNCTION(ToDaysFunction), SCALAR_FUNCTION(ToHoursFunction), + SCALAR_FUNCTION(ToMinutesFunction), SCALAR_FUNCTION(ToSecondsFunction), + SCALAR_FUNCTION(ToMillisecondsFunction), SCALAR_FUNCTION(ToMicrosecondsFunction), + + // Blob functions + SCALAR_FUNCTION(OctetLengthFunctions), SCALAR_FUNCTION(EncodeFunctions), + SCALAR_FUNCTION(DecodeFunctions), + + // UUID functions + SCALAR_FUNCTION(GenRandomUUIDFunction), + + // Struct functions + SCALAR_FUNCTION(StructPackFunctions), SCALAR_FUNCTION(StructExtractFunctions), + + // Map functions + SCALAR_FUNCTION(MapCreationFunctions), SCALAR_FUNCTION(MapExtractFunctions), + SCALAR_FUNCTION_ALIAS(MapExtractFunctions), SCALAR_FUNCTION_ALIAS(SizeFunction), + SCALAR_FUNCTION(MapKeysFunctions), SCALAR_FUNCTION(MapValuesFunctions), + + // Union functions + SCALAR_FUNCTION(UnionValueFunction), SCALAR_FUNCTION(UnionTagFunction), + SCALAR_FUNCTION(UnionExtractFunction), + + // Node/rel functions + SCALAR_FUNCTION(OffsetFunction), REWRITE_FUNCTION(IDFunction), + + // Path functions + SCALAR_FUNCTION(NodesFunction), SCALAR_FUNCTION(RelsFunction), + SCALAR_FUNCTION(PropertiesFunction), SCALAR_FUNCTION(IsTrailFunction), + SCALAR_FUNCTION(IsACyclicFunction), + + // Rdf functions + SCALAR_FUNCTION(RDFTypeFunction), SCALAR_FUNCTION(ValidatePredicateFunction), + + // Aggregate functions + AGGREGATE_FUNCTION(CountStarFunction), AGGREGATE_FUNCTION(CountFunction), + AGGREGATE_FUNCTION(AggregateSumFunction), AGGREGATE_FUNCTION(AggregateAvgFunction), + AGGREGATE_FUNCTION(AggregateMinFunction), AGGREGATE_FUNCTION(AggregateMaxFunction), + AGGREGATE_FUNCTION(CollectFunction), + + // Table functions + TABLE_FUNCTION(CurrentSettingFunction), TABLE_FUNCTION(DBVersionFunction), + TABLE_FUNCTION(ShowTablesFunction), TABLE_FUNCTION(TableInfoFunction), + TABLE_FUNCTION(ShowConnectionFunction), TABLE_FUNCTION(StorageInfoFunction), + + // Read functions + TABLE_FUNCTION(ParquetScanFunction), TABLE_FUNCTION(NpyScanFunction), + TABLE_FUNCTION(SerialCSVScan), TABLE_FUNCTION(ParallelCSVScan), + TABLE_FUNCTION(RdfResourceScan), TABLE_FUNCTION(RdfLiteralScan), + TABLE_FUNCTION(RdfResourceTripleScan), TABLE_FUNCTION(RdfLiteralTripleScan), + TABLE_FUNCTION(RdfAllTripleScan), TABLE_FUNCTION(RdfResourceInMemScan), + TABLE_FUNCTION(RdfLiteralInMemScan), TABLE_FUNCTION(RdfResourceTripleInMemScan), + TABLE_FUNCTION(RdfLiteralTripleInMemScan), TABLE_FUNCTION(FTableScan), + + // End of array + FINAL_FUNCTION}; + + return functions; +} + +} // namespace function +} // namespace kuzu diff --git a/src/function/pattern/CMakeLists.txt b/src/function/pattern/CMakeLists.txt new file mode 100644 index 00000000000..4857f7f50d3 --- /dev/null +++ b/src/function/pattern/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(kuzu_function_pattern + OBJECT + id_function.cpp) + +set(ALL_OBJECT_FILES + ${ALL_OBJECT_FILES} $ + PARENT_SCOPE) diff --git a/src/function/pattern/id_function.cpp b/src/function/pattern/id_function.cpp new file mode 100644 index 00000000000..0495e44bc28 --- /dev/null +++ b/src/function/pattern/id_function.cpp @@ -0,0 +1,49 @@ +#include "binder/expression/expression_util.h" +#include "binder/expression/node_expression.h" +#include "binder/expression/rel_expression.h" +#include "binder/expression_binder.h" +#include "common/cast.h" +#include "common/types/value/value.h" +#include "function/rewrite_function.h" +#include "function/schema/vector_node_rel_functions.h" +#include "function/struct/vector_struct_functions.h" + +using namespace kuzu::common; +using namespace kuzu::binder; + +namespace kuzu { +namespace function { + +static std::shared_ptr rewriteFunc(const expression_vector& params, + ExpressionBinder* binder) { + KU_ASSERT(params.size() == 1); + auto param = params[0].get(); + if (ExpressionUtil::isNodePattern(*param)) { + auto node = ku_dynamic_cast(param); + return node->getInternalID(); + } + if (ExpressionUtil::isRelPattern(*param)) { + auto rel = ku_dynamic_cast(param); + return rel->getPropertyExpression(InternalKeyword::ID); + } + // Bind as struct_extract(param, "_id") + auto key = Value(LogicalType::STRING(), InternalKeyword::ID); + auto keyExpr = binder->createLiteralExpression(key.copy()); + auto newParams = expression_vector{params[0], keyExpr}; + return binder->bindScalarFunctionExpression(newParams, StructExtractFunctions::name); +} + +function_set IDFunction::getFunctionSet() { + function_set functionSet; + auto inputTypes = + std::vector{LogicalTypeID::NODE, LogicalTypeID::REL, LogicalTypeID::STRUCT}; + for (auto& inputType : inputTypes) { + auto function = std::make_unique(InternalKeyword::ID, + std::vector{inputType}, rewriteFunc); + functionSet.push_back(std::move(function)); + } + return functionSet; +} + +} // namespace function +} // namespace kuzu diff --git a/src/function/scalar_macro_function.cpp b/src/function/scalar_macro_function.cpp index 61f82d62318..618ed034033 100644 --- a/src/function/scalar_macro_function.cpp +++ b/src/function/scalar_macro_function.cpp @@ -1,9 +1,8 @@ #include "function/scalar_macro_function.h" -#include - #include "common/serializer/deserializer.h" #include "common/serializer/serializer.h" +#include "common/string_format.h" #include "common/string_utils.h" using namespace kuzu::common; @@ -25,8 +24,8 @@ std::unique_ptr ScalarMacroFunction::copy() const { for (auto& defaultArg : defaultArgs) { defaultArgsCopy.emplace_back(defaultArg.first, defaultArg.second->copy()); } - return std::make_unique( - expression->copy(), positionalArgs, std::move(defaultArgsCopy)); + return std::make_unique(expression->copy(), positionalArgs, + std::move(defaultArgsCopy)); } void ScalarMacroFunction::serialize(Serializer& serializer) const { @@ -54,12 +53,11 @@ std::unique_ptr ScalarMacroFunction::deserialize(Deserializ auto val = ParsedExpression::deserialize(deserializer); defaultArgs.emplace_back(std::move(key), std::move(val)); } - return std::make_unique( - std::move(expression), std::move(positionalArgs), std::move(defaultArgs)); + return std::make_unique(std::move(expression), std::move(positionalArgs), + std::move(defaultArgs)); } std::string ScalarMacroFunction::toCypher(const std::string& name) const { - std::stringstream ss; std::vector paramStrings; for (auto& param : positionalArgs) { paramStrings.push_back(param); @@ -67,9 +65,8 @@ std::string ScalarMacroFunction::toCypher(const std::string& name) const { for (auto& defaultParam : defaultArgs) { paramStrings.push_back(defaultParam.first + ":=" + defaultParam.second->toString()); } - ss << "CREATE MACRO " << name << "(" << StringUtils::join(paramStrings, ",") << ") AS " - << expression->toString(); - return ss.str(); + return stringFormat("CREATE MACRO {} ({}) AS {}", name, StringUtils::join(paramStrings, ","), + expression->toString()); } } // namespace function } // namespace kuzu diff --git a/src/function/table/call/current_setting.cpp b/src/function/table/call/current_setting.cpp index 5008229f8db..70da8da0b29 100644 --- a/src/function/table/call/current_setting.cpp +++ b/src/function/table/call/current_setting.cpp @@ -16,8 +16,8 @@ struct CurrentSettingBindData final : public CallTableFuncBindData { result{std::move(result)} {} std::unique_ptr copy() const override { - return std::make_unique( - result, columnTypes, columnNames, maxOffset); + return std::make_unique(result, columnTypes, columnNames, + maxOffset); } }; @@ -37,8 +37,8 @@ static common::offset_t tableFunc(TableFuncInput& data, TableFuncOutput& output) return 1; } -static std::unique_ptr bindFunc( - ClientContext* context, TableFuncBindInput* input) { +static std::unique_ptr bindFunc(ClientContext* context, + TableFuncBindInput* input) { auto optionName = input->inputs[0].getValue(); std::vector columnNames; std::vector columnTypes; @@ -51,9 +51,8 @@ static std::unique_ptr bindFunc( function_set CurrentSettingFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(CURRENT_SETTING_FUNC_NAME, tableFunc, - bindFunc, initSharedState, initEmptyLocalState, - std::vector{LogicalTypeID::STRING})); + functionSet.push_back(std::make_unique(name, tableFunc, bindFunc, + initSharedState, initEmptyLocalState, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/function/table/call/db_version.cpp b/src/function/table/call/db_version.cpp index 3c5b21785e4..44255980902 100644 --- a/src/function/table/call/db_version.cpp +++ b/src/function/table/call/db_version.cpp @@ -25,13 +25,13 @@ static std::unique_ptr bindFunc(ClientContext*, TableFuncBind std::vector returnTypes; returnColumnNames.emplace_back("version"); returnTypes.emplace_back(*LogicalType::STRING()); - return std::make_unique( - std::move(returnTypes), std::move(returnColumnNames), 1 /* one row result */); + return std::make_unique(std::move(returnTypes), + std::move(returnColumnNames), 1 /* one row result */); } function_set DBVersionFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(DB_VERSION_FUNC_NAME, tableFunc, bindFunc, + functionSet.push_back(std::make_unique(name, tableFunc, bindFunc, initSharedState, initEmptyLocalState, std::vector{})); return functionSet; } diff --git a/src/function/table/call/show_connection.cpp b/src/function/table/call/show_connection.cpp index c0d7e4b505f..6dc8bc8f308 100644 --- a/src/function/table/call/show_connection.cpp +++ b/src/function/table/call/show_connection.cpp @@ -23,8 +23,8 @@ struct ShowConnectionBindData : public CallTableFuncBindData { context{context}, tableEntry{tableEntry} {} inline std::unique_ptr copy() const override { - return std::make_unique( - context, tableEntry, columnTypes, columnNames, maxOffset); + return std::make_unique(context, tableEntry, columnTypes, + columnNames, maxOffset); } }; @@ -58,8 +58,8 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output auto vectorPos = 0u; switch (tableEntry->getTableType()) { case TableType::REL: { - outputRelTableConnection( - srcVector, dstVector, vectorPos, bindData->context, tableEntry->getTableID()); + outputRelTableConnection(srcVector, dstVector, vectorPos, bindData->context, + tableEntry->getTableID()); vectorPos++; } break; case TableType::REL_GROUP: { @@ -78,8 +78,8 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output return vectorPos; } -static std::unique_ptr bindFunc( - ClientContext* context, TableFuncBindInput* input) { +static std::unique_ptr bindFunc(ClientContext* context, + TableFuncBindInput* input) { std::vector columnNames; std::vector columnTypes; // Special case here Due to any -> string, but lack implicit cast @@ -103,8 +103,8 @@ static std::unique_ptr bindFunc( auto relGroupEntry = ku_dynamic_cast(tableEntry); maxOffset = relGroupEntry->getRelTableIDs().size(); } - return std::make_unique( - context, tableEntry, std::move(columnTypes), std::move(columnNames), maxOffset); + return std::make_unique(context, tableEntry, std::move(columnTypes), + std::move(columnNames), maxOffset); } function_set ShowConnectionFunction::getFunctionSet() { diff --git a/src/function/table/call/show_tables.cpp b/src/function/table/call/show_tables.cpp index 98acca07d25..752184a7898 100644 --- a/src/function/table/call/show_tables.cpp +++ b/src/function/table/call/show_tables.cpp @@ -1,4 +1,5 @@ #include "catalog/catalog.h" +#include "catalog/catalog_entry/table_catalog_entry.h" #include "function/table/call_functions.h" using namespace kuzu::common; @@ -42,8 +43,8 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output return numTablesToOutput; } -static std::unique_ptr bindFunc( - main::ClientContext* context, TableFuncBindInput*) { +static std::unique_ptr bindFunc(main::ClientContext* context, + TableFuncBindInput*) { std::vector columnNames; std::vector columnTypes; columnNames.emplace_back("name"); @@ -54,14 +55,14 @@ static std::unique_ptr bindFunc( columnTypes.emplace_back(*LogicalType::STRING()); auto tableEntries = context->getCatalog()->getTableEntries(context->getTx()); auto numTables = context->getCatalog()->getTableCount(context->getTx()); - return std::make_unique( - std::move(tableEntries), std::move(columnTypes), std::move(columnNames), numTables); + return std::make_unique(std::move(tableEntries), std::move(columnTypes), + std::move(columnNames), numTables); } function_set ShowTablesFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(SHOW_TABLES_FUNC_NAME, tableFunc, - bindFunc, initSharedState, initEmptyLocalState, std::vector{})); + functionSet.push_back(std::make_unique(name, tableFunc, bindFunc, + initSharedState, initEmptyLocalState, std::vector{})); return functionSet; } diff --git a/src/function/table/call/storage_info.cpp b/src/function/table/call/storage_info.cpp index 6cdd3026345..9693f87d1a5 100644 --- a/src/function/table/call/storage_info.cpp +++ b/src/function/table/call/storage_info.cpp @@ -3,9 +3,10 @@ #include "function/table/bind_input.h" #include "function/table/call_functions.h" #include "storage/storage_manager.h" +#include "storage/store/list_column.h" +#include "storage/store/node_table.h" #include "storage/store/string_column.h" #include "storage/store/struct_column.h" -#include "storage/store/var_list_column.h" using namespace kuzu::common; using namespace kuzu::catalog; @@ -48,8 +49,6 @@ struct StorageInfoSharedState final : public CallFuncSharedState { columns.push_back(relTable->getCSRLengthColumn(RelDataDirection::FWD)); columns.push_back(relTable->getCSROffsetColumn(RelDataDirection::BWD)); columns.push_back(relTable->getCSRLengthColumn(RelDataDirection::BWD)); - columns.push_back(relTable->getAdjColumn(RelDataDirection::FWD)); - columns.push_back(relTable->getAdjColumn(RelDataDirection::BWD)); for (auto columnID = 0u; columnID < relTable->getNumColumns(); columnID++) { auto column = relTable->getColumn(columnID, RelDataDirection::FWD); auto collectedColumns = collectColumns(column); @@ -86,9 +85,9 @@ struct StorageInfoSharedState final : public CallFuncSharedState { result.push_back(dictionary.getDataColumn()); result.push_back(dictionary.getOffsetColumn()); } break; - case PhysicalTypeID::VAR_LIST: { - auto varListColumn = ku_dynamic_cast(column); - result.push_back(varListColumn->getDataColumn()); + case PhysicalTypeID::LIST: { + auto listColumn = ku_dynamic_cast(column); + result.push_back(listColumn->getDataColumn()); } break; default: { // DO NOTHING. @@ -109,8 +108,8 @@ struct StorageInfoBindData final : public CallTableFuncBindData { tableEntry{tableEntry}, table{table}, context{context} {} inline std::unique_ptr copy() const override { - return std::make_unique( - columnTypes, columnNames, tableEntry, table, context); + return std::make_unique(columnTypes, columnNames, tableEntry, table, + context); } }; @@ -123,8 +122,8 @@ static std::unique_ptr initStorageInfoSharedState( TableFunctionInitInput& input) { auto storageInfoBindData = ku_dynamic_cast(input.bindData); - return std::make_unique( - storageInfoBindData->table, storageInfoBindData->maxOffset); + return std::make_unique(storageInfoBindData->table, + storageInfoBindData->maxOffset); } static void appendColumnChunkStorageInfo(node_group_idx_t nodeGroupIdx, @@ -146,7 +145,7 @@ static void appendColumnChunkStorageInfo(node_group_idx_t nodeGroupIdx, static void appendStorageInfoForColumn(StorageInfoLocalState* localState, std::string tableType, const Column* column, DataChunk& outputChunk, ClientContext* context) { - auto numNodeGroups = column->getNumNodeGroups(&transaction::DUMMY_READ_TRANSACTION); + auto numNodeGroups = column->getNumNodeGroups(context->getTx()); for (auto nodeGroupIdx = 0u; nodeGroupIdx < numNodeGroups; nodeGroupIdx++) { if (outputChunk.state->selVector->selectedSize == DEFAULT_VECTOR_CAPACITY) { localState->dataChunkCollection->append(outputChunk); @@ -167,16 +166,16 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output while (true) { if (localState->currChunkIdx < localState->dataChunkCollection->getNumChunks()) { // Copy from local state chunk. - auto chunk = localState->dataChunkCollection->getChunk(localState->currChunkIdx); - auto numValuesToOutput = chunk->state->selVector->selectedSize; + auto& chunk = localState->dataChunkCollection->getChunkUnsafe(localState->currChunkIdx); + auto numValuesToOutput = chunk.state->selVector->selectedSize; for (auto columnIdx = 0u; columnIdx < dataChunk.getNumValueVectors(); columnIdx++) { - auto localVector = chunk->getValueVector(columnIdx); + auto localVector = chunk.getValueVector(columnIdx); auto outputVector = dataChunk.getValueVector(columnIdx); for (auto i = 0u; i < numValuesToOutput; i++) { outputVector->copyFromVectorData(i, localVector.get(), i); } } - dataChunk.state->selVector->resetSelectorToUnselectedWithSize(numValuesToOutput); + dataChunk.state->selVector->setToUnfiltered(numValuesToOutput); localState->currChunkIdx++; return numValuesToOutput; } @@ -199,8 +198,8 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output } } -static std::unique_ptr bindFunc( - ClientContext* context, TableFuncBindInput* input) { +static std::unique_ptr bindFunc(ClientContext* context, + TableFuncBindInput* input) { std::vector columnNames = {"node_group_id", "column_name", "data_type", "table_type", "start_page_idx", "num_pages", "num_values", "compression"}; std::vector columnTypes; @@ -220,18 +219,16 @@ static std::unique_ptr bindFunc( auto tableID = catalog->getTableID(context->getTx(), tableName); auto tableEntry = catalog->getTableCatalogEntry(context->getTx(), tableID); auto storageManager = context->getStorageManager(); - auto table = tableEntry->getTableType() == TableType::NODE ? - reinterpret_cast(storageManager->getNodeTable(tableID)) : - reinterpret_cast(storageManager->getRelTable(tableID)); - return std::make_unique( - std::move(columnTypes), std::move(columnNames), tableEntry, table, context); + auto table = storageManager->getTable(tableID); + return std::make_unique(std::move(columnTypes), std::move(columnNames), + tableEntry, table, context); } function_set StorageInfoFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(STORAGE_INFO_FUNC_NAME, tableFunc, - bindFunc, initStorageInfoSharedState, initLocalState, - std::vector{LogicalTypeID::STRING})); + functionSet.push_back( + std::make_unique(name, tableFunc, bindFunc, initStorageInfoSharedState, + initLocalState, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/function/table/call/table_info.cpp b/src/function/table/call/table_info.cpp index 616848fc81c..88122cdb9e0 100644 --- a/src/function/table/call/table_info.cpp +++ b/src/function/table/call/table_info.cpp @@ -46,8 +46,8 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output if (property->getName() == rdf::PID) { // Replace pid column with (virtual) iri column. dataChunk.getValueVector(0)->setValue(vectorPos, -1); - dataChunk.getValueVector(1)->setValue( - vectorPos, std::string(rdf::IRI) + " (Virtual)"); + dataChunk.getValueVector(1)->setValue(vectorPos, + std::string(rdf::IRI) + " (Virtual)"); dataChunk.getValueVector(2)->setValue(vectorPos, LogicalType::STRING()->toString()); vectorPos++; continue; @@ -61,16 +61,16 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output auto nodeTableEntry = ku_dynamic_cast(tableEntry); auto primaryKeyID = nodeTableEntry->getPrimaryKeyPID(); - dataChunk.getValueVector(3)->setValue( - vectorPos, primaryKeyID == property->getPropertyID()); + dataChunk.getValueVector(3)->setValue(vectorPos, + primaryKeyID == property->getPropertyID()); } vectorPos++; } return vectorPos; } -static std::unique_ptr bindFunc( - main::ClientContext* context, TableFuncBindInput* input) { +static std::unique_ptr bindFunc(main::ClientContext* context, + TableFuncBindInput* input) { std::vector columnNames; std::vector columnTypes; auto tableName = input->inputs[0].getValue(); @@ -86,13 +86,13 @@ static std::unique_ptr bindFunc( columnNames.emplace_back("primary key"); columnTypes.push_back(*LogicalType::BOOL()); } - return std::make_unique( - tableEntry, std::move(columnTypes), std::move(columnNames), tableEntry->getNumProperties()); + return std::make_unique(tableEntry, std::move(columnTypes), + std::move(columnNames), tableEntry->getNumProperties()); } function_set TableInfoFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(TABLE_INFO_FUNC_NAME, tableFunc, bindFunc, + functionSet.push_back(std::make_unique(name, tableFunc, bindFunc, initSharedState, initEmptyLocalState, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/function/vector_arithmetic_functions.cpp b/src/function/vector_arithmetic_functions.cpp index 2fc12f016a1..bc201855d4a 100644 --- a/src/function/vector_arithmetic_functions.cpp +++ b/src/function/vector_arithmetic_functions.cpp @@ -1,6 +1,7 @@ #include "function/arithmetic/vector_arithmetic_functions.h" #include "common/types/date_t.h" +#include "common/types/int128_t.h" #include "common/types/interval_t.h" #include "common/types/timestamp_t.h" #include "function/arithmetic/abs.h" @@ -13,57 +14,173 @@ #include "function/arithmetic/subtract.h" #include "function/list/functions/list_concat_function.h" #include "function/list/vector_list_functions.h" -#include "function/string/functions/concat_function.h" +#include "function/scalar_function.h" +#include "function/string/vector_string_functions.h" using namespace kuzu::common; namespace kuzu { namespace function { +template +static void getUnaryExecFunc(LogicalTypeID operandTypeID, scalar_func_exec_t& func) { + switch (operandTypeID) { + case LogicalTypeID::SERIAL: + case LogicalTypeID::INT64: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::INT32: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::INT16: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::INT8: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::UINT64: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::UINT32: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::UINT16: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::UINT8: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::INT128: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::DOUBLE: { + func = ScalarFunction::UnaryExecFunction; + } break; + case LogicalTypeID::FLOAT: { + func = ScalarFunction::UnaryExecFunction; + } break; + default: + KU_UNREACHABLE; + } +} + +template +static void getBinaryExecFunc(LogicalTypeID operandTypeID, scalar_func_exec_t& func) { + switch (operandTypeID) { + case LogicalTypeID::SERIAL: + case LogicalTypeID::INT64: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::INT32: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::INT16: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::INT8: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::UINT64: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::UINT32: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::UINT16: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::UINT8: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::INT128: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::DOUBLE: { + func = ScalarFunction::BinaryExecFunction; + } break; + case LogicalTypeID::FLOAT: { + func = ScalarFunction::BinaryExecFunction; + } break; + default: + KU_UNREACHABLE; + } +} + +template +static std::unique_ptr getUnaryFunction(std::string name, + LogicalTypeID operandTypeID) { + function::scalar_func_exec_t execFunc; + getUnaryExecFunc(operandTypeID, execFunc); + return std::make_unique(std::move(name), + std::vector{operandTypeID}, operandTypeID, execFunc); +} + +template +static std::unique_ptr getUnaryFunction(std::string name, + LogicalTypeID operandTypeID, LogicalTypeID resultTypeID) { + return std::make_unique(std::move(name), + std::vector{operandTypeID}, resultTypeID, + ScalarFunction::UnaryExecFunction); +} + +template +static inline std::unique_ptr getBinaryFunction(std::string name, + LogicalTypeID operandTypeID) { + function::scalar_func_exec_t execFunc; + getBinaryExecFunc(operandTypeID, execFunc); + return std::make_unique(std::move(name), + std::vector{operandTypeID, operandTypeID}, operandTypeID, execFunc); +} + +template +static inline std::unique_ptr getBinaryFunction(std::string name, + LogicalTypeID operandTypeID, LogicalTypeID resultTypeID) { + return std::make_unique(std::move(name), + std::vector{operandTypeID, operandTypeID}, resultTypeID, + ScalarFunction::BinaryExecFunction); +} + function_set AddFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getBinaryFunction(ADD_FUNC_NAME, typeID)); + result.push_back(getBinaryFunction(name, typeID)); } // list + list -> list - result.push_back(std::make_unique(ADD_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::VAR_LIST}, - LogicalTypeID::VAR_LIST, + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::LIST}, LogicalTypeID::LIST, ScalarFunction::BinaryExecListStructFunction, nullptr, ListConcatFunction::bindFunc, false /* isVarlength*/)); // string + string -> string - result.push_back(std::make_unique(ADD_FUNC_NAME, - std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, - LogicalTypeID::STRING, - ScalarFunction::BinaryStringExecFunction)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, + LogicalTypeID::STRING, ConcatFunction::execFunc)); // interval + interval → interval - result.push_back(ArithmeticFunction::getBinaryFunction( - ADD_FUNC_NAME, LogicalTypeID::INTERVAL, LogicalTypeID::INTERVAL)); + result.push_back(getBinaryFunction(name, LogicalTypeID::INTERVAL, + LogicalTypeID::INTERVAL)); // date + int → date - result.push_back(make_unique(ADD_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE, LogicalTypeID::INT64}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); // int + date → date - result.push_back(make_unique(ADD_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::INT64, LogicalTypeID::DATE}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); // date + interval → date - result.push_back(make_unique(ADD_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE, LogicalTypeID::INTERVAL}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); // interval + date → date - result.push_back(make_unique(ADD_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::INTERVAL, LogicalTypeID::DATE}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); // timestamp + interval → timestamp - result.push_back(make_unique(ADD_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP, LogicalTypeID::INTERVAL}, LogicalTypeID::TIMESTAMP, ScalarFunction::BinaryExecFunction)); // interval + timestamp → timestamp - result.push_back(make_unique(ADD_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::INTERVAL, LogicalTypeID::TIMESTAMP}, LogicalTypeID::TIMESTAMP, ScalarFunction::BinaryExecFunction)); @@ -73,40 +190,38 @@ function_set AddFunction::getFunctionSet() { function_set SubtractFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - ArithmeticFunction::getBinaryFunction(SUBTRACT_FUNC_NAME, typeID)); + result.push_back(getBinaryFunction(name, typeID)); } // date - date → int64 - result.push_back(ArithmeticFunction::getBinaryFunction( - SUBTRACT_FUNC_NAME, LogicalTypeID::DATE, LogicalTypeID::INT64)); + result.push_back(getBinaryFunction(name, LogicalTypeID::DATE, + LogicalTypeID::INT64)); // date - integer → date - result.push_back(make_unique(SUBTRACT_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE, LogicalTypeID::INT64}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); // date - interval → date - result.push_back(make_unique(SUBTRACT_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE, LogicalTypeID::INTERVAL}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); // timestamp - timestamp → interval - result.push_back(ArithmeticFunction::getBinaryFunction( - SUBTRACT_FUNC_NAME, LogicalTypeID::TIMESTAMP, LogicalTypeID::INTERVAL)); + result.push_back(getBinaryFunction(name, + LogicalTypeID::TIMESTAMP, LogicalTypeID::INTERVAL)); // timestamp - interval → timestamp - result.push_back(make_unique(SUBTRACT_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP, LogicalTypeID::INTERVAL}, LogicalTypeID::TIMESTAMP, ScalarFunction::BinaryExecFunction)); // interval - interval → interval - result.push_back(ArithmeticFunction::getBinaryFunction( - SUBTRACT_FUNC_NAME, LogicalTypeID::INTERVAL, LogicalTypeID::INTERVAL)); + result.push_back(getBinaryFunction(name, + LogicalTypeID::INTERVAL, LogicalTypeID::INTERVAL)); return result; } function_set MultiplyFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - ArithmeticFunction::getBinaryFunction(MULTIPLY_FUNC_NAME, typeID)); + result.push_back(getBinaryFunction(name, typeID)); } return result; } @@ -114,10 +229,10 @@ function_set MultiplyFunction::getFunctionSet() { function_set DivideFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getBinaryFunction(DIVIDE_FUNC_NAME, typeID)); + result.push_back(getBinaryFunction(name, typeID)); } // interval / int → interval - result.push_back(make_unique(DIVIDE_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::INTERVAL, LogicalTypeID::INT64}, LogicalTypeID::INTERVAL, ScalarFunction::BinaryExecFunction)); @@ -127,7 +242,7 @@ function_set DivideFunction::getFunctionSet() { function_set ModuloFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getBinaryFunction(MODULO_FUNC_NAME, typeID)); + result.push_back(getBinaryFunction(name, typeID)); } return result; } @@ -135,15 +250,15 @@ function_set ModuloFunction::getFunctionSet() { function_set PowerFunction::getFunctionSet() { function_set result; // double ^ double -> double - result.push_back(ArithmeticFunction::getBinaryFunction( - POWER_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getBinaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set NegateFunction::getFunctionSet() { function_set result; for (auto& typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getUnaryFunction(NEGATE_FUNC_NAME, typeID)); + result.push_back(getUnaryFunction(name, typeID)); } return result; } @@ -151,7 +266,7 @@ function_set NegateFunction::getFunctionSet() { function_set AbsFunction::getFunctionSet() { function_set result; for (auto& typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getUnaryFunction(ABS_FUNC_NAME, typeID)); + result.push_back(getUnaryFunction(name, typeID)); } return result; } @@ -159,7 +274,7 @@ function_set AbsFunction::getFunctionSet() { function_set FloorFunction::getFunctionSet() { function_set result; for (auto& typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getUnaryFunction(FLOOR_FUNC_NAME, typeID)); + result.push_back(getUnaryFunction(name, typeID)); } return result; } @@ -167,159 +282,159 @@ function_set FloorFunction::getFunctionSet() { function_set CeilFunction::getFunctionSet() { function_set result; for (auto& typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(ArithmeticFunction::getUnaryFunction(CEIL_FUNC_NAME, typeID)); + result.push_back(getUnaryFunction(name, typeID)); } return result; } function_set SinFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - SIN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set CosFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - COS_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set TanFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - TAN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set CotFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - COT_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set AsinFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - ASIN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set AcosFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - ACOS_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set AtanFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - ATAN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set FactorialFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(FACTORIAL_FUNC_NAME, - std::vector{LogicalTypeID::INT64}, LogicalTypeID::INT64, - ScalarFunction::UnaryExecFunction)); + result.push_back( + make_unique(name, std::vector{LogicalTypeID::INT64}, + LogicalTypeID::INT64, ScalarFunction::UnaryExecFunction)); return result; } function_set SqrtFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - SQRT_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set CbrtFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - CBRT_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set GammaFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - GAMMA_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set LgammaFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - LGAMMA_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set LnFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - LN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set LogFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - LOG_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set Log2Function::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - LOG2_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set DegreesFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - DEGREES_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set RadiansFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - RADIANS_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set EvenFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - EVEN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set SignFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getUnaryFunction( - SIGN_FUNC_NAME, LogicalTypeID::INT64, LogicalTypeID::INT64)); - result.push_back(ArithmeticFunction::getUnaryFunction( - SIGN_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::INT64)); - result.push_back(ArithmeticFunction::getUnaryFunction( - SIGN_FUNC_NAME, LogicalTypeID::FLOAT, LogicalTypeID::INT64)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::INT64, LogicalTypeID::INT64)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::INT64)); + result.push_back( + getUnaryFunction(name, LogicalTypeID::FLOAT, LogicalTypeID::INT64)); return result; } function_set Atan2Function::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getBinaryFunction( - ATAN2_FUNC_NAME, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); + result.push_back( + getBinaryFunction(name, LogicalTypeID::DOUBLE, LogicalTypeID::DOUBLE)); return result; } function_set RoundFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(ROUND_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DOUBLE, LogicalTypeID::INT64}, LogicalTypeID::DOUBLE, ScalarFunction::BinaryExecFunction)); return result; @@ -327,42 +442,42 @@ function_set RoundFunction::getFunctionSet() { function_set BitwiseXorFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getBinaryFunction( - BITWISE_XOR_FUNC_NAME, LogicalTypeID::INT64, LogicalTypeID::INT64)); + result.push_back( + getBinaryFunction(name, LogicalTypeID::INT64, LogicalTypeID::INT64)); return result; } function_set BitwiseAndFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getBinaryFunction( - BITWISE_AND_FUNC_NAME, LogicalTypeID::INT64, LogicalTypeID::INT64)); + result.push_back( + getBinaryFunction(name, LogicalTypeID::INT64, LogicalTypeID::INT64)); return result; } function_set BitwiseOrFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getBinaryFunction( - BITWISE_OR_FUNC_NAME, LogicalTypeID::INT64, LogicalTypeID::INT64)); + result.push_back( + getBinaryFunction(name, LogicalTypeID::INT64, LogicalTypeID::INT64)); return result; } function_set BitShiftLeftFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getBinaryFunction( - BITSHIFT_LEFT_FUNC_NAME, LogicalTypeID::INT64, LogicalTypeID::INT64)); + result.push_back( + getBinaryFunction(name, LogicalTypeID::INT64, LogicalTypeID::INT64)); return result; } function_set BitShiftRightFunction::getFunctionSet() { function_set result; - result.push_back(ArithmeticFunction::getBinaryFunction( - BITSHIFT_RIGHT_FUNC_NAME, LogicalTypeID::INT64, LogicalTypeID::INT64)); + result.push_back(getBinaryFunction(name, LogicalTypeID::INT64, + LogicalTypeID::INT64)); return result; } function_set PiFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(PI_FUNC_NAME, std::vector{}, + result.push_back(make_unique(name, std::vector{}, LogicalTypeID::DOUBLE, ScalarFunction::ConstExecFunction)); return result; } diff --git a/src/function/vector_array_functions.cpp b/src/function/vector_array_functions.cpp new file mode 100644 index 00000000000..b2c6cfb49a0 --- /dev/null +++ b/src/function/vector_array_functions.cpp @@ -0,0 +1,172 @@ +#include "function/array/vector_array_functions.h" + +#include "common/exception/binder.h" +#include "function/array/functions/array_cosine_similarity.h" +#include "function/array/functions/array_cross_product.h" +#include "function/array/functions/array_distance.h" +#include "function/array/functions/array_inner_product.h" +#include "function/list/vector_list_functions.h" +#include "function/scalar_function.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace function { + +std::unique_ptr ArrayValueBindFunc(const binder::expression_vector& arguments, + Function* /*function*/) { + auto resultType = + LogicalType::ARRAY(ListCreationFunction::getChildType(arguments).copy(), arguments.size()); + return std::make_unique(std::move(resultType)); +} + +function_set ArrayValueFunction::getFunctionSet() { + function_set result; + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::ANY}, LogicalTypeID::ARRAY, + ListCreationFunction::execFunc, nullptr, ArrayValueBindFunc, true /* isVarLength */)); + return result; +} + +std::unique_ptr ArrayCrossProductBindFunc( + const binder::expression_vector& arguments, Function* function) { + auto leftType = arguments[0]->dataType; + auto rightType = arguments[1]->dataType; + if (leftType != rightType) { + throw BinderException( + stringFormat("{} requires both arrays to have the same element type and size of 3", + ArrayCrossProductFunction::name)); + } + scalar_func_exec_t execFunc; + switch (ArrayType::getChildType(&leftType)->getLogicalTypeID()) { + case LogicalTypeID::INT128: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + case LogicalTypeID::INT64: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + case LogicalTypeID::INT32: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + case LogicalTypeID::INT16: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + case LogicalTypeID::INT8: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + case LogicalTypeID::FLOAT: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + case LogicalTypeID::DOUBLE: + execFunc = ScalarFunction::BinaryExecListStructFunction>; + break; + default: + throw BinderException{ + stringFormat("{} can only be applied on array of floating points or integers", + ArrayCrossProductFunction::name)}; + } + ku_dynamic_cast(function)->execFunc = execFunc; + auto resultType = LogicalType::ARRAY(*ArrayType::getChildType(&leftType), + ArrayType::getNumElements(&leftType)); + return std::make_unique(std::move(resultType)); +} + +function_set ArrayCrossProductFunction::getFunctionSet() { + function_set result; + result.push_back(std::make_unique(name, + std::vector{ + LogicalTypeID::ARRAY, + LogicalTypeID::ARRAY, + }, + LogicalTypeID::ARRAY, nullptr, nullptr, ArrayCrossProductBindFunc, + false /* isVarLength */)); + return result; +} + +static void validateArrayFunctionParameters(const LogicalType& leftType, + const LogicalType& rightType, const std::string& functionName) { + if (leftType != rightType) { + throw BinderException( + stringFormat("{} requires both arrays to have the same element type", functionName)); + } + if (ArrayType::getChildType(&leftType)->getLogicalTypeID() != LogicalTypeID::FLOAT && + ArrayType::getChildType(&leftType)->getLogicalTypeID() != LogicalTypeID::DOUBLE) { + throw BinderException( + stringFormat("{} requires argument type of FLOAT or DOUBLE.", functionName)); + } +} + +template +static scalar_func_exec_t getBinaryArrayExecFuncSwitchResultType() { + auto execFunc = + ScalarFunction::BinaryExecListStructFunction; + return execFunc; +} + +template +scalar_func_exec_t getScalarExecFunc(LogicalType type) { + scalar_func_exec_t execFunc; + switch (ArrayType::getChildType(&type)->getLogicalTypeID()) { + case LogicalTypeID::FLOAT: + execFunc = getBinaryArrayExecFuncSwitchResultType(); + break; + case LogicalTypeID::DOUBLE: + execFunc = getBinaryArrayExecFuncSwitchResultType(); + break; + default: + KU_UNREACHABLE; + } + return execFunc; +} + +template +std::unique_ptr arrayTemplateBindFunc(std::string functionName, + const binder::expression_vector& arguments, Function* function) { + auto leftType = arguments[0]->dataType; + auto rightType = arguments[1]->dataType; + validateArrayFunctionParameters(leftType, rightType, functionName); + ku_dynamic_cast(function)->execFunc = + getScalarExecFunc(leftType); + return std::make_unique(ArrayType::getChildType(&leftType)->copy()); +} + +template +function_set templateGetFunctionSet(const std::string& functionName) { + function_set result; + result.push_back(std::make_unique(functionName, + std::vector{ + LogicalTypeID::ARRAY, + LogicalTypeID::ARRAY, + }, + LogicalTypeID::ANY, nullptr, nullptr, + std::bind(arrayTemplateBindFunc, functionName, std::placeholders::_1, + std::placeholders::_2), + false /* isVarLength */)); + return result; +} + +function_set ArrayCosineSimilarityFunction::getFunctionSet() { + return templateGetFunctionSet(name); +} + +function_set ArrayDistanceFunction::getFunctionSet() { + return templateGetFunctionSet(name); +} + +function_set ArrayInnerProductFunction::getFunctionSet() { + return templateGetFunctionSet(name); +} + +function_set ArrayDotProductFunction::getFunctionSet() { + return templateGetFunctionSet(name); +} + +} // namespace function +} // namespace kuzu diff --git a/src/function/vector_blob_functions.cpp b/src/function/vector_blob_functions.cpp index 4fd40c40f04..ecc64a5d792 100644 --- a/src/function/vector_blob_functions.cpp +++ b/src/function/vector_blob_functions.cpp @@ -3,6 +3,7 @@ #include "function/blob/functions/decode_function.h" #include "function/blob/functions/encode_function.h" #include "function/blob/functions/octet_length_function.h" +#include "function/scalar_function.h" using namespace kuzu::common; @@ -11,16 +12,16 @@ namespace function { function_set OctetLengthFunctions::getFunctionSet() { function_set definitions; - definitions.push_back(make_unique(OCTET_LENGTH_FUNC_NAME, - std::vector{LogicalTypeID::BLOB}, LogicalTypeID::INT64, - ScalarFunction::UnaryExecFunction, nullptr, nullptr, nullptr, - false /* isVarLength */)); + definitions.push_back( + make_unique(name, std::vector{LogicalTypeID::BLOB}, + LogicalTypeID::INT64, ScalarFunction::UnaryExecFunction, + nullptr, nullptr, nullptr, false /* isVarLength */)); return definitions; } function_set EncodeFunctions::getFunctionSet() { function_set definitions; - definitions.push_back(make_unique(ENCODE_FUNC_NAME, + definitions.push_back(make_unique(name, std::vector{LogicalTypeID::STRING}, LogicalTypeID::BLOB, ScalarFunction::UnaryStringExecFunction, nullptr, false /* isVarLength */)); @@ -29,7 +30,7 @@ function_set EncodeFunctions::getFunctionSet() { function_set DecodeFunctions::getFunctionSet() { function_set definitions; - definitions.push_back(make_unique(DECODE_FUNC_NAME, + definitions.push_back(make_unique(name, std::vector{LogicalTypeID::BLOB}, LogicalTypeID::STRING, ScalarFunction::UnaryStringExecFunction, nullptr, false /* isVarLength */)); diff --git a/src/function/vector_boolean_functions.cpp b/src/function/vector_boolean_functions.cpp index cae7e3b2cf9..a71ae4fac19 100644 --- a/src/function/vector_boolean_functions.cpp +++ b/src/function/vector_boolean_functions.cpp @@ -8,7 +8,7 @@ namespace kuzu { namespace function { void VectorBooleanFunction::bindExecFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func) { + const binder::expression_vector& children, scalar_func_exec_t& func) { if (isExpressionBinary(expressionType)) { bindBinaryExecFunction(expressionType, children, func); } else { @@ -18,7 +18,7 @@ void VectorBooleanFunction::bindExecFunction(ExpressionType expressionType, } void VectorBooleanFunction::bindSelectFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func) { + const binder::expression_vector& children, scalar_func_select_t& func) { if (isExpressionBinary(expressionType)) { bindBinarySelectFunction(expressionType, children, func); } else { @@ -28,7 +28,7 @@ void VectorBooleanFunction::bindSelectFunction(ExpressionType expressionType, } void VectorBooleanFunction::bindBinaryExecFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func) { + const binder::expression_vector& children, scalar_func_exec_t& func) { KU_ASSERT(children.size() == 2); auto leftType = children[0]->dataType; auto rightType = children[1]->dataType; @@ -54,7 +54,7 @@ void VectorBooleanFunction::bindBinaryExecFunction(ExpressionType expressionType } void VectorBooleanFunction::bindBinarySelectFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func) { + const binder::expression_vector& children, scalar_func_select_t& func) { KU_ASSERT(children.size() == 2); auto leftType = children[0]->dataType; auto rightType = children[1]->dataType; @@ -80,7 +80,7 @@ void VectorBooleanFunction::bindBinarySelectFunction(ExpressionType expressionTy } void VectorBooleanFunction::bindUnaryExecFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func) { + const binder::expression_vector& children, scalar_func_exec_t& func) { KU_ASSERT( children.size() == 1 && children[0]->dataType.getLogicalTypeID() == LogicalTypeID::BOOL); (void)children; @@ -96,7 +96,7 @@ void VectorBooleanFunction::bindUnaryExecFunction(ExpressionType expressionType, } void VectorBooleanFunction::bindUnarySelectFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func) { + const binder::expression_vector& children, scalar_func_select_t& func) { KU_ASSERT( children.size() == 1 && children[0]->dataType.getLogicalTypeID() == LogicalTypeID::BOOL); (void)children; diff --git a/src/function/vector_cast_functions.cpp b/src/function/vector_cast_functions.cpp index 02376b6f454..9a499e0cc91 100644 --- a/src/function/vector_cast_functions.cpp +++ b/src/function/vector_cast_functions.cpp @@ -4,79 +4,25 @@ #include "binder/expression/literal_expression.h" #include "common/exception/binder.h" #include "common/exception/conversion.h" -#include "function/cast/functions/cast_fixed_list.h" +#include "function/built_in_function_utils.h" +#include "function/cast/functions/cast_array.h" #include "function/cast/functions/cast_from_string_functions.h" #include "function/cast/functions/cast_functions.h" #include "function/cast/functions/cast_rdf_variant.h" using namespace kuzu::common; +using namespace kuzu::binder; namespace kuzu { namespace function { -template -static void fixedListToListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - KU_ASSERT(params.size() == 1); - const auto& inputVector = params[0]; - - auto numValuesPerList = FixedListType::getNumValuesInList(&inputVector->dataType); - for (auto i = 0u; i < inputVector->state->selVector->selectedSize; i++) { - auto pos = inputVector->state->selVector->selectedPositions[i]; - result.setNull(pos, inputVector->isNull(pos)); - if (!result.isNull(pos)) { - list_entry_t listEntry{pos * numValuesPerList, numValuesPerList}; - result.setValue(pos, listEntry); - } - } - auto numOfEntries = inputVector->state->selVector - ->selectedPositions[inputVector->state->selVector->selectedSize - 1] + - 1; - ListVector::resizeDataVector(&result, numOfEntries * numValuesPerList); - - auto resultVector = ListVector::getDataVector(&result); - scalar_exec_func func = CastFunction::bindCastFunction( - "CAST", FixedListType::getChildType(&inputVector->dataType)->getLogicalTypeID(), - resultVector->dataType.getLogicalTypeID()) - ->execFunc; - reinterpret_cast(dataPtr)->numOfEntries = numOfEntries; - func(params, *resultVector, dataPtr); -} - -template<> -void fixedListToListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { - KU_ASSERT(params.size() == 1); - const auto& inputVector = params[0]; - - auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; - result.setNullFromBits(inputVector->getNullMaskData(), 0, 0, numOfEntries); - auto numValuesPerList = FixedListType::getNumValuesInList(&inputVector->dataType); - ListVector::resizeDataVector(&result, numOfEntries * numValuesPerList); - - for (auto i = 0u; i < numOfEntries; i++) { - result.setNull(i, inputVector->isNull(i)); - if (!result.isNull(i)) { - list_entry_t listEntry{i * numValuesPerList, numValuesPerList}; - result.setValue(i, listEntry); - } - } - - auto resultVector = ListVector::getDataVector(&result); - scalar_exec_func func = CastFunction::bindCastFunction( - "CAST", FixedListType::getChildType(&inputVector->dataType)->getLogicalTypeID(), - resultVector->dataType.getLogicalTypeID()) - ->execFunc; - func(params, *resultVector, dataPtr); -} - static void resolveNestedVector(std::shared_ptr inputVector, ValueVector* resultVector, uint64_t numOfEntries, CastFunctionBindData* dataPtr) { auto inputType = &inputVector->dataType; auto resultType = &resultVector->dataType; while (true) { - if (inputType->getPhysicalType() == PhysicalTypeID::VAR_LIST && - resultType->getPhysicalType() == PhysicalTypeID::VAR_LIST) { + if (inputType->getPhysicalType() == PhysicalTypeID::LIST && + resultType->getPhysicalType() == PhysicalTypeID::LIST) { // copy data and nullmask from input memcpy(resultVector->getData(), inputVector->getData(), numOfEntries * resultVector->getNumBytesPerValue()); @@ -113,8 +59,8 @@ static void resolveNestedVector(std::shared_ptr inputVector, ValueV auto inputFieldVectors = StructVector::getFieldVectors(inputVector.get()); auto resultFieldVectors = StructVector::getFieldVectors(resultVector); for (auto i = 0u; i < inputFieldVectors.size(); i++) { - resolveNestedVector( - inputFieldVectors[i], resultFieldVectors[i].get(), numOfEntries, dataPtr); + resolveNestedVector(inputFieldVectors[i], resultFieldVectors[i].get(), numOfEntries, + dataPtr); } return; } else { @@ -123,43 +69,43 @@ static void resolveNestedVector(std::shared_ptr inputVector, ValueV } // non-nested types - scalar_exec_func func = CastFunction::bindCastFunction( - "CAST", inputType->getLogicalTypeID(), resultType->getLogicalTypeID()) - ->execFunc; + scalar_func_exec_t func = CastFunction::bindCastFunction("CAST", + inputType->getLogicalTypeID(), resultType->getLogicalTypeID()) + ->execFunc; std::vector> childParams{inputVector}; dataPtr->numOfEntries = numOfEntries; func(childParams, *resultVector, (void*)dataPtr); } -static void nestedTypesCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr) { +static void nestedTypesCastExecFunction(const std::vector>& params, + ValueVector& result, void* dataPtr) { KU_ASSERT(params.size() == 1); result.resetAuxiliaryBuffer(); const auto& inputVector = params[0]; // check if all selcted list entry have the requried fixed list size - if (CastFixedListHelper::containsListToFixedList(&inputVector->dataType, &result.dataType)) { + if (CastArrayHelper::containsListToArray(&inputVector->dataType, &result.dataType)) { for (auto i = 0u; i < inputVector->state->selVector->selectedSize; i++) { auto pos = inputVector->state->selVector->selectedPositions[i]; - CastFixedListHelper::validateListEntry(inputVector.get(), &result.dataType, pos); + CastArrayHelper::validateListEntry(inputVector.get(), &result.dataType, pos); } }; auto numOfEntries = inputVector->state->selVector ->selectedPositions[inputVector->state->selVector->selectedSize - 1] + 1; - resolveNestedVector( - inputVector, &result, numOfEntries, reinterpret_cast(dataPtr)); + resolveNestedVector(inputVector, &result, numOfEntries, + reinterpret_cast(dataPtr)); } bool CastFunction::hasImplicitCast(const LogicalType& srcType, const LogicalType& dstType) { // TODO(Jiamin): should remove after support list implicit cast - if (srcType.getLogicalTypeID() == LogicalTypeID::VAR_LIST && - dstType.getLogicalTypeID() == LogicalTypeID::VAR_LIST) { + if (srcType.getLogicalTypeID() == LogicalTypeID::LIST && + dstType.getLogicalTypeID() == LogicalTypeID::LIST) { return false; } - if (BuiltInFunctionsUtils::getCastCost( - srcType.getLogicalTypeID(), dstType.getLogicalTypeID()) != UNDEFINED_CAST_COST) { + if (BuiltInFunctionsUtils::getCastCost(srcType.getLogicalTypeID(), + dstType.getLogicalTypeID()) != UNDEFINED_CAST_COST) { return true; } // TODO(Jiamin): there are still other special cases @@ -171,9 +117,9 @@ bool CastFunction::hasImplicitCast(const LogicalType& srcType, const LogicalType } template -static std::unique_ptr bindCastFromStringFunction( - const std::string& functionName, LogicalTypeID targetTypeID) { - scalar_exec_func execFunc; +static std::unique_ptr bindCastFromStringFunction(const std::string& functionName, + LogicalTypeID targetTypeID) { + scalar_func_exec_t execFunc; switch (targetTypeID) { case LogicalTypeID::DATE: { execFunc = @@ -264,13 +210,11 @@ static std::unique_ptr bindCastFromStringFunction( execFunc = ScalarFunction::UnaryCastStringExecFunction; } break; - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: { execFunc = ScalarFunction::UnaryCastStringExecFunction; } break; - case LogicalTypeID::FIXED_LIST: { - execFunc = CastFixedList::stringtoFixedListCastExecFunction; - } break; case LogicalTypeID::MAP: { execFunc = ScalarFunction::UnaryCastStringExecFunction; @@ -291,13 +235,13 @@ static std::unique_ptr bindCastFromStringFunction( throw ConversionException{stringFormat("Unsupported casting function from STRING to {}.", LogicalTypeUtils::toString(targetTypeID))}; } - return std::make_unique( - functionName, std::vector{LogicalTypeID::STRING}, targetTypeID, execFunc); + return std::make_unique(functionName, + std::vector{LogicalTypeID::STRING}, targetTypeID, execFunc); } static std::unique_ptr bindCastFromRdfVariantFunction( const std::string& functionName, LogicalTypeID targetTypeID) { - scalar_exec_func execFunc; + scalar_func_exec_t execFunc; switch (targetTypeID) { case LogicalTypeID::DATE: { execFunc = ScalarFunction::UnaryRdfVariantCastExecFunction bindCastFromRdfVariantFunction( } template -static std::unique_ptr bindCastToStringFunction( - const std::string& functionName, LogicalTypeID sourceTypeID) { - scalar_exec_func func; +static std::unique_ptr bindCastToStringFunction(const std::string& functionName, + LogicalTypeID sourceTypeID) { + scalar_func_exec_t func; switch (sourceTypeID) { case LogicalTypeID::BOOL: { func = ScalarFunction::UnaryCastExecFunction; @@ -459,13 +403,11 @@ static std::unique_ptr bindCastToStringFunction( func = ScalarFunction::UnaryCastExecFunction; } break; - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: { func = ScalarFunction::UnaryCastExecFunction; } break; - case LogicalTypeID::FIXED_LIST: { - func = CastFixedList::fixedListToStringCastExecFunction; - } break; case LogicalTypeID::MAP: { func = ScalarFunction::UnaryCastExecFunction; @@ -490,13 +432,13 @@ static std::unique_ptr bindCastToStringFunction( default: KU_UNREACHABLE; } - return std::make_unique( - functionName, std::vector{sourceTypeID}, LogicalTypeID::STRING, func); + return std::make_unique(functionName, std::vector{sourceTypeID}, + LogicalTypeID::STRING, func); } -static std::unique_ptr bindCastToRdfVariantFunction( - const std::string& functionName, LogicalTypeID sourceTypeID) { - scalar_exec_func execFunc; +static std::unique_ptr bindCastToRdfVariantFunction(const std::string& functionName, + LogicalTypeID sourceTypeID) { + scalar_func_exec_t execFunc; switch (sourceTypeID) { case LogicalTypeID::DATE: { execFunc = ScalarFunction::UnaryRdfVariantCastExecFunction bindCastToRdfVariantFunction( } template -static std::unique_ptr bindCastToNumericFunction( - const std::string& functionName, LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID) { - scalar_exec_func func; +static std::unique_ptr bindCastToNumericFunction(const std::string& functionName, + LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID) { + scalar_func_exec_t func; switch (sourceTypeID) { case LogicalTypeID::INT8: { func = ScalarFunction::UnaryExecFunction; @@ -620,40 +562,24 @@ static std::unique_ptr bindCastToNumericFunction( throw ConversionException{stringFormat("Unsupported casting function from {} to {}.", LogicalTypeUtils::toString(sourceTypeID), LogicalTypeUtils::toString(targetTypeID))}; } - return std::make_unique( - functionName, std::vector{sourceTypeID}, targetTypeID, func); + return std::make_unique(functionName, std::vector{sourceTypeID}, + targetTypeID, func); } template -static std::unique_ptr bindCastBetweenNested( - const std::string& functionName, LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID) { +static std::unique_ptr bindCastBetweenNested(const std::string& functionName, + LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID) { switch (sourceTypeID) { - case LogicalTypeID::VAR_LIST: { - if (targetTypeID == LogicalTypeID::FIXED_LIST) { - return std::make_unique(functionName, - std::vector{sourceTypeID}, targetTypeID, - CastFixedList::listToFixedListCastExecFunction); - } - } + case LogicalTypeID::LIST: case LogicalTypeID::MAP: - case LogicalTypeID::STRUCT: { - if (sourceTypeID == targetTypeID) { + case LogicalTypeID::STRUCT: + case LogicalTypeID::ARRAY: { + if (CastArrayHelper::checkCompatibleNestedTypes(sourceTypeID, targetTypeID)) { return std::make_unique(functionName, std::vector{sourceTypeID}, targetTypeID, nestedTypesCastExecFunction); } } - case LogicalTypeID::FIXED_LIST: { - if (targetTypeID == LogicalTypeID::VAR_LIST) { - return std::make_unique(functionName, - std::vector{sourceTypeID}, targetTypeID, - fixedListToListCastExecFunction); - } else if (sourceTypeID == targetTypeID) { - return std::make_unique(functionName, - std::vector{sourceTypeID}, targetTypeID, - CastFixedList::castBetweenFixedListExecFunc); - } - } default: throw ConversionException{stringFormat("Unsupported casting function from {} to {}.", LogicalTypeUtils::toString(sourceTypeID), LogicalTypeUtils::toString(targetTypeID))}; @@ -661,9 +587,9 @@ static std::unique_ptr bindCastBetweenNested( } template -static std::unique_ptr bindCastToTimestampFunction( - const std::string& functionName, LogicalTypeID sourceTypeID, LogicalTypeID dstTypeID) { - scalar_exec_func func; +static std::unique_ptr bindCastToTimestampFunction(const std::string& functionName, + LogicalTypeID sourceTypeID, LogicalTypeID dstTypeID) { + scalar_func_exec_t func; switch (sourceTypeID) { case LogicalTypeID::DATE: { func = ScalarFunction::UnaryExecFunction; @@ -689,13 +615,13 @@ static std::unique_ptr bindCastToTimestampFunction( throw ConversionException{stringFormat("Unsupported casting function from {} to {}.", LogicalTypeUtils::toString(sourceTypeID), LogicalTypeUtils::toString(dstTypeID))}; } - return std::make_unique( - functionName, std::vector{sourceTypeID}, LogicalTypeID::TIMESTAMP, func); + return std::make_unique(functionName, std::vector{sourceTypeID}, + LogicalTypeID::TIMESTAMP, func); } template -std::unique_ptr CastFunction::bindCastFunction( - const std::string& functionName, LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID) { +std::unique_ptr CastFunction::bindCastFunction(const std::string& functionName, + LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID) { if (sourceTypeID == LogicalTypeID::STRING) { return bindCastFromStringFunction(functionName, targetTypeID); } @@ -710,72 +636,72 @@ std::unique_ptr CastFunction::bindCastFunction( return bindCastToRdfVariantFunction(functionName, sourceTypeID); } case LogicalTypeID::DOUBLE: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::FLOAT: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::INT128: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, + sourceTypeID, targetTypeID); } case LogicalTypeID::SERIAL: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, + sourceTypeID, targetTypeID); } case LogicalTypeID::INT64: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::INT32: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::INT16: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::INT8: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::UINT64: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, + sourceTypeID, targetTypeID); } case LogicalTypeID::UINT32: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, + sourceTypeID, targetTypeID); } case LogicalTypeID::UINT16: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, + sourceTypeID, targetTypeID); } case LogicalTypeID::UINT8: { - return bindCastToNumericFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToNumericFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::TIMESTAMP_NS: { - return bindCastToTimestampFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToTimestampFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::TIMESTAMP_MS: { - return bindCastToTimestampFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToTimestampFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::TIMESTAMP_SEC: { - return bindCastToTimestampFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToTimestampFunction(functionName, sourceTypeID, + targetTypeID); } case LogicalTypeID::TIMESTAMP_TZ: case LogicalTypeID::TIMESTAMP: { - return bindCastToTimestampFunction( - functionName, sourceTypeID, targetTypeID); + return bindCastToTimestampFunction(functionName, sourceTypeID, + targetTypeID); } - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: case LogicalTypeID::MAP: case LogicalTypeID::STRUCT: { return bindCastBetweenNested(functionName, sourceTypeID, targetTypeID); @@ -789,28 +715,28 @@ std::unique_ptr CastFunction::bindCastFunction( function_set CastToDateFunction::getFunctionSet() { function_set result; - result.push_back(CastFunction::bindCastFunction( - CAST_TO_DATE_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::DATE)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_DATE_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::DATE)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::DATE)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::DATE)); return result; } function_set CastToTimestampFunction::getFunctionSet() { function_set result; - result.push_back(CastFunction::bindCastFunction( - CAST_TO_TIMESTAMP_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::TIMESTAMP)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_TIMESTAMP_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::TIMESTAMP)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::TIMESTAMP)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::TIMESTAMP)); return result; } function_set CastToIntervalFunction::getFunctionSet() { function_set result; - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INTERVAL_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::INTERVAL)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INTERVAL_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INTERVAL)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::INTERVAL)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INTERVAL)); return result; } @@ -818,220 +744,210 @@ function_set CastToStringFunction::getFunctionSet() { function_set result; result.reserve(LogicalTypeUtils::getAllValidLogicTypes().size()); for (auto& type : LogicalTypeUtils::getAllValidLogicTypes()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_STRING_FUNC_NAME, type, LogicalTypeID::STRING)); + result.push_back(CastFunction::bindCastFunction(name, type, LogicalTypeID::STRING)); } return result; } function_set CastToBlobFunction::getFunctionSet() { function_set result; - result.push_back(CastFunction::bindCastFunction( - CAST_TO_BLOB_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::BLOB)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_BLOB_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::BLOB)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::BLOB)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::BLOB)); return result; } function_set CastToUUIDFunction::getFunctionSet() { function_set result; - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UUID_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::UUID)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::UUID)); return result; } function_set CastToBoolFunction::getFunctionSet() { function_set result; - result.push_back(CastFunction::bindCastFunction( - CAST_TO_BOOL_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::BOOL)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_BOOL_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::BOOL)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::BOOL)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::BOOL)); return result; } function_set CastToDoubleFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(CastFunction::bindCastFunction( - CAST_TO_DOUBLE_FUNC_NAME, typeID, LogicalTypeID::DOUBLE)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::DOUBLE)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_DOUBLE_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::DOUBLE)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_DOUBLE_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::DOUBLE)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::DOUBLE)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::DOUBLE)); return result; } function_set CastToFloatFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_FLOAT_FUNC_NAME, typeID, LogicalTypeID::FLOAT)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::FLOAT)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_FLOAT_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::FLOAT)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_FLOAT_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::FLOAT)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::FLOAT)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::FLOAT)); return result; } function_set CastToInt128Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT128_FUNC_NAME, typeID, LogicalTypeID::INT128)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::INT128)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT128_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::INT128)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::INT128)); return result; } function_set CastToSerialFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(CastFunction::bindCastFunction( - CAST_TO_SERIAL_FUNC_NAME, typeID, LogicalTypeID::SERIAL)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::SERIAL)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_SERIAL_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::SERIAL)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_SERIAL_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::SERIAL)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::SERIAL)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::SERIAL)); return result; } function_set CastToInt64Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_INT64_FUNC_NAME, typeID, LogicalTypeID::INT64)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::INT64)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT64_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::INT64)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT64_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT64)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::INT64)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT64)); return result; } function_set CastToInt32Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_INT32_FUNC_NAME, typeID, LogicalTypeID::INT32)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::INT32)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT32_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::INT32)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT32_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT32)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::INT32)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT32)); return result; } function_set CastToInt16Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_INT16_FUNC_NAME, typeID, LogicalTypeID::INT16)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::INT16)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT16_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::INT16)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT16_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT16)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::INT16)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT16)); return result; } function_set CastToInt8Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_INT8_FUNC_NAME, typeID, LogicalTypeID::INT8)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::INT8)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT8_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::INT8)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_INT8_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT8)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::INT8)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::INT8)); return result; } function_set CastToUInt64Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT64_FUNC_NAME, typeID, LogicalTypeID::UINT64)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::UINT64)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT64_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::UINT64)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT64_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT64)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::UINT64)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT64)); return result; } function_set CastToUInt32Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT32_FUNC_NAME, typeID, LogicalTypeID::UINT32)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::UINT32)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT32_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::UINT32)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT32_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT32)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::UINT32)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT32)); return result; } function_set CastToUInt16Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT16_FUNC_NAME, typeID, LogicalTypeID::UINT16)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::UINT16)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT16_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::UINT16)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT16_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT16)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::UINT16)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT16)); return result; } function_set CastToUInt8Function::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { - result.push_back( - CastFunction::bindCastFunction(CAST_TO_UINT8_FUNC_NAME, typeID, LogicalTypeID::UINT8)); + result.push_back(CastFunction::bindCastFunction(name, typeID, LogicalTypeID::UINT8)); } - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT8_FUNC_NAME, LogicalTypeID::STRING, LogicalTypeID::UINT8)); - result.push_back(CastFunction::bindCastFunction( - CAST_TO_UINT8_FUNC_NAME, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT8)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::STRING, LogicalTypeID::UINT8)); + result.push_back( + CastFunction::bindCastFunction(name, LogicalTypeID::RDF_VARIANT, LogicalTypeID::UINT8)); return result; } -std::unique_ptr CastAnyFunction::bindFunc( - const binder::expression_vector& arguments, Function* function) { - // check the size of the arguments - if (arguments.size() != 2) { - throw BinderException(stringFormat( - "Invalid number of arguments for given function CAST. Expected: 2, Actual: {}.", - arguments.size())); +static std::unique_ptr castBindFunc(const binder::expression_vector& arguments, + Function* function) { + KU_ASSERT(arguments.size() == 2); + // Bind target type. + if (arguments[1]->expressionType != ExpressionType::LITERAL) { + throw BinderException( + stringFormat("Second parameter of CAST function must be an literal.")); } - + auto literalExpr = ku_dynamic_cast(arguments[1].get()); + auto targetTypeStr = literalExpr->getValue()->getValue(); + auto targetType = binder::Binder::bindDataType(targetTypeStr); + if (*targetType == arguments[0]->getDataType()) { // No need to cast. + return nullptr; + } + // Assign default type if input is ANY type, e.g. NULL auto inputTypeID = arguments[0]->dataType.getLogicalTypeID(); if (inputTypeID == LogicalTypeID::ANY) { inputTypeID = LogicalTypeID::STRING; } - auto str = ((binder::LiteralExpression&)*arguments[1]).getValue()->getValue(); - auto outputType = binder::Binder::bindDataType(str); auto func = ku_dynamic_cast(function); - func->name = "CAST_TO_" + str; - func->parameterTypeIDs[0] = inputTypeID; + func->name = "CAST_TO_" + targetTypeStr; func->execFunc = - CastFunction::bindCastFunction(func->name, inputTypeID, outputType->getLogicalTypeID()) + CastFunction::bindCastFunction(func->name, inputTypeID, targetType->getLogicalTypeID()) ->execFunc; - return std::make_unique(std::move(outputType)); + return std::make_unique(std::move(targetType)); } function_set CastAnyFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(CAST_FUNC_NAME, - std::vector{LogicalTypeID::ANY}, LogicalTypeID::ANY, nullptr, nullptr, - bindFunc, false)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::ANY, LogicalTypeID::STRING}, LogicalTypeID::ANY, + nullptr, nullptr, castBindFunc, false)); return result; } diff --git a/src/function/vector_date_functions.cpp b/src/function/vector_date_functions.cpp index 4e0e8d620f9..2af8e16874f 100644 --- a/src/function/vector_date_functions.cpp +++ b/src/function/vector_date_functions.cpp @@ -1,6 +1,7 @@ #include "function/date/vector_date_functions.h" #include "function/date/date_functions.h" +#include "function/scalar_function.h" using namespace kuzu::common; @@ -9,15 +10,15 @@ namespace function { function_set DatePartFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(DATE_PART_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::DATE}, LogicalTypeID::INT64, ScalarFunction::BinaryExecFunction)); - result.push_back(make_unique(DATE_PART_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::TIMESTAMP}, LogicalTypeID::INT64, ScalarFunction::BinaryExecFunction)); - result.push_back(make_unique(DATE_PART_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::INTERVAL}, LogicalTypeID::INT64, ScalarFunction::BinaryExecFunction)); @@ -26,10 +27,10 @@ function_set DatePartFunction::getFunctionSet() { function_set DateTruncFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(DATE_TRUNC_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::DATE}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); - result.push_back(make_unique(DATE_TRUNC_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::TIMESTAMP}, LogicalTypeID::TIMESTAMP, ScalarFunction::BinaryExecFunction)); @@ -38,10 +39,10 @@ function_set DateTruncFunction::getFunctionSet() { function_set DayNameFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(DAYNAME_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE}, LogicalTypeID::STRING, ScalarFunction::UnaryExecFunction)); - result.push_back(make_unique(DAYNAME_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP}, LogicalTypeID::STRING, ScalarFunction::UnaryExecFunction)); return result; @@ -49,10 +50,10 @@ function_set DayNameFunction::getFunctionSet() { function_set GreatestFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(GREATEST_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE, LogicalTypeID::DATE}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); - result.push_back(make_unique(GREATEST_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP, LogicalTypeID::TIMESTAMP}, LogicalTypeID::TIMESTAMP, ScalarFunction::BinaryExecFunction)); @@ -61,21 +62,21 @@ function_set GreatestFunction::getFunctionSet() { function_set LastDayFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(LAST_DAY_FUNC_NAME, - std::vector{LogicalTypeID::DATE}, LogicalTypeID::DATE, - ScalarFunction::UnaryExecFunction)); - result.push_back(make_unique(LAST_DAY_FUNC_NAME, - std::vector{LogicalTypeID::TIMESTAMP}, LogicalTypeID::DATE, - ScalarFunction::UnaryExecFunction)); + result.push_back( + make_unique(name, std::vector{LogicalTypeID::DATE}, + LogicalTypeID::DATE, ScalarFunction::UnaryExecFunction)); + result.push_back( + make_unique(name, std::vector{LogicalTypeID::TIMESTAMP}, + LogicalTypeID::DATE, ScalarFunction::UnaryExecFunction)); return result; } function_set LeastFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(LEAST_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE, LogicalTypeID::DATE}, LogicalTypeID::DATE, ScalarFunction::BinaryExecFunction)); - result.push_back(make_unique(LEAST_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP, LogicalTypeID::TIMESTAMP}, LogicalTypeID::TIMESTAMP, ScalarFunction::BinaryExecFunction)); @@ -84,9 +85,9 @@ function_set LeastFunction::getFunctionSet() { function_set MakeDateFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(MAKE_DATE_FUNC_NAME, - std::vector{ - LogicalTypeID::INT64, LogicalTypeID::INT64, LogicalTypeID::INT64}, + result.push_back(make_unique(name, + std::vector{LogicalTypeID::INT64, LogicalTypeID::INT64, + LogicalTypeID::INT64}, LogicalTypeID::DATE, ScalarFunction::TernaryExecFunction)); return result; @@ -94,10 +95,10 @@ function_set MakeDateFunction::getFunctionSet() { function_set MonthNameFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(MONTHNAME_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DATE}, LogicalTypeID::STRING, ScalarFunction::UnaryExecFunction)); - result.push_back(make_unique(MONTHNAME_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP}, LogicalTypeID::STRING, ScalarFunction::UnaryExecFunction)); return result; diff --git a/src/function/vector_hash_functions.cpp b/src/function/vector_hash_functions.cpp index 602698db777..6796bd861d6 100644 --- a/src/function/vector_hash_functions.cpp +++ b/src/function/vector_hash_functions.cpp @@ -7,6 +7,74 @@ using namespace kuzu::common; namespace kuzu { namespace function { +static std::unique_ptr computeDataVecHash(ValueVector* operand) { + auto hashVector = std::make_unique(*LogicalType::LIST(LogicalType::HASH())); + auto numValuesInDataVec = ListVector::getDataVectorSize(operand); + ListVector::resizeDataVector(hashVector.get(), numValuesInDataVec); + auto selectionState = std::make_shared(); + selectionState->selVector->setToFiltered(); + ListVector::getDataVector(operand)->setState(selectionState); + auto numValuesComputed = 0u; + while (numValuesComputed < numValuesInDataVec) { + for (auto i = 0u; i < DEFAULT_VECTOR_CAPACITY; i++) { + selectionState->selVector->selectedPositions[i] = numValuesComputed; + numValuesComputed++; + } + VectorHashFunction::computeHash(ListVector::getDataVector(operand), + ListVector::getDataVector(hashVector.get())); + } + return hashVector; +} + +static void finalizeDataVecHash(ValueVector* operand, ValueVector* result, ValueVector* hashVec) { + for (auto i = 0u; i < result->state->getNumSelectedValues(); i++) { + auto pos = operand->state->selVector->selectedPositions[i]; + auto entry = operand->getValue(pos); + if (operand->isNull(pos)) { + result->setValue(pos, NULL_HASH); + } else { + auto hashValue = NULL_HASH; + for (auto j = 0u; j < entry.size; j++) { + hashValue = combineHashScalar(hashValue, + ListVector::getDataVector(hashVec)->getValue(entry.offset + j)); + } + result->setValue(pos, hashValue); + } + } +} + +static void computeListVectorHash(ValueVector* operand, ValueVector* result) { + auto dataVecHash = computeDataVecHash(operand); + finalizeDataVecHash(operand, result, dataVecHash.get()); +} + +static void computeStructVecHash(ValueVector* operand, ValueVector* result) { + switch (operand->dataType.getLogicalTypeID()) { + case LogicalTypeID::NODE: { + KU_ASSERT(0 == common::StructType::getFieldIdx(&operand->dataType, InternalKeyword::ID)); + UnaryHashFunctionExecutor::execute( + *StructVector::getFieldVector(operand, 0), *result); + } break; + case LogicalTypeID::REL: { + KU_ASSERT(3 == StructType::getFieldIdx(&operand->dataType, InternalKeyword::ID)); + UnaryHashFunctionExecutor::execute( + *StructVector::getFieldVector(operand, 3), *result); + } break; + case LogicalTypeID::STRUCT: { + VectorHashFunction::computeHash(StructVector::getFieldVector(operand, 0 /* idx */).get(), + result); + auto tmpHashVector = std::make_unique(LogicalTypeID::INT64); + for (auto i = 1u; i < StructType::getNumFields(&operand->dataType); i++) { + auto fieldVector = StructVector::getFieldVector(operand, i); + VectorHashFunction::computeHash(fieldVector.get(), tmpHashVector.get()); + VectorHashFunction::combineHash(tmpHashVector.get(), result, result); + } + } break; + default: + KU_UNREACHABLE; + } +} + void VectorHashFunction::computeHash(ValueVector* operand, ValueVector* result) { result->state = operand->state; KU_ASSERT(result->dataType.getLogicalTypeID() == LogicalTypeID::INT64); @@ -57,30 +125,10 @@ void VectorHashFunction::computeHash(ValueVector* operand, ValueVector* result) UnaryHashFunctionExecutor::execute(*operand, *result); } break; case PhysicalTypeID::STRUCT: { - if (operand->dataType.getLogicalTypeID() == LogicalTypeID::NODE) { - KU_ASSERT( - 0 == common::StructType::getFieldIdx(&operand->dataType, InternalKeyword::ID)); - UnaryHashFunctionExecutor::execute( - *StructVector::getFieldVector(operand, 0), *result); - } else if (operand->dataType.getLogicalTypeID() == LogicalTypeID::REL) { - KU_ASSERT(3 == StructType::getFieldIdx(&operand->dataType, InternalKeyword::ID)); - UnaryHashFunctionExecutor::execute( - *StructVector::getFieldVector(operand, 3), *result); - } else { - VectorHashFunction::computeHash( - StructVector::getFieldVector(operand, 0 /* idx */).get(), result); - auto tmpHashVector = std::make_unique(LogicalTypeID::INT64); - for (auto i = 1u; i < StructType::getNumFields(&operand->dataType); i++) { - auto fieldVector = StructVector::getFieldVector(operand, i); - VectorHashFunction::computeHash(fieldVector.get(), tmpHashVector.get()); - VectorHashFunction::combineHash(tmpHashVector.get(), result, result); - } - } + computeStructVecHash(operand, result); } break; - case PhysicalTypeID::VAR_LIST: { - // TODO(Ziyi): We should pass in the selection state here, and do vectorized hash - // computation. - UnaryHashFunctionExecutor::execute(*operand, *result); + case PhysicalTypeID::LIST: { + computeListVectorHash(operand, result); } break; // LCOV_EXCL_START default: { diff --git a/src/function/vector_list_functions.cpp b/src/function/vector_list_functions.cpp index 4b2b5e810e5..87792daf3a2 100644 --- a/src/function/vector_list_functions.cpp +++ b/src/function/vector_list_functions.cpp @@ -1,8 +1,9 @@ #include "function/list/vector_list_functions.h" -#include "binder/expression_binder.h" #include "common/exception/binder.h" #include "common/exception/runtime.h" +#include "common/types/int128_t.h" +#include "common/types/interval_t.h" #include "function/list/functions/list_any_value_function.h" #include "function/list/functions/list_append_function.h" #include "function/list/functions/list_concat_function.h" @@ -20,21 +21,213 @@ #include "function/list/functions/list_sort_function.h" #include "function/list/functions/list_sum_function.h" #include "function/list/functions/list_unique_function.h" +#include "function/scalar_function.h" using namespace kuzu::common; namespace kuzu { namespace function { -static std::string getListFunctionIncompatibleChildrenTypeErrorMsg( - const std::string& functionName, const LogicalType& left, const LogicalType& right) { +template +static scalar_func_exec_t getBinaryListExecFuncSwitchRight(const LogicalType& rightType) { + scalar_func_exec_t execFunc; + switch (rightType.getPhysicalType()) { + case PhysicalTypeID::BOOL: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT64: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT32: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT16: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT8: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT64: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT32: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT16: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT8: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT128: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::DOUBLE: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::FLOAT: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::STRING: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INTERVAL: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INTERNAL_ID: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::LIST: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::STRUCT: { + execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + default: { + KU_UNREACHABLE; + } + } + return execFunc; +} + +template +static scalar_func_exec_t getBinaryListExecFuncSwitchAll(const LogicalType& type) { + scalar_func_exec_t execFunc; + switch (type.getPhysicalType()) { + case PhysicalTypeID::INT64: { + execFunc = + ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT32: { + execFunc = + ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT16: { + execFunc = + ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT8: { + execFunc = + ScalarFunction::BinaryExecListStructFunction; + } break; + default: { + KU_UNREACHABLE; + } + } + return execFunc; +} + +template +static scalar_func_exec_t getTernaryListExecFuncSwitchAll(const LogicalType& type) { + scalar_func_exec_t execFunc; + switch (type.getPhysicalType()) { + case PhysicalTypeID::INT64: { + execFunc = ScalarFunction::TernaryExecListStructFunction; + } break; + case PhysicalTypeID::INT32: { + execFunc = ScalarFunction::TernaryExecListStructFunction; + } break; + case PhysicalTypeID::INT16: { + execFunc = ScalarFunction::TernaryExecListStructFunction; + } break; + case PhysicalTypeID::INT8: { + execFunc = ScalarFunction::TernaryExecListStructFunction; + } break; + default: { + KU_UNREACHABLE; + } + } + return execFunc; +} + +template +static std::unique_ptr bindFuncListAggr( + const binder::expression_vector& arguments, Function* function) { + auto scalarFunction = ku_dynamic_cast(function); + auto resultType = ListType::getChildType(&arguments[0]->dataType); + switch (resultType->getLogicalTypeID()) { + case LogicalTypeID::SERIAL: + case LogicalTypeID::INT64: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::INT32: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::INT16: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::INT8: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::UINT64: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::UINT32: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::UINT16: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::UINT8: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::INT128: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::DOUBLE: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + case LogicalTypeID::FLOAT: { + scalarFunction->execFunc = + ScalarFunction::UnaryExecNestedTypeFunction; + } break; + default: { + throw BinderException(stringFormat("Unsupported inner data type for {}: {}", function->name, + LogicalTypeUtils::toString(resultType->getLogicalTypeID()))); + } + } + return std::make_unique(resultType->copy()); +} + +static std::string getListFunctionIncompatibleChildrenTypeErrorMsg(const std::string& functionName, + const LogicalType& left, const LogicalType& right) { return std::string("Cannot bind " + functionName + " with parameter type " + left.toString() + " and " + right.toString() + "."); } void ListCreationFunction::execFunc(const std::vector>& parameters, ValueVector& result, void* /*dataPtr*/) { - KU_ASSERT(result.dataType.getLogicalTypeID() == LogicalTypeID::VAR_LIST); result.resetAuxiliaryBuffer(); for (auto selectedPos = 0u; selectedPos < result.state->selVector->selectedSize; ++selectedPos) { @@ -59,47 +252,51 @@ static LogicalType getValidLogicalType(const binder::expression_vector& expressi return expression->dataType; } } - return LogicalType(common::LogicalTypeID::ANY); + return LogicalType(LogicalTypeID::ANY); } -std::unique_ptr ListCreationFunction::bindFunc( +static std::unique_ptr ListCreationBindFunc( const binder::expression_vector& arguments, Function* /*function*/) { + auto resultType = LogicalType::LIST(ListCreationFunction::getChildType(arguments).copy()); + return std::make_unique(std::move(resultType)); +} + +LogicalType ListCreationFunction::getChildType(const binder::expression_vector& arguments) { // ListCreation requires all parameters to have the same type or be ANY type. The result type of // listCreation can be determined by the first non-ANY type parameter. If all parameters have // dataType ANY, then the resultType will be INT64[] (default type). auto childType = getValidLogicalType(arguments); - if (childType.getLogicalTypeID() == common::LogicalTypeID::ANY) { - childType = LogicalType(common::LogicalTypeID::STRING); + if (childType.getLogicalTypeID() == LogicalTypeID::ANY) { + childType = LogicalType(LogicalTypeID::STRING); } // Cast parameters with ANY dataType to resultChildType. for (auto& argument : arguments) { auto& parameterType = argument->getDataTypeReference(); if (parameterType != childType) { if (parameterType.getLogicalTypeID() == LogicalTypeID::ANY) { - binder::ExpressionBinder::resolveAnyDataType(*argument, childType); + argument->cast(childType); } else { - throw BinderException(getListFunctionIncompatibleChildrenTypeErrorMsg( - LIST_CREATION_FUNC_NAME, arguments[0]->getDataType(), argument->getDataType())); + throw BinderException(getListFunctionIncompatibleChildrenTypeErrorMsg(name, + arguments[0]->getDataType(), argument->getDataType())); } } } - auto resultType = LogicalType::VAR_LIST(childType.copy()); - return std::make_unique(std::move(resultType)); + return childType; } function_set ListCreationFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_CREATION_FUNC_NAME, - std::vector{LogicalTypeID::ANY}, LogicalTypeID::VAR_LIST, execFunc, nullptr, - bindFunc, true /* isVarLength */)); + result.push_back( + std::make_unique(name, std::vector{LogicalTypeID::ANY}, + LogicalTypeID::LIST, execFunc, nullptr, ListCreationBindFunc, true /* isVarLength */)); return result; } -std::unique_ptr ListRangeFunction::bindFunc( +static std::unique_ptr ListRangeBindFunc( const binder::expression_vector& arguments, Function* /*function*/) { KU_ASSERT(arguments[0]->dataType == arguments[1]->dataType); - auto resultType = LogicalType::VAR_LIST( - std::make_unique(arguments[0]->dataType.getLogicalTypeID())); + auto resultType = + LogicalType::LIST(std::make_unique(arguments[0]->dataType.getLogicalTypeID())); return std::make_unique(std::move(resultType)); } @@ -107,45 +304,44 @@ function_set ListRangeFunction::getFunctionSet() { function_set result; for (auto typeID : LogicalTypeUtils::getIntegerLogicalTypeIDs()) { // start, end - result.push_back(std::make_unique(LIST_RANGE_FUNC_NAME, - std::vector{typeID, typeID}, LogicalTypeID::VAR_LIST, - ListFunction::getBinaryListExecFuncSwitchAll(LogicalType{typeID}), - nullptr, bindFunc, false)); + result.push_back(std::make_unique(name, + std::vector{typeID, typeID}, LogicalTypeID::LIST, + getBinaryListExecFuncSwitchAll(LogicalType{typeID}), nullptr, + ListRangeBindFunc, false)); // start, end, step - result.push_back(std::make_unique(LIST_RANGE_FUNC_NAME, - std::vector{typeID, typeID, typeID}, LogicalTypeID::VAR_LIST, - ListFunction::getTernaryListExecFuncSwitchAll(LogicalType{typeID}), - nullptr, bindFunc, false)); + result.push_back(std::make_unique(name, + std::vector{typeID, typeID, typeID}, LogicalTypeID::LIST, + getTernaryListExecFuncSwitchAll(LogicalType{typeID}), nullptr, + ListRangeBindFunc, false)); } return result; } function_set SizeFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(SIZE_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::INT64, + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST}, LogicalTypeID::INT64, ScalarFunction::UnaryExecFunction, true /* isVarlength*/)); - result.push_back(std::make_unique(CARDINALITY_FUNC_NAME, + result.push_back(std::make_unique(alias, std::vector{LogicalTypeID::MAP}, LogicalTypeID::INT64, ScalarFunction::UnaryExecFunction, true /* isVarlength*/)); - result.push_back(std::make_unique(SIZE_FUNC_NAME, + result.push_back(std::make_unique(name, std::vector{LogicalTypeID::STRING}, LogicalTypeID::INT64, ScalarFunction::UnaryExecFunction, true /* isVarlength*/)); return result; } template -static void BinaryExecListExtractFunction( - const std::vector>& params, common::ValueVector& result, - void* /*dataPtr*/ = nullptr) { +static void BinaryExecListExtractFunction(const std::vector>& params, + ValueVector& result, void* /*dataPtr*/ = nullptr) { KU_ASSERT(params.size() == 2); - BinaryFunctionExecutor::executeListExtract( - *params[0], *params[1], result); + BinaryFunctionExecutor::executeListExtract(*params[0], + *params[1], result); } -std::unique_ptr ListExtractFunction::bindFunc( +static std::unique_ptr ListExtractBindFunc( const binder::expression_vector& arguments, Function* function) { - auto resultType = VarListType::getChildType(&arguments[0]->dataType); + auto resultType = ListType::getChildType(&arguments[0]->dataType); auto scalarFunction = ku_dynamic_cast(function); switch (resultType->getPhysicalType()) { case PhysicalTypeID::BOOL: { @@ -204,7 +400,7 @@ std::unique_ptr ListExtractFunction::bindFunc( scalarFunction->execFunc = BinaryExecListExtractFunction; } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { scalarFunction->execFunc = BinaryExecListExtractFunction; } break; @@ -225,127 +421,130 @@ std::unique_ptr ListExtractFunction::bindFunc( function_set ListExtractFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_EXTRACT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::INT64}, - LogicalTypeID::ANY, nullptr, nullptr, bindFunc, false /* isVarlength*/)); - result.push_back(std::make_unique(LIST_EXTRACT_FUNC_NAME, + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::INT64}, LogicalTypeID::ANY, + nullptr, nullptr, ListExtractBindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::BinaryExecFunction, false /* isVarlength */)); - return result; -} - -function_set ListConcatFunction::getFunctionSet() { - function_set result; - auto execFunc = ScalarFunction::BinaryExecListStructFunction; - result.push_back(std::make_unique(LIST_CONCAT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::VAR_LIST}, - LogicalTypeID::VAR_LIST, execFunc, nullptr, bindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::ARRAY, LogicalTypeID::INT64}, LogicalTypeID::ANY, + nullptr, nullptr, ListExtractBindFunc, false /* isVarlength*/)); return result; } std::unique_ptr ListConcatFunction::bindFunc( const binder::expression_vector& arguments, Function* /*function*/) { if (arguments[0]->getDataType() != arguments[1]->getDataType()) { - throw BinderException(getListFunctionIncompatibleChildrenTypeErrorMsg( - LIST_CONCAT_FUNC_NAME, arguments[0]->getDataType(), arguments[1]->getDataType())); + throw BinderException(getListFunctionIncompatibleChildrenTypeErrorMsg(name, + arguments[0]->getDataType(), arguments[1]->getDataType())); } return std::make_unique(arguments[0]->getDataType().copy()); } -std::unique_ptr ListAppendFunction::bindFunc( +function_set ListConcatFunction::getFunctionSet() { + function_set result; + auto execFunc = ScalarFunction::BinaryExecListStructFunction; + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::LIST}, LogicalTypeID::LIST, + execFunc, nullptr, bindFunc, false /* isVarlength*/)); + return result; +} + +static std::unique_ptr ListAppendBindFunc( const binder::expression_vector& arguments, Function* function) { - if (*VarListType::getChildType(&arguments[0]->dataType) != arguments[1]->getDataType()) { + if (*ListType::getChildType(&arguments[0]->dataType) != arguments[1]->getDataType()) { throw BinderException(getListFunctionIncompatibleChildrenTypeErrorMsg( - LIST_APPEND_FUNC_NAME, arguments[0]->getDataType(), arguments[1]->getDataType())); + ListAppendFunction::name, arguments[0]->getDataType(), arguments[1]->getDataType())); } auto resultType = arguments[0]->getDataType(); auto scalarFunction = ku_dynamic_cast(function); scalarFunction->execFunc = - ListFunction::getBinaryListExecFuncSwitchRight( - arguments[1]->getDataType()); + getBinaryListExecFuncSwitchRight(arguments[1]->getDataType()); return std::make_unique(resultType.copy()); } function_set ListAppendFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_APPEND_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::ANY}, - LogicalTypeID::VAR_LIST, nullptr, nullptr, bindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::ANY}, LogicalTypeID::LIST, + nullptr, nullptr, ListAppendBindFunc, false /* isVarlength*/)); return result; } -std::unique_ptr ListPrependFunction::bindFunc( +static std::unique_ptr ListPrependBindFunc( const binder::expression_vector& arguments, Function* function) { if (arguments[0]->getDataType().getLogicalTypeID() != LogicalTypeID::ANY && - arguments[1]->dataType != *VarListType::getChildType(&arguments[0]->dataType)) { + arguments[1]->dataType != *ListType::getChildType(&arguments[0]->dataType)) { throw BinderException(getListFunctionIncompatibleChildrenTypeErrorMsg( - LIST_PREPEND_FUNC_NAME, arguments[0]->getDataType(), arguments[1]->getDataType())); + ListPrependFunction::name, arguments[0]->getDataType(), arguments[1]->getDataType())); } auto resultType = arguments[0]->getDataType(); auto scalarFunction = ku_dynamic_cast(function); scalarFunction->execFunc = - ListFunction::getBinaryListExecFuncSwitchRight( - arguments[1]->getDataType()); + getBinaryListExecFuncSwitchRight(arguments[1]->getDataType()); return std::make_unique(resultType.copy()); } function_set ListPrependFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_PREPEND_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::ANY}, - LogicalTypeID::VAR_LIST, nullptr, nullptr, bindFunc, false /* isVarlength */)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::ANY}, LogicalTypeID::LIST, + nullptr, nullptr, ListPrependBindFunc, false /* isVarlength */)); return result; } +static std::unique_ptr ListPositionBindFunc( + const binder::expression_vector& arguments, Function* function) { + auto scalarFunction = ku_dynamic_cast(function); + scalarFunction->execFunc = + getBinaryListExecFuncSwitchRight(arguments[1]->getDataType()); + return std::make_unique(LogicalType::INT64()); +} + function_set ListPositionFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_POSITION_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::ANY}, - LogicalTypeID::INT64, nullptr, nullptr, bindFunc, false /* isVarlength */)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::ANY}, LogicalTypeID::INT64, + nullptr, nullptr, ListPositionBindFunc, false /* isVarlength */)); return result; } -std::unique_ptr ListPositionFunction::bindFunc( +static std::unique_ptr ListContainsBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); scalarFunction->execFunc = - ListFunction::getBinaryListExecFuncSwitchRight( - arguments[1]->getDataType()); - return std::make_unique(LogicalType::INT64()); + getBinaryListExecFuncSwitchRight(arguments[1]->getDataType()); + return std::make_unique(LogicalType::BOOL()); } function_set ListContainsFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_CONTAINS_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::ANY}, - LogicalTypeID::BOOL, nullptr, nullptr, bindFunc, false /* isVarlength */)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::ANY}, LogicalTypeID::BOOL, + nullptr, nullptr, ListContainsBindFunc, false /* isVarlength */)); return result; } -std::unique_ptr ListContainsFunction::bindFunc( - const binder::expression_vector& arguments, Function* function) { - auto scalarFunction = ku_dynamic_cast(function); - scalarFunction->execFunc = - ListFunction::getBinaryListExecFuncSwitchRight( - arguments[1]->getDataType()); - return std::make_unique(LogicalType::BOOL()); +static std::unique_ptr ListSliceBindFunc( + const binder::expression_vector& arguments, Function* /*function*/) { + return std::make_unique(arguments[0]->getDataType().copy()); } function_set ListSliceFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_SLICE_FUNC_NAME, - std::vector{ - LogicalTypeID::VAR_LIST, LogicalTypeID::INT64, LogicalTypeID::INT64}, - LogicalTypeID::VAR_LIST, + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::INT64, LogicalTypeID::INT64}, + LogicalTypeID::LIST, ScalarFunction::TernaryExecListStructFunction, - nullptr, bindFunc, false /* isVarlength*/)); - result.push_back(std::make_unique(LIST_SLICE_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::INT64, LogicalTypeID::INT64}, + nullptr, ListSliceBindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64, + LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::TernaryExecListStructFunction, @@ -353,90 +552,89 @@ function_set ListSliceFunction::getFunctionSet() { return result; } -std::unique_ptr ListSliceFunction::bindFunc( - const binder::expression_vector& arguments, Function* /*function*/) { - return std::make_unique(arguments[0]->getDataType().copy()); -} - -function_set ListSortFunction::getFunctionSet() { - function_set result; - result.push_back(std::make_unique(LIST_SORT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::VAR_LIST, nullptr, - nullptr, bindFunc, false /* isVarlength*/)); - result.push_back(std::make_unique(LIST_SORT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::STRING}, - LogicalTypeID::VAR_LIST, nullptr, nullptr, bindFunc, false /* isVarlength*/)); - result.push_back(std::make_unique(LIST_SORT_FUNC_NAME, - std::vector{ - LogicalTypeID::VAR_LIST, LogicalTypeID::STRING, LogicalTypeID::STRING}, - LogicalTypeID::VAR_LIST, nullptr, nullptr, bindFunc, false /* isVarlength*/)); - return result; +template +static void getListSortExecFunction(const binder::expression_vector& arguments, + scalar_func_exec_t& func) { + if (arguments.size() == 1) { + func = ScalarFunction::UnaryExecNestedTypeFunction>; + return; + } else if (arguments.size() == 2) { + func = ScalarFunction::BinaryExecListStructFunction>; + return; + } else if (arguments.size() == 3) { + func = ScalarFunction::TernaryExecListStructFunction>; + return; + } else { + throw RuntimeException("Invalid number of arguments"); + } } -std::unique_ptr ListSortFunction::bindFunc( +static std::unique_ptr ListSortBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); - switch (VarListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { + switch (ListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { case LogicalTypeID::SERIAL: case LogicalTypeID::INT64: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT32: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT16: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT8: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT64: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT32: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT16: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT8: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT128: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::DOUBLE: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::FLOAT: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::BOOL: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::STRING: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::DATE: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_MS: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_NS: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_SEC: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_TZ: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INTERVAL: { - getExecFunction(arguments, scalarFunction->execFunc); + getListSortExecFunction(arguments, scalarFunction->execFunc); } break; default: { KU_UNREACHABLE; @@ -445,100 +643,101 @@ std::unique_ptr ListSortFunction::bindFunc( return std::make_unique(arguments[0]->getDataType().copy()); } +function_set ListSortFunction::getFunctionSet() { + function_set result; + result.push_back( + std::make_unique(name, std::vector{LogicalTypeID::LIST}, + LogicalTypeID::LIST, nullptr, nullptr, ListSortBindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::STRING}, LogicalTypeID::LIST, + nullptr, nullptr, ListSortBindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::STRING, + LogicalTypeID::STRING}, + LogicalTypeID::LIST, nullptr, nullptr, ListSortBindFunc, false /* isVarlength*/)); + return result; +} + template -void ListSortFunction::getExecFunction( - const binder::expression_vector& arguments, scalar_exec_func& func) { +static void getListReverseSortExecFunction(const binder::expression_vector& arguments, + scalar_func_exec_t& func) { if (arguments.size() == 1) { - func = ScalarFunction::UnaryExecNestedTypeFunction>; + func = ScalarFunction::UnaryExecNestedTypeFunction>; return; } else if (arguments.size() == 2) { func = ScalarFunction::BinaryExecListStructFunction>; - return; - } else if (arguments.size() == 3) { - func = ScalarFunction::TernaryExecListStructFunction>; + ListReverseSort>; return; } else { throw RuntimeException("Invalid number of arguments"); } } -function_set ListReverseSortFunction::getFunctionSet() { - function_set result; - result.push_back(std::make_unique(LIST_REVERSE_SORT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::VAR_LIST, nullptr, - nullptr, bindFunc, false /* isVarlength*/)); - result.push_back(std::make_unique(LIST_REVERSE_SORT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::STRING}, - LogicalTypeID::VAR_LIST, nullptr, nullptr, bindFunc, false /* isVarlength*/)); - return result; -} - -std::unique_ptr ListReverseSortFunction::bindFunc( +static std::unique_ptr ListReverseSortBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); - switch (VarListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { + switch (ListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { case LogicalTypeID::SERIAL: case LogicalTypeID::INT64: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT32: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT16: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT8: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT64: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT32: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT16: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::UINT8: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INT128: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::DOUBLE: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::FLOAT: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::BOOL: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::STRING: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::DATE: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_MS: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_NS: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_SEC: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP_TZ: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::TIMESTAMP: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; case LogicalTypeID::INTERVAL: { - getExecFunction(arguments, scalarFunction->execFunc); + getListReverseSortExecFunction(arguments, scalarFunction->execFunc); } break; default: { KU_UNREACHABLE; @@ -547,50 +746,37 @@ std::unique_ptr ListReverseSortFunction::bindFunc( return std::make_unique(arguments[0]->getDataType().copy()); } -template -void ListReverseSortFunction::getExecFunction( - const binder::expression_vector& arguments, scalar_exec_func& func) { - if (arguments.size() == 1) { - func = ScalarFunction::UnaryExecNestedTypeFunction>; - return; - } else if (arguments.size() == 2) { - func = ScalarFunction::BinaryExecListStructFunction>; - return; - } else { - throw RuntimeException("Invalid number of arguments"); - } -} - -function_set ListSumFunction::getFunctionSet() { +function_set ListReverseSortFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_SUM_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::INT64, nullptr, nullptr, - ListFunction::bindFuncListAggr, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST}, LogicalTypeID::LIST, nullptr, nullptr, + ListReverseSortBindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::STRING}, LogicalTypeID::LIST, + nullptr, nullptr, ListReverseSortBindFunc, false /* isVarlength*/)); return result; } -function_set ListProductFunction::getFunctionSet() { +function_set ListSumFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_PRODUCT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::INT64, nullptr, nullptr, - ListFunction::bindFuncListAggr, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST}, LogicalTypeID::INT64, nullptr, nullptr, + bindFuncListAggr, false /* isVarlength*/)); return result; } -function_set ListDistinctFunction::getFunctionSet() { +function_set ListProductFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_DISTINCT_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::VAR_LIST, nullptr, - nullptr, bindFunc, false /* isVarlength*/)); + result.push_back(std::make_unique(name, + std::vector{LogicalTypeID::LIST}, LogicalTypeID::INT64, nullptr, nullptr, + bindFuncListAggr, false /* isVarlength*/)); return result; } -std::unique_ptr ListDistinctFunction::bindFunc( +static std::unique_ptr ListDistinctBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); - switch (VarListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { + switch (ListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { case LogicalTypeID::SERIAL: case LogicalTypeID::INT64: { scalarFunction->execFunc = ScalarFunction::UnaryExecNestedTypeFunction ListDistinctFunction::bindFunc( return std::make_unique(arguments[0]->getDataType().copy()); } -function_set ListUniqueFunction::getFunctionSet() { +function_set ListDistinctFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_UNIQUE_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::INT64, nullptr, nullptr, - bindFunc, false /* isVarlength*/)); + result.push_back( + std::make_unique(name, std::vector{LogicalTypeID::LIST}, + LogicalTypeID::LIST, nullptr, nullptr, ListDistinctBindFunc, false /* isVarlength*/)); return result; } -std::unique_ptr ListUniqueFunction::bindFunc( +static std::unique_ptr ListUniqueBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); - switch (VarListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { + switch (ListType::getChildType(&arguments[0]->dataType)->getLogicalTypeID()) { case LogicalTypeID::SERIAL: case LogicalTypeID::INT64: { scalarFunction->execFunc = @@ -787,18 +973,18 @@ std::unique_ptr ListUniqueFunction::bindFunc( return std::make_unique(LogicalType::INT64()); } -function_set ListAnyValueFunction::getFunctionSet() { +function_set ListUniqueFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_ANY_VALUE_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::ANY, nullptr, nullptr, - bindFunc, false /* isVarlength*/)); + result.push_back( + std::make_unique(name, std::vector{LogicalTypeID::LIST}, + LogicalTypeID::INT64, nullptr, nullptr, ListUniqueBindFunc, false /* isVarlength*/)); return result; } -std::unique_ptr ListAnyValueFunction::bindFunc( +static std::unique_ptr ListAnyValueBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); - auto resultType = VarListType::getChildType(&arguments[0]->dataType); + auto resultType = ListType::getChildType(&arguments[0]->dataType); switch (resultType->getLogicalTypeID()) { case LogicalTypeID::SERIAL: case LogicalTypeID::INT64: { @@ -881,7 +1067,7 @@ std::unique_ptr ListAnyValueFunction::bindFunc( scalarFunction->execFunc = ScalarFunction::UnaryExecNestedTypeFunction; } break; - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::LIST: { scalarFunction->execFunc = ScalarFunction::UnaryExecNestedTypeFunction; } break; @@ -896,6 +1082,14 @@ std::unique_ptr ListAnyValueFunction::bindFunc( return std::make_unique(resultType->copy()); } +function_set ListAnyValueFunction::getFunctionSet() { + function_set result; + result.push_back( + std::make_unique(name, std::vector{LogicalTypeID::LIST}, + LogicalTypeID::ANY, nullptr, nullptr, ListAnyValueBindFunc, false /* isVarlength*/)); + return result; +} + static std::unique_ptr ListReverseBindFunc( const binder::expression_vector& arguments, Function* function) { auto scalarFunction = ku_dynamic_cast(function); @@ -907,9 +1101,9 @@ static std::unique_ptr ListReverseBindFunc( function_set ListReverseFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(LIST_REVERSE_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST}, LogicalTypeID::ANY, nullptr, nullptr, - ListReverseBindFunc, false /* isVarlength*/)); + result.push_back( + std::make_unique(name, std::vector{LogicalTypeID::LIST}, + LogicalTypeID::ANY, nullptr, nullptr, ListReverseBindFunc, false /* isVarlength*/)); return result; } diff --git a/src/function/vector_map_functions.cpp b/src/function/vector_map_functions.cpp index d1fd14190e6..60685f70c08 100644 --- a/src/function/vector_map_functions.cpp +++ b/src/function/vector_map_functions.cpp @@ -1,39 +1,31 @@ #include "function/map/vector_map_functions.h" -#include "function/list/vector_list_functions.h" #include "function/map/functions/map_creation_function.h" #include "function/map/functions/map_extract_function.h" #include "function/map/functions/map_keys_function.h" #include "function/map/functions/map_values_function.h" +#include "function/scalar_function.h" using namespace kuzu::common; namespace kuzu { namespace function { -function_set MapCreationFunctions::getFunctionSet() { - auto execFunc = ScalarFunction::BinaryExecListStructFunction; - function_set functionSet; - functionSet.push_back(make_unique(MAP_CREATION_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::VAR_LIST}, - LogicalTypeID::MAP, execFunc, nullptr, bindFunc, false /* isVarLength */)); - return functionSet; -} - -std::unique_ptr MapCreationFunctions::bindFunc( +static std::unique_ptr MapCreationBindFunc( const binder::expression_vector& arguments, kuzu::function::Function* /*function*/) { - auto keyType = VarListType::getChildType(&arguments[0]->dataType); - auto valueType = VarListType::getChildType(&arguments[1]->dataType); + auto keyType = ListType::getChildType(&arguments[0]->dataType); + auto valueType = ListType::getChildType(&arguments[1]->dataType); auto resultType = LogicalType::MAP(*keyType, *valueType); return std::make_unique(std::move(resultType)); } -function_set MapExtractFunctions::getFunctionSet() { +function_set MapCreationFunctions::getFunctionSet() { + auto execFunc = ScalarFunction::BinaryExecListStructFunction; function_set functionSet; - functionSet.push_back(make_unique(MAP_EXTRACT_FUNC_NAME, - std::vector{LogicalTypeID::MAP, LogicalTypeID::ANY}, LogicalTypeID::VAR_LIST, - nullptr, nullptr, bindFunc, false /* isVarLength */)); + functionSet.push_back(make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::LIST}, LogicalTypeID::MAP, + execFunc, nullptr, MapCreationBindFunc, false /* isVarLength */)); return functionSet; } @@ -45,48 +37,126 @@ static void validateKeyType(const std::shared_ptr& mapExpres } } -std::unique_ptr MapExtractFunctions::bindFunc( +static std::unique_ptr MapExtractBindFunc( const binder::expression_vector& arguments, kuzu::function::Function* function) { validateKeyType(arguments[0], arguments[1]); auto scalarFunction = ku_dynamic_cast(function); - scalarFunction->execFunc = - ListFunction::getBinaryListExecFuncSwitchRight( - arguments[1]->getDataType()); - return std::make_unique(LogicalType::VAR_LIST( + switch (arguments[1]->getDataType().getPhysicalType()) { + case PhysicalTypeID::BOOL: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT64: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT32: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT16: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT8: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT64: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT32: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT16: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::UINT8: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INT128: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::DOUBLE: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::FLOAT: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::STRING: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INTERVAL: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::INTERNAL_ID: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::LIST: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + case PhysicalTypeID::STRUCT: { + scalarFunction->execFunc = ScalarFunction::BinaryExecListStructFunction; + } break; + default: { + KU_UNREACHABLE; + } + } + return std::make_unique(LogicalType::LIST( std::make_unique(*MapType::getValueType(&arguments[0]->dataType)))); } +function_set MapExtractFunctions::getFunctionSet() { + function_set functionSet; + functionSet.push_back(make_unique(name, + std::vector{LogicalTypeID::MAP, LogicalTypeID::ANY}, LogicalTypeID::LIST, + nullptr, nullptr, MapExtractBindFunc, false /* isVarLength */)); + return functionSet; +} + +static std::unique_ptr MapKeysBindFunc(const binder::expression_vector& arguments, + kuzu::function::Function* /*function*/) { + return std::make_unique(LogicalType::LIST( + std::make_unique(*MapType::getKeyType(&arguments[0]->dataType)))); +} + function_set MapKeysFunctions::getFunctionSet() { auto execFunc = ScalarFunction::UnaryExecNestedTypeFunction; function_set functionSet; - functionSet.push_back(make_unique(MAP_KEYS_FUNC_NAME, - std::vector{LogicalTypeID::MAP}, LogicalTypeID::VAR_LIST, execFunc, nullptr, - bindFunc, false /* isVarLength */)); + functionSet.push_back( + make_unique(name, std::vector{LogicalTypeID::MAP}, + LogicalTypeID::LIST, execFunc, nullptr, MapKeysBindFunc, false /* isVarLength */)); return functionSet; } -std::unique_ptr MapKeysFunctions::bindFunc( +static std::unique_ptr MapValuesBindFunc( const binder::expression_vector& arguments, kuzu::function::Function* /*function*/) { - return std::make_unique(LogicalType::VAR_LIST( - std::make_unique(*MapType::getKeyType(&arguments[0]->dataType)))); + return std::make_unique(LogicalType::LIST( + std::make_unique(*MapType::getValueType(&arguments[0]->dataType)))); } function_set MapValuesFunctions::getFunctionSet() { auto execFunc = ScalarFunction::UnaryExecNestedTypeFunction; function_set functionSet; - functionSet.push_back(make_unique(MAP_VALUES_FUNC_NAME, - std::vector{LogicalTypeID::MAP}, LogicalTypeID::VAR_LIST, execFunc, nullptr, - bindFunc, false /* isVarLength */)); + functionSet.push_back( + make_unique(name, std::vector{LogicalTypeID::MAP}, + LogicalTypeID::LIST, execFunc, nullptr, MapValuesBindFunc, false /* isVarLength */)); return functionSet; } -std::unique_ptr MapValuesFunctions::bindFunc( - const binder::expression_vector& arguments, kuzu::function::Function* /*function*/) { - return std::make_unique(LogicalType::VAR_LIST( - std::make_unique(*MapType::getValueType(&arguments[0]->dataType)))); -} - } // namespace function } // namespace kuzu diff --git a/src/function/vector_node_rel_functions.cpp b/src/function/vector_node_rel_functions.cpp index 41520b8ef4c..dc223395731 100644 --- a/src/function/vector_node_rel_functions.cpp +++ b/src/function/vector_node_rel_functions.cpp @@ -1,15 +1,26 @@ #include "function/schema/vector_node_rel_functions.h" +#include "common/vector/value_vector.h" +#include "function/scalar_function.h" +#include "function/schema/offset_functions.h" +#include "function/unary_function_executor.h" + using namespace kuzu::common; namespace kuzu { namespace function { +static void OffsetExecFunc(const std::vector>& params, + ValueVector& result, void* /*dataPtr*/ = nullptr) { + KU_ASSERT(params.size() == 1); + UnaryFunctionExecutor::execute(*params[0], result); +} + function_set OffsetFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(make_unique(OFFSET_FUNC_NAME, - std::vector{LogicalTypeID::INTERNAL_ID}, LogicalTypeID::INT64, - OffsetFunction::execFunction)); + functionSet.push_back( + make_unique(name, std::vector{LogicalTypeID::INTERNAL_ID}, + LogicalTypeID::INT64, OffsetExecFunc)); return functionSet; } diff --git a/src/function/vector_null_functions.cpp b/src/function/vector_null_functions.cpp index 1c07f166bcf..03711dd973b 100644 --- a/src/function/vector_null_functions.cpp +++ b/src/function/vector_null_functions.cpp @@ -8,7 +8,7 @@ namespace kuzu { namespace function { void VectorNullFunction::bindExecFunction(ExpressionType expressionType, - const binder::expression_vector& /*children*/, scalar_exec_func& func) { + const binder::expression_vector& /*children*/, scalar_func_exec_t& func) { switch (expressionType) { case ExpressionType::IS_NULL: { func = UnaryNullExecFunction; @@ -25,7 +25,7 @@ void VectorNullFunction::bindExecFunction(ExpressionType expressionType, } void VectorNullFunction::bindSelectFunction(ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func) { + const binder::expression_vector& children, scalar_func_select_t& func) { KU_ASSERT(children.size() == 1); (void)children; switch (expressionType) { diff --git a/src/function/vector_path_functions.cpp b/src/function/vector_path_functions.cpp index 2077e0cb448..dfa202f759e 100644 --- a/src/function/vector_path_functions.cpp +++ b/src/function/vector_path_functions.cpp @@ -3,7 +3,9 @@ #include "binder/expression/literal_expression.h" #include "common/exception/binder.h" #include "common/string_format.h" +#include "common/vector/value_vector.h" #include "function/path/path_function_executor.h" +#include "function/scalar_function.h" #include "function/struct/vector_struct_functions.h" using namespace kuzu::common; @@ -11,55 +13,47 @@ using namespace kuzu::common; namespace kuzu { namespace function { -function_set NodesFunction::getFunctionSet() { - function_set functionSet; - functionSet.push_back(make_unique(NODES_FUNC_NAME, - std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::ANY, nullptr, - nullptr, StructExtractFunctions::compileFunc, bindFunc, false /* isVarLength */)); - return functionSet; -} - -std::unique_ptr NodesFunction::bindFunc( - const binder::expression_vector& arguments, Function* /*function*/) { +static std::unique_ptr NodesBindFunc(const binder::expression_vector& arguments, + Function* /*function*/) { auto structType = arguments[0]->getDataType(); auto fieldIdx = StructType::getFieldIdx(&structType, InternalKeyword::NODES); return std::make_unique( StructType::getFieldTypes(&structType)[fieldIdx]->copy(), fieldIdx); } -function_set RelsFunction::getFunctionSet() { +function_set NodesFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(make_unique(RELS_FUNC_NAME, + functionSet.push_back(make_unique(name, std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::ANY, nullptr, - nullptr, StructExtractFunctions::compileFunc, bindFunc, false /* isVarLength */)); + nullptr, StructExtractFunctions::compileFunc, NodesBindFunc, false /* isVarLength */)); return functionSet; } -std::unique_ptr RelsFunction::bindFunc( - const binder::expression_vector& arguments, Function* /*function*/) { +static std::unique_ptr RelsBindFunc(const binder::expression_vector& arguments, + Function* /*function*/) { auto structType = arguments[0]->getDataType(); auto fieldIdx = StructType::getFieldIdx(&structType, InternalKeyword::RELS); return std::make_unique( StructType::getFieldTypes(&structType)[fieldIdx]->copy(), fieldIdx); } -function_set PropertiesFunction::getFunctionSet() { - function_set functions; - functions.push_back(make_unique(PROPERTIES_FUNC_NAME, - std::vector{LogicalTypeID::VAR_LIST, LogicalTypeID::STRING}, - LogicalTypeID::ANY, execFunc, nullptr, compileFunc, bindFunc, false /* isVarLength */)); - return functions; +function_set RelsFunction::getFunctionSet() { + function_set functionSet; + functionSet.push_back(make_unique(name, + std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::ANY, nullptr, + nullptr, StructExtractFunctions::compileFunc, RelsBindFunc, false /* isVarLength */)); + return functionSet; } -std::unique_ptr PropertiesFunction::bindFunc( +static std::unique_ptr PropertiesBindFunc( const binder::expression_vector& arguments, Function* /*function*/) { if (arguments[1]->expressionType != ExpressionType::LITERAL) { throw BinderException(stringFormat( - "Expected literal input as the second argument for {}().", PROPERTIES_FUNC_NAME)); + "Expected literal input as the second argument for {}().", PropertiesFunction::name)); } auto key = ((binder::LiteralExpression&)*arguments[1]).getValue()->getValue(); auto listType = arguments[0]->getDataType(); - auto childType = VarListType::getChildType(&listType); + auto childType = ListType::getChildType(&listType); struct_field_idx_t fieldIdx; if (childType->getLogicalTypeID() == LogicalTypeID::NODE || childType->getLogicalTypeID() == LogicalTypeID::REL) { @@ -72,21 +66,21 @@ std::unique_ptr PropertiesFunction::bindFunc( stringFormat("Cannot extract properties from {}.", listType.toString())); } auto field = StructType::getField(childType, fieldIdx); - auto returnType = LogicalType::VAR_LIST(field->getType()->copy()); + auto returnType = LogicalType::LIST(field->getType()->copy()); return std::make_unique(std::move(returnType), fieldIdx); } -void PropertiesFunction::compileFunc(FunctionBindData* bindData, +static void PropertiesCompileFunc(FunctionBindData* bindData, const std::vector>& parameters, std::shared_ptr& result) { - KU_ASSERT(parameters[0]->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + KU_ASSERT(parameters[0]->dataType.getPhysicalType() == PhysicalTypeID::LIST); auto propertiesBindData = reinterpret_cast(bindData); - auto fieldVector = StructVector::getFieldVector( - ListVector::getDataVector(parameters[0].get()), propertiesBindData->childIdx); + auto fieldVector = StructVector::getFieldVector(ListVector::getDataVector(parameters[0].get()), + propertiesBindData->childIdx); ListVector::setDataVector(result.get(), fieldVector); } -void PropertiesFunction::execFunc(const std::vector>& parameters, +static void PropertiesExecFunc(const std::vector>& parameters, ValueVector& result, void* /*dataPtr*/) { if (parameters[0]->state->isFlat()) { auto inputPos = parameters[0]->state->selVector->selectedPositions[0]; @@ -114,41 +108,50 @@ void PropertiesFunction::execFunc(const std::vector } } -function_set IsTrailFunction::getFunctionSet() { - function_set functionSet; - functionSet.push_back(make_unique(IS_TRAIL_FUNC_NAME, - std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::BOOL, execFunc, - selectFunc, nullptr, nullptr, false /* isVarLength */)); - return functionSet; +function_set PropertiesFunction::getFunctionSet() { + function_set functions; + functions.push_back(make_unique(name, + std::vector{LogicalTypeID::LIST, LogicalTypeID::STRING}, LogicalTypeID::ANY, + PropertiesExecFunc, nullptr, PropertiesCompileFunc, PropertiesBindFunc, + false /* isVarLength */)); + return functions; } -void IsTrailFunction::execFunc(const std::vector>& parameters, +static void IsTrailExecFunc(const std::vector>& parameters, ValueVector& result, void* /*dataPtr*/) { UnaryPathExecutor::executeRelIDs(*parameters[0], result); } -bool IsTrailFunction::selectFunc( - const std::vector>& parameters, SelectionVector& selectionVector) { +static bool IsTrailSelectFunc(const std::vector>& parameters, + SelectionVector& selectionVector) { return UnaryPathExecutor::selectRelIDs(*parameters[0], selectionVector); } -function_set IsACyclicFunction::getFunctionSet() { +function_set IsTrailFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(make_unique(IS_ACYCLIC_FUNC_NAME, - std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::BOOL, execFunc, - selectFunc, nullptr, nullptr, false /* isVarLength */)); + functionSet.push_back(make_unique(name, + std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::BOOL, + IsTrailExecFunc, IsTrailSelectFunc, nullptr, nullptr, false /* isVarLength */)); return functionSet; } -void IsACyclicFunction::execFunc(const std::vector>& parameters, +static void IsACyclicExecFunc(const std::vector>& parameters, ValueVector& result, void* /*dataPtr*/) { UnaryPathExecutor::executeNodeIDs(*parameters[0], result); } -bool IsACyclicFunction::selectFunc( - const std::vector>& parameters, SelectionVector& selectionVector) { +static bool IsACyclicSelectFunc(const std::vector>& parameters, + SelectionVector& selectionVector) { return UnaryPathExecutor::selectNodeIDs(*parameters[0], selectionVector); } +function_set IsACyclicFunction::getFunctionSet() { + function_set functionSet; + functionSet.push_back(make_unique(name, + std::vector{LogicalTypeID::RECURSIVE_REL}, LogicalTypeID::BOOL, + IsACyclicExecFunc, IsACyclicSelectFunc, nullptr, nullptr, false /* isVarLength */)); + return functionSet; +} + } // namespace function } // namespace kuzu diff --git a/src/function/vector_rdf_functions.cpp b/src/function/vector_rdf_functions.cpp index 7ec759c0499..81446fff0eb 100644 --- a/src/function/vector_rdf_functions.cpp +++ b/src/function/vector_rdf_functions.cpp @@ -1,6 +1,7 @@ #include "function/rdf/vector_rdf_functions.h" #include "function/rdf/rdf_functions.h" +#include "function/scalar_function.h" using namespace kuzu::common; @@ -9,7 +10,7 @@ namespace function { function_set RDFTypeFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(TYPE_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::RDF_VARIANT}, LogicalTypeID::STRING, ScalarFunction::UnaryExecNestedTypeFunction)); return result; @@ -17,7 +18,7 @@ function_set RDFTypeFunction::getFunctionSet() { function_set ValidatePredicateFunction::getFunctionSet() { function_set result; - result.push_back(std::make_unique(VALIDATE_PREDICATE_FUNC_NAME, + result.push_back(std::make_unique(name, std::vector{LogicalTypeID::STRING}, LogicalTypeID::STRING, ScalarFunction::UnaryStringExecFunction)); return result; diff --git a/src/function/vector_string_functions.cpp b/src/function/vector_string_functions.cpp index fd285f6deb6..5c48e904244 100644 --- a/src/function/vector_string_functions.cpp +++ b/src/function/vector_string_functions.cpp @@ -1,9 +1,9 @@ #include "function/string/vector_string_functions.h" #include "function/string/functions/array_extract_function.h" -#include "function/string/functions/concat_function.h" #include "function/string/functions/contains_function.h" #include "function/string/functions/ends_with_function.h" +#include "function/string/functions/initcap_function.h" #include "function/string/functions/left_operation.h" #include "function/string/functions/levenshtein_function.h" #include "function/string/functions/lpad_function.h" @@ -23,74 +23,49 @@ using namespace kuzu::common; namespace kuzu { namespace function { -void BaseLowerUpperFunction::operation(common::ku_string_t& input, common::ku_string_t& result, - common::ValueVector& resultValueVector, bool isUpper) { +void BaseLowerUpperFunction::operation(ku_string_t& input, ku_string_t& result, + ValueVector& resultValueVector, bool isUpper) { uint32_t resultLen = getResultLen((char*)input.getData(), input.len, isUpper); result.len = resultLen; - if (resultLen <= common::ku_string_t::SHORT_STR_LENGTH) { + if (resultLen <= ku_string_t::SHORT_STR_LENGTH) { convertCase((char*)result.prefix, input.len, (char*)input.getData(), isUpper); } else { - result.overflowPtr = reinterpret_cast( - common::StringVector::getInMemOverflowBuffer(&resultValueVector) - ->allocateSpace(result.len)); + StringVector::reserveString(&resultValueVector, result, resultLen); auto buffer = reinterpret_cast(result.overflowPtr); convertCase(buffer, input.len, (char*)input.getData(), isUpper); - memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH); + memcpy(result.prefix, buffer, ku_string_t::PREFIX_LENGTH); } } -void BaseStrOperation::operation(common::ku_string_t& input, common::ku_string_t& result, - common::ValueVector& resultValueVector, uint32_t (*strOperation)(char* data, uint32_t len)) { - if (input.len <= common::ku_string_t::SHORT_STR_LENGTH) { +void BaseStrOperation::operation(ku_string_t& input, ku_string_t& result, + ValueVector& resultValueVector, uint32_t (*strOperation)(char* data, uint32_t len)) { + if (input.len <= ku_string_t::SHORT_STR_LENGTH) { memcpy(result.prefix, input.prefix, input.len); result.len = strOperation((char*)result.prefix, input.len); } else { - result.overflowPtr = reinterpret_cast( - common::StringVector::getInMemOverflowBuffer(&resultValueVector) - ->allocateSpace(input.len)); + StringVector::reserveString(&resultValueVector, result, input.len); auto buffer = reinterpret_cast(result.overflowPtr); memcpy(buffer, input.getData(), input.len); result.len = strOperation(buffer, input.len); memcpy(result.prefix, buffer, - result.len < common::ku_string_t::PREFIX_LENGTH ? result.len : - common::ku_string_t::PREFIX_LENGTH); + result.len < ku_string_t::PREFIX_LENGTH ? result.len : ku_string_t::PREFIX_LENGTH); } } -void Concat::concat(const char* left, uint32_t leftLen, const char* right, uint32_t rightLen, - common::ku_string_t& result, common::ValueVector& resultValueVector) { - auto len = leftLen + rightLen; - if (len <= common::ku_string_t::SHORT_STR_LENGTH /* concat result is short */) { - memcpy(result.prefix, left, leftLen); - memcpy(result.prefix + leftLen, right, rightLen); - } else { - result.overflowPtr = reinterpret_cast( - common::StringVector::getInMemOverflowBuffer(&resultValueVector)->allocateSpace(len)); - auto buffer = reinterpret_cast(result.overflowPtr); - memcpy(buffer, left, leftLen); - memcpy(buffer + leftLen, right, rightLen); - memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH); - } - result.len = len; -} - -void Repeat::operation(common::ku_string_t& left, int64_t& right, common::ku_string_t& result, - common::ValueVector& resultValueVector) { +void Repeat::operation(ku_string_t& left, int64_t& right, ku_string_t& result, + ValueVector& resultValueVector) { result.len = left.len * right; - if (result.len <= common::ku_string_t::SHORT_STR_LENGTH) { + if (result.len <= ku_string_t::SHORT_STR_LENGTH) { repeatStr((char*)result.prefix, left.getAsString(), right); } else { - result.overflowPtr = reinterpret_cast( - common::StringVector::getInMemOverflowBuffer(&resultValueVector) - ->allocateSpace(result.len)); + StringVector::reserveString(&resultValueVector, result, result.len); auto buffer = reinterpret_cast(result.overflowPtr); repeatStr(buffer, left.getAsString(), right); - memcpy(result.prefix, buffer, common::ku_string_t::PREFIX_LENGTH); + memcpy(result.prefix, buffer, ku_string_t::PREFIX_LENGTH); } } -void Reverse::operation(common::ku_string_t& input, common::ku_string_t& result, - common::ValueVector& resultValueVector) { +void Reverse::operation(ku_string_t& input, ku_string_t& result, ValueVector& resultValueVector) { bool isAscii = true; std::string inputStr = input.getAsString(); for (uint32_t i = 0; i < input.len; i++) { @@ -103,28 +78,26 @@ void Reverse::operation(common::ku_string_t& input, common::ku_string_t& result, BaseStrOperation::operation(input, result, resultValueVector, reverseStr); } else { result.len = input.len; - if (result.len > common::ku_string_t::SHORT_STR_LENGTH) { - result.overflowPtr = reinterpret_cast( - common::StringVector::getInMemOverflowBuffer(&resultValueVector) - ->allocateSpace(input.len)); + if (result.len > ku_string_t::SHORT_STR_LENGTH) { + StringVector::reserveString(&resultValueVector, result, input.len); } - auto resultBuffer = result.len <= common::ku_string_t::SHORT_STR_LENGTH ? + auto resultBuffer = result.len <= ku_string_t::SHORT_STR_LENGTH ? reinterpret_cast(result.prefix) : reinterpret_cast(result.overflowPtr); - utf8proc::utf8proc_grapheme_callback( - inputStr.c_str(), input.len, [&](size_t start, size_t end) { + utf8proc::utf8proc_grapheme_callback(inputStr.c_str(), input.len, + [&](size_t start, size_t end) { memcpy(resultBuffer + input.len - end, input.getData() + start, end - start); return true; }); - if (result.len > common::ku_string_t::SHORT_STR_LENGTH) { - memcpy(result.prefix, resultBuffer, common::ku_string_t::PREFIX_LENGTH); + if (result.len > ku_string_t::SHORT_STR_LENGTH) { + memcpy(result.prefix, resultBuffer, ku_string_t::PREFIX_LENGTH); } } } function_set ArrayExtractFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(ARRAY_EXTRACT_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::BinaryExecFunction, @@ -132,19 +105,51 @@ function_set ArrayExtractFunction::getFunctionSet() { return functionSet; } +void ConcatFunction::execFunc(const std::vector>& parameters, + ValueVector& result, void* /*dataPtr*/) { + result.resetAuxiliaryBuffer(); + for (auto selectedPos = 0u; selectedPos < result.state->selVector->selectedSize; + ++selectedPos) { + auto pos = result.state->selVector->selectedPositions[selectedPos]; + auto strLen = 0u; + for (auto i = 0u; i < parameters.size(); i++) { + const auto& parameter = parameters[i]; + auto paramPos = parameter->state->isFlat() ? + parameter->state->selVector->selectedPositions[0] : + pos; + strLen += parameter->getValue(paramPos).len; + } + auto& resultStr = result.getValue(pos); + StringVector::reserveString(&result, resultStr, strLen); + auto dstData = strLen <= ku_string_t::SHORT_STR_LENGTH ? + resultStr.prefix : + reinterpret_cast(resultStr.overflowPtr); + for (auto i = 0u; i < parameters.size(); i++) { + const auto& parameter = parameters[i]; + auto paramPos = parameter->state->isFlat() ? + parameter->state->selVector->selectedPositions[0] : + pos; + auto srcStr = parameter->getValue(paramPos); + memcpy(dstData, srcStr.getData(), srcStr.len); + dstData += srcStr.len; + } + if (strLen > ku_string_t::SHORT_STR_LENGTH) { + memcpy(resultStr.prefix, resultStr.getData(), ku_string_t::PREFIX_LENGTH); + } + } +} + function_set ConcatFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(CONCAT_FUNC_NAME, - std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, - LogicalTypeID::STRING, - ScalarFunction::BinaryStringExecFunction, - false /* isVarLength */)); + functionSet.emplace_back( + make_unique(name, std::vector{LogicalTypeID::STRING}, + LogicalTypeID::STRING, execFunc, true /* isVarLength */)); return functionSet; } function_set ContainsFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(CONTAINS_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::BOOL, ScalarFunction::BinaryExecFunction, @@ -155,7 +160,7 @@ function_set ContainsFunction::getFunctionSet() { function_set EndsWithFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(ENDS_WITH_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::BOOL, ScalarFunction::BinaryExecFunction, @@ -166,7 +171,7 @@ function_set EndsWithFunction::getFunctionSet() { function_set LeftFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(LEFT_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::BinaryStringExecFunction, @@ -176,9 +181,9 @@ function_set LeftFunction::getFunctionSet() { function_set LpadFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(LPAD_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::INT64, LogicalTypeID::STRING}, + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64, + LogicalTypeID::STRING}, LogicalTypeID::STRING, ScalarFunction::TernaryStringExecFunction, @@ -188,7 +193,7 @@ function_set LpadFunction::getFunctionSet() { function_set RepeatFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(REPEAT_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::BinaryStringExecFunction, @@ -198,7 +203,7 @@ function_set RepeatFunction::getFunctionSet() { function_set RightFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(RIGHT_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::BinaryStringExecFunction, @@ -208,9 +213,9 @@ function_set RightFunction::getFunctionSet() { function_set RpadFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(RPAD_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::INT64, LogicalTypeID::STRING}, + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64, + LogicalTypeID::STRING}, LogicalTypeID::STRING, ScalarFunction::TernaryStringExecFunction, @@ -220,7 +225,7 @@ function_set RpadFunction::getFunctionSet() { function_set StartsWithFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(STARTS_WITH_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::BOOL, ScalarFunction::BinaryExecFunction, @@ -231,9 +236,9 @@ function_set StartsWithFunction::getFunctionSet() { function_set SubStrFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(SUBSTRING_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::INT64, LogicalTypeID::INT64}, + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::INT64, + LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::TernaryStringExecFunction, @@ -243,7 +248,7 @@ function_set SubStrFunction::getFunctionSet() { function_set RegexpFullMatchFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(REGEXP_FULL_MATCH_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::BOOL, ScalarFunction::BinaryExecFunction, @@ -254,7 +259,7 @@ function_set RegexpFullMatchFunction::getFunctionSet() { function_set RegexpMatchesFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(REGEXP_MATCHES_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::BOOL, ScalarFunction::BinaryExecFunction, @@ -267,9 +272,9 @@ function_set RegexpReplaceFunction::getFunctionSet() { function_set functionSet; // Todo: Implement a function with modifiers // regexp_replace(string, regex, replacement, modifiers) - functionSet.emplace_back(make_unique(REGEXP_REPLACE_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::STRING, LogicalTypeID::STRING}, + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING, + LogicalTypeID::STRING}, LogicalTypeID::STRING, ScalarFunction::TernaryStringExecFunction, @@ -279,15 +284,15 @@ function_set RegexpReplaceFunction::getFunctionSet() { function_set RegexpExtractFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(REGEXP_EXTRACT_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::STRING, ScalarFunction::BinaryStringExecFunction, false /* isVarLength */)); - functionSet.emplace_back(make_unique(REGEXP_EXTRACT_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::STRING, LogicalTypeID::INT64}, + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING, + LogicalTypeID::INT64}, LogicalTypeID::STRING, ScalarFunction::TernaryStringExecFunction, @@ -297,16 +302,16 @@ function_set RegexpExtractFunction::getFunctionSet() { function_set RegexpExtractAllFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(REGEXP_EXTRACT_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, - LogicalTypeID::VAR_LIST, + LogicalTypeID::LIST, ScalarFunction::BinaryStringExecFunction, nullptr, bindFunc, false /* isVarLength */)); - functionSet.emplace_back(make_unique(REGEXP_EXTRACT_FUNC_NAME, - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::STRING, LogicalTypeID::INT64}, - LogicalTypeID::VAR_LIST, + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING, + LogicalTypeID::INT64}, + LogicalTypeID::LIST, ScalarFunction::TernaryStringExecFunction, nullptr, bindFunc, false /* isVarLength */)); @@ -315,12 +320,12 @@ function_set RegexpExtractAllFunction::getFunctionSet() { std::unique_ptr RegexpExtractAllFunction::bindFunc( const binder::expression_vector& /*arguments*/, Function* /*definition*/) { - return std::make_unique(LogicalType::VAR_LIST(LogicalType::STRING())); + return std::make_unique(LogicalType::LIST(LogicalType::STRING())); } function_set LevenshteinFunction::getFunctionSet() { function_set functionSet; - functionSet.emplace_back(make_unique(LEVENSHTEIN_FUNC_NAME, + functionSet.emplace_back(make_unique(name, std::vector{LogicalTypeID::STRING, LogicalTypeID::STRING}, LogicalTypeID::INT64, ScalarFunction::BinaryExecFunction, nullptr, @@ -328,5 +333,14 @@ function_set LevenshteinFunction::getFunctionSet() { return functionSet; } +function_set InitcapFunction::getFunctionSet() { + function_set functionSet; + functionSet.emplace_back(make_unique(name, + std::vector{LogicalTypeID::STRING}, LogicalTypeID::STRING, + ScalarFunction::UnaryStringExecFunction, nullptr, + nullptr, false /* isVarLength */)); + return functionSet; +} + } // namespace function } // namespace kuzu diff --git a/src/function/vector_struct_functions.cpp b/src/function/vector_struct_functions.cpp index dde88007805..0bb000f26a0 100644 --- a/src/function/vector_struct_functions.cpp +++ b/src/function/vector_struct_functions.cpp @@ -4,28 +4,19 @@ #include "binder/expression_binder.h" #include "common/exception/binder.h" #include "common/string_format.h" -#include "function/function.h" +#include "function/scalar_function.h" using namespace kuzu::common; namespace kuzu { namespace function { -function_set StructPackFunctions::getFunctionSet() { - function_set functions; - functions.push_back(make_unique(STRUCT_PACK_FUNC_NAME, - std::vector{LogicalTypeID::ANY}, LogicalTypeID::STRUCT, execFunc, nullptr, - compileFunc, bindFunc, true /* isVarLength */)); - return functions; -} - -std::unique_ptr StructPackFunctions::bindFunc( +static std::unique_ptr StructPackBindFunc( const binder::expression_vector& arguments, Function* /*function*/) { std::vector fields; for (auto& argument : arguments) { if (argument->getDataType().getLogicalTypeID() == LogicalTypeID::ANY) { - binder::ExpressionBinder::resolveAnyDataType( - *argument, LogicalType{LogicalTypeID::STRING}); + argument->cast(*LogicalType::STRING()); } fields.emplace_back(argument->getAlias(), argument->getDataType().copy()); } @@ -33,20 +24,6 @@ std::unique_ptr StructPackFunctions::bindFunc( return std::make_unique(std::move(resultType)); } -void StructPackFunctions::execFunc(const std::vector>& parameters, - ValueVector& result, void* /*dataPtr*/) { - for (auto i = 0u; i < parameters.size(); i++) { - auto& parameter = parameters[i]; - if (parameter->state == result.state) { - continue; - } - // If the parameter's state is inconsistent with the result's state, we need to copy the - // parameter's value to the corresponding child vector. - copyParameterValueToStructFieldVector( - parameter.get(), StructVector::getFieldVector(&result, i).get(), result.state.get()); - } -} - void StructPackFunctions::compileFunc(FunctionBindData* /*bindData*/, const std::vector>& parameters, std::shared_ptr& result) { @@ -61,8 +38,8 @@ void StructPackFunctions::compileFunc(FunctionBindData* /*bindData*/, } } -void StructPackFunctions::copyParameterValueToStructFieldVector( - const ValueVector* parameter, ValueVector* structField, DataChunkState* structVectorState) { +static void copyParameterValueToStructFieldVector(const ValueVector* parameter, + ValueVector* structField, DataChunkState* structVectorState) { // If the parameter is unFlat, then its state must be consistent with the result's state. // Thus, we don't need to copy values to structFieldVector. KU_ASSERT(parameter->state->isFlat()); @@ -78,15 +55,25 @@ void StructPackFunctions::copyParameterValueToStructFieldVector( } } -function_set StructExtractFunctions::getFunctionSet() { - function_set functions; - auto inputTypeIDs = - std::vector{LogicalTypeID::STRUCT, LogicalTypeID::NODE, LogicalTypeID::REL}; - for (auto inputTypeID : inputTypeIDs) { - functions.push_back(make_unique(STRUCT_EXTRACT_FUNC_NAME, - std::vector{inputTypeID, LogicalTypeID::STRING}, LogicalTypeID::ANY, - nullptr, nullptr, compileFunc, bindFunc, false /* isVarLength */)); +void StructPackFunctions::execFunc(const std::vector>& parameters, + ValueVector& result, void* /*dataPtr*/) { + for (auto i = 0u; i < parameters.size(); i++) { + auto& parameter = parameters[i]; + if (parameter->state == result.state) { + continue; + } + // If the parameter's state is inconsistent with the result's state, we need to copy the + // parameter's value to the corresponding child vector. + copyParameterValueToStructFieldVector(parameter.get(), + StructVector::getFieldVector(&result, i).get(), result.state.get()); } +} + +function_set StructPackFunctions::getFunctionSet() { + function_set functions; + functions.push_back(make_unique(name, + std::vector{LogicalTypeID::ANY}, LogicalTypeID::STRUCT, execFunc, nullptr, + compileFunc, StructPackBindFunc, true /* isVarLength */)); return functions; } @@ -114,5 +101,22 @@ void StructExtractFunctions::compileFunc(FunctionBindData* bindData, result->state = parameters[0]->state; } +static std::unique_ptr getStructExtractFunction(LogicalTypeID logicalTypeID) { + return std::make_unique(StructExtractFunctions::name, + std::vector{logicalTypeID, LogicalTypeID::STRING}, LogicalTypeID::ANY, + nullptr, nullptr, StructExtractFunctions::compileFunc, StructExtractFunctions::bindFunc, + false /* isVarLength */); +} + +function_set StructExtractFunctions::getFunctionSet() { + function_set functions; + auto inputTypeIDs = + std::vector{LogicalTypeID::STRUCT, LogicalTypeID::NODE, LogicalTypeID::REL}; + for (auto inputTypeID : inputTypeIDs) { + functions.push_back(getStructExtractFunction(inputTypeID)); + } + return functions; +} + } // namespace function } // namespace kuzu diff --git a/src/function/vector_timestamp_functions.cpp b/src/function/vector_timestamp_functions.cpp index 5f160ca8a60..5a135aa28cf 100644 --- a/src/function/vector_timestamp_functions.cpp +++ b/src/function/vector_timestamp_functions.cpp @@ -1,5 +1,6 @@ #include "function/timestamp/vector_timestamp_functions.h" +#include "function/scalar_function.h" #include "function/timestamp/timestamp_function.h" using namespace kuzu::common; @@ -9,7 +10,7 @@ namespace function { function_set CenturyFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(CENTURY_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::TIMESTAMP}, LogicalTypeID::INT64, ScalarFunction::UnaryExecFunction)); return result; @@ -17,7 +18,7 @@ function_set CenturyFunction::getFunctionSet() { function_set EpochMsFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(EPOCH_MS_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::INT64}, LogicalTypeID::TIMESTAMP, ScalarFunction::UnaryExecFunction)); return result; @@ -25,7 +26,7 @@ function_set EpochMsFunction::getFunctionSet() { function_set ToTimestampFunction::getFunctionSet() { function_set result; - result.push_back(make_unique(TO_TIMESTAMP_FUNC_NAME, + result.push_back(make_unique(name, std::vector{LogicalTypeID::DOUBLE}, LogicalTypeID::TIMESTAMP, ScalarFunction::UnaryExecFunction)); return result; diff --git a/src/function/vector_union_functions.cpp b/src/function/vector_union_functions.cpp index 33c720209c2..72f202e2c4f 100644 --- a/src/function/vector_union_functions.cpp +++ b/src/function/vector_union_functions.cpp @@ -1,6 +1,6 @@ #include "function/union/vector_union_functions.h" -#include "binder/expression_binder.h" +#include "function/scalar_function.h" #include "function/struct/vector_struct_functions.h" #include "function/union/functions/union_tag.h" @@ -9,36 +9,27 @@ using namespace kuzu::common; namespace kuzu { namespace function { -function_set UnionValueFunction::getFunctionSet() { - function_set functionSet; - functionSet.push_back(make_unique(UNION_VALUE_FUNC_NAME, - std::vector{LogicalTypeID::ANY}, LogicalTypeID::UNION, execFunc, nullptr, - compileFunc, bindFunc, false /* isVarLength */)); - return functionSet; -} - -std::unique_ptr UnionValueFunction::bindFunc( +static std::unique_ptr UnionValueBindFunc( const binder::expression_vector& arguments, kuzu::function::Function* /*function*/) { KU_ASSERT(arguments.size() == 1); std::vector fields; // TODO(Ziy): Use UINT8 to represent tag value. - fields.emplace_back( - UnionType::TAG_FIELD_NAME, std::make_unique(UnionType::TAG_FIELD_TYPE)); + fields.emplace_back(UnionType::TAG_FIELD_NAME, + std::make_unique(UnionType::TAG_FIELD_TYPE)); if (arguments[0]->getDataType().getLogicalTypeID() == common::LogicalTypeID::ANY) { - binder::ExpressionBinder::resolveAnyDataType( - *arguments[0], LogicalType(LogicalTypeID::STRING)); + arguments[0]->cast(*LogicalType::STRING()); } fields.emplace_back(arguments[0]->getAlias(), arguments[0]->getDataType().copy()); auto resultType = LogicalType::UNION(std::move(fields)); return std::make_unique(std::move(resultType)); } -void UnionValueFunction::execFunc(const std::vector>& /*parameters*/, +static void UnionValueExecFunc(const std::vector>& /*parameters*/, ValueVector& result, void* /*dataPtr*/) { UnionVector::setTagField(&result, UnionType::TAG_FIELD_IDX); } -void UnionValueFunction::compileFunc(FunctionBindData* /*bindData*/, +static void UnionValueCompileFunc(FunctionBindData* /*bindData*/, const std::vector>& parameters, std::shared_ptr& result) { KU_ASSERT(parameters.size() == 1); @@ -47,9 +38,17 @@ void UnionValueFunction::compileFunc(FunctionBindData* /*bindData*/, UnionVector::referenceVector(result.get(), UnionType::TAG_FIELD_IDX, parameters[0]); } +function_set UnionValueFunction::getFunctionSet() { + function_set functionSet; + functionSet.push_back(make_unique(name, + std::vector{LogicalTypeID::ANY}, LogicalTypeID::UNION, UnionValueExecFunc, + nullptr, UnionValueCompileFunc, UnionValueBindFunc, false /* isVarLength */)); + return functionSet; +} + function_set UnionTagFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(make_unique(UNION_TAG_FUNC_NAME, + functionSet.push_back(make_unique(name, std::vector{LogicalTypeID::UNION}, LogicalTypeID::STRING, ScalarFunction::UnaryExecNestedTypeFunction, nullptr, nullptr, false /* isVarLength */)); @@ -58,7 +57,7 @@ function_set UnionTagFunction::getFunctionSet() { function_set UnionExtractFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(make_unique(UNION_EXTRACT_FUNC_NAME, + functionSet.push_back(make_unique(name, std::vector{LogicalTypeID::UNION, LogicalTypeID::STRING}, LogicalTypeID::ANY, nullptr, nullptr, StructExtractFunctions::compileFunc, StructExtractFunctions::bindFunc, false /* isVarLength */)); diff --git a/src/function/vector_uuid_functions.cpp b/src/function/vector_uuid_functions.cpp index b8f6cc2ef88..e4bb0a22cbc 100644 --- a/src/function/vector_uuid_functions.cpp +++ b/src/function/vector_uuid_functions.cpp @@ -1,5 +1,6 @@ #include "function/uuid/vector_uuid_functions.h" +#include "function/scalar_function.h" #include "function/uuid/functions/gen_random_uuid.h" using namespace kuzu::common; @@ -9,9 +10,8 @@ namespace function { function_set GenRandomUUIDFunction::getFunctionSet() { function_set definitions; - definitions.push_back( - make_unique(GEN_RANDOM_UUID_FUNC_NAME, std::vector{}, - LogicalTypeID::UUID, ScalarFunction::PoniterExecFunction)); + definitions.push_back(make_unique(name, std::vector{}, + LogicalTypeID::UUID, ScalarFunction::PoniterExecFunction)); return definitions; } diff --git a/src/include/binder/binder.h b/src/include/binder/binder.h index 47205bf5525..4e8c6ab7f52 100644 --- a/src/include/binder/binder.h +++ b/src/include/binder/binder.h @@ -1,22 +1,30 @@ #pragma once +#include "binder/binder_scope.h" +#include "binder/expression_binder.h" #include "binder/query/bound_regular_query.h" #include "binder/query/query_graph.h" -#include "catalog/catalog.h" #include "common/copier_config/reader_config.h" -#include "expression_binder.h" +#include "common/enums/table_type.h" #include "parser/query/graph_pattern/pattern_element.h" #include "parser/query/regular_query.h" -#include "storage/storage_manager.h" namespace kuzu { namespace parser { struct CreateTableInfo; -} +struct BaseScanSource; +} // namespace parser + +namespace catalog { +class NodeTableCatalogEntry; +class RelTableCatalogEntry; +class RDFGraphCatalogEntry; +class Property; +} // namespace catalog namespace extension { struct ExtensionOptions; -} +} // namespace extension namespace main { class ClientContext; @@ -25,10 +33,12 @@ class Database; namespace function { struct TableFunction; -} +} // namespace function namespace binder { - +struct PropertyInfo; +struct BoundBaseScanSource; +struct BoundCreateTableInfo; struct BoundInsertInfo; struct BoundSetPropertyInfo; struct BoundDeleteInfo; @@ -39,56 +49,22 @@ struct ExportedTableData; // BinderScope keeps track of expressions in scope and their aliases. We maintain the order of // expressions in -class BinderScope { -public: - BinderScope() = default; - BinderScope(expression_vector expressions, - std::unordered_map varNameToIdx) - : expressions{std::move(expressions)}, varNameToIdx{std::move(varNameToIdx)} {} - - inline bool empty() const { return expressions.empty(); } - inline bool contains(const std::string& varName) const { - return varNameToIdx.contains(varName); - } - inline std::shared_ptr getExpression(const std::string& varName) const { - return expressions[varNameToIdx.at(varName)]; - } - inline expression_vector getExpressions() const { return expressions; } - inline void addExpression(const std::string& varName, std::shared_ptr expression) { - varNameToIdx.insert({varName, expressions.size()}); - expressions.push_back(std::move(expression)); - } - inline void removeExpression(const std::string& name) { - auto idx = varNameToIdx.at(name); - varNameToIdx.erase(name); - expressions[idx] = nullptr; - } - inline void clear() { - expressions.clear(); - varNameToIdx.clear(); - } - inline std::unique_ptr copy() { - return std::make_unique(expressions, varNameToIdx); - } - -private: - expression_vector expressions; - std::unordered_map varNameToIdx; -}; class Binder { friend class ExpressionBinder; public: - explicit Binder(const catalog::Catalog& catalog, storage::MemoryManager* memoryManager, - storage::StorageManager* storageManager, common::VirtualFileSystem* vfs, - main::ClientContext* clientContext, extension::ExtensionOptions* extensionOptions) - : catalog{catalog}, memoryManager{memoryManager}, storageManager{storageManager}, vfs{vfs}, - lastExpressionId{0}, scope{std::make_unique()}, expressionBinder{this}, - clientContext{clientContext}, extensionOptions{extensionOptions} {} + explicit Binder(main::ClientContext* clientContext) + : lastExpressionId{0}, scope{}, expressionBinder{this, clientContext}, + clientContext{clientContext} {} std::unique_ptr bind(const parser::Statement& statement); + void setInputParameters( + std::unordered_map> parameters) { + expressionBinder.parameterMap = parameters; + } + inline std::unordered_map> getParameterMap() { return expressionBinder.parameterMap; } @@ -104,10 +80,10 @@ class Binder { common::table_id_t bindTableID(const std::string& tableName) const; std::shared_ptr createVariable(std::string_view name, common::LogicalTypeID typeID); - std::shared_ptr createVariable( - const std::string& name, common::LogicalTypeID typeID); - std::shared_ptr createVariable( - const std::string& name, const common::LogicalType& dataType); + std::shared_ptr createVariable(const std::string& name, + common::LogicalTypeID typeID); + std::shared_ptr createVariable(const std::string& name, + const common::LogicalType& dataType); /*** bind DDL ***/ BoundCreateTableInfo bindCreateTableInfo(const parser::CreateTableInfo* info); @@ -130,25 +106,25 @@ class Binder { /*** bind copy ***/ std::unique_ptr bindCopyFromClause(const parser::Statement& statement); std::unique_ptr bindCopyNodeFrom(const parser::Statement& statement, - std::unique_ptr config, catalog::NodeTableCatalogEntry* nodeTableEntry); std::unique_ptr bindCopyRelFrom(const parser::Statement& statement, - std::unique_ptr config, catalog::RelTableCatalogEntry* relTableEntry); + catalog::RelTableCatalogEntry* relTableEntry); std::unique_ptr bindCopyRdfFrom(const parser::Statement& statement, - std::unique_ptr config, catalog::RDFGraphCatalogEntry* rdfGraphEntry); - void bindExpectedNodeColumns(catalog::NodeTableCatalogEntry* nodeTableEntry, - const std::vector& inputColumnNames, std::vector& columnNames, - std::vector& columnTypes); - void bindExpectedRelColumns(catalog::RelTableCatalogEntry* relTableEntry, - const std::vector& inputColumnNames, std::vector& columnNames, - std::vector& columnTypes); + catalog::RDFGraphCatalogEntry* rdfGraphEntry); std::unique_ptr bindCopyToClause(const parser::Statement& statement); std::unique_ptr bindExportDatabaseClause(const parser::Statement& statement); std::unique_ptr bindImportDatabaseClause(const parser::Statement& statement); - /*** bind file scan ***/ + std::unique_ptr bindAttachDatabase(const parser::Statement& statement); + std::unique_ptr bindDetachDatabase(const parser::Statement& statement); + + /*** bind scan source ***/ + std::unique_ptr bindScanSource(parser::BaseScanSource* scanSource, + const parser::parsing_option_t& options, const std::vector& columnNames, + const std::vector& columnTypes); + std::unordered_map bindParsingOptions( const parser::parsing_option_t& parsingOptions); common::FileType bindFileType(const std::vector& filePaths); @@ -200,16 +176,16 @@ class Binder { std::unique_ptr bindDeleteClause( const parser::UpdatingClause& updatingClause); - std::vector bindInsertInfos( - const QueryGraphCollection& queryGraphCollection, const expression_set& nodeRelScope_); + std::vector bindInsertInfos(const QueryGraphCollection& queryGraphCollection, + const std::unordered_set& patternsInScope); void bindInsertNode(std::shared_ptr node, std::vector& infos); void bindInsertRel(std::shared_ptr rel, std::vector& infos); expression_vector bindInsertColumnDataExprs( const std::unordered_map>& propertyRhsExpr, const std::vector& properties); - BoundSetPropertyInfo bindSetPropertyInfo( - parser::ParsedExpression* lhs, parser::ParsedExpression* rhs); + BoundSetPropertyInfo bindSetPropertyInfo(parser::ParsedExpression* lhs, + parser::ParsedExpression* rhs); expression_pair bindSetItem(parser::ParsedExpression* lhs, parser::ParsedExpression* rhs); /*** bind projection clause ***/ @@ -226,14 +202,13 @@ class Binder { uint64_t bindSkipLimitExpression(const parser::ParsedExpression& expression); void addExpressionsToScope(const expression_vector& projectionExpressions); - void resolveAnyDataTypeWithDefaultType(const expression_vector& expressions); /*** bind graph pattern ***/ BoundGraphPattern bindGraphPattern(const std::vector& graphPattern); QueryGraph bindPatternElement(const parser::PatternElement& patternElement); - std::shared_ptr createPath( - const std::string& pathName, const expression_vector& children); + std::shared_ptr createPath(const std::string& pathName, + const expression_vector& children); std::shared_ptr bindQueryRel(const parser::RelPattern& relPattern, const std::shared_ptr& leftNode, @@ -247,18 +222,18 @@ class Binder { std::pair bindVariableLengthRelBound(const parser::RelPattern& relPattern); void bindQueryRelProperties(RelExpression& rel); - std::shared_ptr bindQueryNode( - const parser::NodePattern& nodePattern, QueryGraph& queryGraph); + std::shared_ptr bindQueryNode(const parser::NodePattern& nodePattern, + QueryGraph& queryGraph); std::shared_ptr createQueryNode(const parser::NodePattern& nodePattern); - std::shared_ptr createQueryNode( - const std::string& parsedName, const std::vector& tableIDs); + std::shared_ptr createQueryNode(const std::string& parsedName, + const std::vector& tableIDs); void bindQueryNodeProperties(NodeExpression& node); /*** bind table ID ***/ // Bind table names to catalog table schemas. The function does NOT validate if the table schema // type matches node or rel pattern. - std::vector bindTableIDs( - const std::vector& tableNames, bool nodePattern); + std::vector bindTableIDs(const std::vector& tableNames, + bool nodePattern); std::vector getNodeTableIDs( const std::vector& tableIDs); std::vector getNodeTableIDs(common::table_id_t tableID); @@ -276,10 +251,6 @@ class Binder { static void validateOrderByFollowedBySkipOrLimitInWithClause( const BoundProjectionBody& boundProjectionBody); - // We don't support read after write for simplicity. User should instead querying through - // multiple statement. - static void validateReadNotFollowUpdate(const NormalizedSingleQuery& singleQuery); - void validateTableType(common::table_id_t tableID, common::TableType expectedTableType); void validateTableExist(const std::string& tableName); @@ -287,22 +258,17 @@ class Binder { std::string getUniqueExpressionName(const std::string& name); static bool isReservedPropertyName(const std::string& name); - std::unique_ptr saveScope(); - void restoreScope(std::unique_ptr prevVariableScope); + BinderScope saveScope(); + void restoreScope(BinderScope prevScope); - function::TableFunction* getScanFunction( - common::FileType fileType, const common::ReaderConfig& config); + function::TableFunction getScanFunction(common::FileType fileType, + const common::ReaderConfig& config); private: - const catalog::Catalog& catalog; - storage::MemoryManager* memoryManager; - storage::StorageManager* storageManager; - common::VirtualFileSystem* vfs; uint32_t lastExpressionId; - std::unique_ptr scope; + BinderScope scope; ExpressionBinder expressionBinder; main::ClientContext* clientContext; - extension::ExtensionOptions* extensionOptions; }; } // namespace binder diff --git a/src/include/binder/binder_scope.h b/src/include/binder/binder_scope.h new file mode 100644 index 00000000000..fea0e02c408 --- /dev/null +++ b/src/include/binder/binder_scope.h @@ -0,0 +1,66 @@ +#pragma once + +#include "binder/expression/expression.h" +#include "binder/expression/node_expression.h" + +namespace kuzu { +namespace binder { + +class BinderScope { +public: + BinderScope() = default; + EXPLICIT_COPY_DEFAULT_MOVE(BinderScope); + + bool empty() const { return expressions.empty(); } + bool contains(const std::string& varName) const { return nameToExprIdx.contains(varName); } + std::shared_ptr getExpression(const std::string& varName) const { + KU_ASSERT(nameToExprIdx.contains(varName)); + return expressions[nameToExprIdx.at(varName)]; + } + expression_vector getExpressions() const { return expressions; } + void addExpression(const std::string& varName, std::shared_ptr expression); + + void memorizeTableIDs(const std::string& name, std::vector tableIDs) { + memorizedNodeNameToTableIDs.insert({name, tableIDs}); + } + bool hasMemorizedTableIDs(const std::string& name) const { + return memorizedNodeNameToTableIDs.contains(name); + } + std::vector getMemorizedTableIDs(const std::string& name) { + KU_ASSERT(memorizedNodeNameToTableIDs.contains(name)); + return memorizedNodeNameToTableIDs.at(name); + } + + void addNodeReplacement(std::shared_ptr node) { + nodeReplacement.insert({node->getVariableName(), node}); + } + bool hasNodeReplacement(const std::string& name) const { + return nodeReplacement.contains(name); + } + std::shared_ptr getNodeReplacement(const std::string& name) const { + KU_ASSERT(hasNodeReplacement(name)); + return nodeReplacement.at(name); + } + + void clear(); + +private: + BinderScope(const BinderScope& other) + : expressions{other.expressions}, nameToExprIdx{other.nameToExprIdx}, + memorizedNodeNameToTableIDs{other.memorizedNodeNameToTableIDs} {} + +private: + // Expressions in scope. Order should be preserved. + expression_vector expressions; + std::unordered_map nameToExprIdx; + // A node might be popped out of scope. But we may need to retain its table ID information. + // E.g. MATCH (a:person) WITH collect(a) AS list_a UNWIND list_a AS new_a MATCH (new_a)-[]->() + // It will be more performant if we can retain the information that new_a has label person. + std::unordered_map> memorizedNodeNameToTableIDs; + // A node pattern may not always be bound as a node expression, e.g. in the above query, + // (new_a) is bound as a variable rather than node expression. + std::unordered_map> nodeReplacement; +}; + +} // namespace binder +} // namespace kuzu diff --git a/src/include/binder/bound_attach_database.h b/src/include/binder/bound_attach_database.h new file mode 100644 index 00000000000..1d36954d7b3 --- /dev/null +++ b/src/include/binder/bound_attach_database.h @@ -0,0 +1,23 @@ +#pragma once + +#include "binder/bound_statement.h" +#include "parser/parsed_data/attach_info.h" + +namespace kuzu { +namespace binder { + +class BoundAttachDatabase final : public BoundStatement { +public: + explicit BoundAttachDatabase(parser::AttachInfo attachInfo) + : BoundStatement{common::StatementType::ATTACH_DATABASE, + BoundStatementResult::createEmptyResult()}, + attachInfo{std::move(attachInfo)} {} + + parser::AttachInfo getAttachInfo() const { return attachInfo; } + +private: + parser::AttachInfo attachInfo; +}; + +} // namespace binder +} // namespace kuzu diff --git a/src/include/binder/bound_create_macro.h b/src/include/binder/bound_create_macro.h index 3e6bedd63c3..2acd3d1a684 100644 --- a/src/include/binder/bound_create_macro.h +++ b/src/include/binder/bound_create_macro.h @@ -8,8 +8,8 @@ namespace binder { class BoundCreateMacro : public BoundStatement { public: - explicit BoundCreateMacro( - std::string macroName, std::unique_ptr macro) + explicit BoundCreateMacro(std::string macroName, + std::unique_ptr macro) : BoundStatement{common::StatementType::CREATE_MACRO, BoundStatementResult::createSingleStringColumnResult("result" /* columnName */)}, macroName{std::move(macroName)}, macro{std::move(macro)} {} diff --git a/src/include/binder/bound_detach_database.h b/src/include/binder/bound_detach_database.h new file mode 100644 index 00000000000..a99f88372bc --- /dev/null +++ b/src/include/binder/bound_detach_database.h @@ -0,0 +1,22 @@ +#pragma once + +#include "binder/bound_statement.h" + +namespace kuzu { +namespace binder { + +class BoundDetachDatabase final : public BoundStatement { +public: + explicit BoundDetachDatabase(std::string dbName) + : BoundStatement{common::StatementType::DETACH_DATABASE, + BoundStatementResult::createEmptyResult()}, + dbName{std::move(dbName)} {} + + std::string getDBName() const { return dbName; } + +private: + std::string dbName; +}; + +} // namespace binder +} // namespace kuzu diff --git a/src/include/binder/bound_explain.h b/src/include/binder/bound_explain.h index fa0d78c2535..0db6ab5dffd 100644 --- a/src/include/binder/bound_explain.h +++ b/src/include/binder/bound_explain.h @@ -8,8 +8,8 @@ namespace binder { class BoundExplain : public BoundStatement { public: - explicit BoundExplain( - std::unique_ptr statementToExplain, common::ExplainType explainType) + explicit BoundExplain(std::unique_ptr statementToExplain, + common::ExplainType explainType) : BoundStatement{common::StatementType::EXPLAIN, BoundStatementResult::createSingleStringColumnResult( "explain result" /* columnName */)}, diff --git a/src/include/binder/bound_scan_source.h b/src/include/binder/bound_scan_source.h new file mode 100644 index 00000000000..d94a9d90bbd --- /dev/null +++ b/src/include/binder/bound_scan_source.h @@ -0,0 +1,71 @@ +#pragma once + +#include "binder/bound_statement.h" +#include "binder/copy/bound_file_scan_info.h" +#include "common/enums/scan_source_type.h" + +namespace kuzu { +namespace binder { + +struct BoundBaseScanSource { + common::ScanSourceType type; + + explicit BoundBaseScanSource(common::ScanSourceType type) : type{type} {} + virtual ~BoundBaseScanSource() = default; + + virtual expression_vector getColumns() = 0; + + virtual std::unique_ptr copy() const = 0; + +protected: + BoundBaseScanSource(const BoundBaseScanSource& other) : type{other.type} {} +}; + +struct BoundEmptyScanSource : public BoundBaseScanSource { + BoundEmptyScanSource() : BoundBaseScanSource{common::ScanSourceType::EMPTY} {} + BoundEmptyScanSource(const BoundEmptyScanSource& other) : BoundBaseScanSource{other} {} + + expression_vector getColumns() override { return expression_vector{}; } + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } +}; + +struct BoundFileScanSource : public BoundBaseScanSource { + BoundFileScanInfo fileScanInfo; + + explicit BoundFileScanSource(BoundFileScanInfo fileScanInfo) + : BoundBaseScanSource{common::ScanSourceType::FILE}, fileScanInfo{std::move(fileScanInfo)} { + } + BoundFileScanSource(const BoundFileScanSource& other) + : BoundBaseScanSource{other}, fileScanInfo{other.fileScanInfo.copy()} {} + + expression_vector getColumns() override { return fileScanInfo.columns; } + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } +}; + +struct BoundQueryScanSource : public BoundBaseScanSource { + // Use shared ptr to avoid copy BoundStatement. + // We should consider implement a copy constructor though. + std::shared_ptr statement; + + explicit BoundQueryScanSource(std::shared_ptr statement) + : BoundBaseScanSource{common::ScanSourceType::QUERY}, statement{std::move(statement)} {} + BoundQueryScanSource(const BoundQueryScanSource& other) + : BoundBaseScanSource{other}, statement{other.statement} {} + + expression_vector getColumns() override { + return statement->getStatementResult()->getColumns(); + } + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } +}; + +} // namespace binder +} // namespace kuzu diff --git a/src/include/binder/bound_statement_rewriter.h b/src/include/binder/bound_statement_rewriter.h index cd95d91f58f..49ceb5e9daa 100644 --- a/src/include/binder/bound_statement_rewriter.h +++ b/src/include/binder/bound_statement_rewriter.h @@ -1,7 +1,7 @@ #pragma once #include "bound_statement.h" -#include "catalog/catalog.h" +#include "main/client_context.h" namespace kuzu { namespace binder { @@ -9,7 +9,7 @@ namespace binder { // Perform semantic rewrite over bound statement. class BoundStatementRewriter { public: - static void rewrite(BoundStatement& boundStatement, const catalog::Catalog& catalog); + static void rewrite(BoundStatement& boundStatement, const main::ClientContext& clientContext); }; } // namespace binder diff --git a/src/include/binder/bound_statement_visitor.h b/src/include/binder/bound_statement_visitor.h index 45a1652b193..efcd4318a33 100644 --- a/src/include/binder/bound_statement_visitor.h +++ b/src/include/binder/bound_statement_visitor.h @@ -20,8 +20,8 @@ class BoundStatementVisitor { virtual void visitCreateTable(const BoundStatement&) {} virtual void visitDropTable(const BoundStatement&) {} virtual void visitAlter(const BoundStatement&) {} - virtual void visitCopyFrom(const BoundStatement&) {} - virtual void visitCopyTo(const BoundStatement&) {} + virtual void visitCopyFrom(const BoundStatement&); + virtual void visitCopyTo(const BoundStatement&); virtual void visitExportDatabase(const BoundStatement&) {} virtual void visitImportDatabase(const BoundStatement&) {} virtual void visitStandaloneCall(const BoundStatement&) {} @@ -48,6 +48,8 @@ class BoundStatementVisitor { virtual void visitProjectionBody(const BoundProjectionBody& /* projectionBody*/) {} virtual void visitProjectionBodyPredicate(const std::shared_ptr& /* predicate*/) {} + virtual void visitAttachDatabase(const BoundStatement&) {} + virtual void visitDetachDatabase(const BoundStatement&) {} }; } // namespace binder diff --git a/src/include/binder/copy/bound_copy_from.h b/src/include/binder/copy/bound_copy_from.h index 9df2089bc7c..bbf79a3ae70 100644 --- a/src/include/binder/copy/bound_copy_from.h +++ b/src/include/binder/copy/bound_copy_from.h @@ -1,7 +1,6 @@ #pragma once -#include "binder/bound_statement.h" -#include "bound_file_scan_info.h" +#include "binder/bound_scan_source.h" #include "catalog/catalog_entry/table_catalog_entry.h" #include "index_look_up_info.h" @@ -14,24 +13,24 @@ struct ExtraBoundCopyFromInfo { }; struct BoundCopyFromInfo { + // Table entry to copy into. catalog::TableCatalogEntry* tableEntry; - std::unique_ptr fileScanInfo; - bool containsSerial; + // Data source + std::unique_ptr source; + // Row offset of input data to generate internal ID. + std::shared_ptr offset; std::unique_ptr extraInfo; BoundCopyFromInfo(catalog::TableCatalogEntry* tableEntry, - std::unique_ptr fileScanInfo, bool containsSerial, + std::unique_ptr source, std::shared_ptr offset, std::unique_ptr extraInfo) - : tableEntry{tableEntry}, fileScanInfo{std::move(fileScanInfo)}, - containsSerial{containsSerial}, extraInfo{std::move(extraInfo)} {} + : tableEntry{tableEntry}, source{std::move(source)}, offset{offset}, + extraInfo{std::move(extraInfo)} {} EXPLICIT_COPY_DEFAULT_MOVE(BoundCopyFromInfo); private: BoundCopyFromInfo(const BoundCopyFromInfo& other) - : tableEntry{other.tableEntry}, containsSerial{other.containsSerial} { - if (other.fileScanInfo) { - fileScanInfo = std::make_unique(other.fileScanInfo->copy()); - } + : tableEntry{other.tableEntry}, source{other.source->copy()}, offset{other.offset} { if (other.extraInfo) { extraInfo = other.extraInfo->copy(); } diff --git a/src/include/binder/copy/bound_copy_to.h b/src/include/binder/copy/bound_copy_to.h index c7dac956f1d..d306c8d05d7 100644 --- a/src/include/binder/copy/bound_copy_to.h +++ b/src/include/binder/copy/bound_copy_to.h @@ -1,6 +1,6 @@ #pragma once -#include "binder/query/bound_regular_query.h" +#include "binder/bound_statement.h" #include "common/copier_config/csv_reader_config.h" #include "common/copier_config/reader_config.h" @@ -10,27 +10,21 @@ namespace binder { class BoundCopyTo : public BoundStatement { public: BoundCopyTo(std::string filePath, common::FileType fileType, - std::vector columnNames, std::vector columnTypes, - std::unique_ptr regularQuery, common::CSVOption csvOption) + std::unique_ptr query, common::CSVOption csvOption) : BoundStatement{common::StatementType::COPY_TO, BoundStatementResult::createEmptyResult()}, - filePath{std::move(filePath)}, fileType{fileType}, columnNames{std::move(columnNames)}, - columnTypes{std::move(columnTypes)}, - regularQuery{std::move(regularQuery)}, csvOption{std::move(csvOption)} {} + filePath{std::move(filePath)}, fileType{fileType}, query{std::move(query)}, + csvOption{std::move(csvOption)} {} inline std::string getFilePath() const { return filePath; } inline common::FileType getFileType() const { return fileType; } - inline std::vector getColumnNames() const { return columnNames; } - inline const std::vector& getColumnTypesRef() const { return columnTypes; } - inline const BoundRegularQuery* getRegularQuery() const { return regularQuery.get(); } + inline const BoundStatement* getRegularQuery() const { return query.get(); } inline const common::CSVOption* getCopyOption() const { return &csvOption; } private: std::string filePath; common::FileType fileType; - std::vector columnNames; - std::vector columnTypes; - std::unique_ptr regularQuery; + std::unique_ptr query; common::CSVOption csvOption; }; diff --git a/src/include/binder/copy/bound_export_database.h b/src/include/binder/copy/bound_export_database.h index 06dfa4e4f9a..6336ca47aba 100644 --- a/src/include/binder/copy/bound_export_database.h +++ b/src/include/binder/copy/bound_export_database.h @@ -2,6 +2,7 @@ #include "binder/binder.h" #include "binder/bound_statement.h" #include "binder/query/bound_regular_query.h" +#include "common/copier_config/csv_reader_config.h" #include "common/copier_config/reader_config.h" namespace kuzu { @@ -17,7 +18,7 @@ struct ExportedTableData { inline const BoundRegularQuery* getRegularQuery() const { return regularQuery.get(); } }; -class BoundExportDatabase : public BoundStatement { +class BoundExportDatabase final : public BoundStatement { public: BoundExportDatabase(std::string filePath, common::FileType fileType, std::vector exportData, diff --git a/src/include/binder/copy/bound_file_scan_info.h b/src/include/binder/copy/bound_file_scan_info.h index a734fc28141..cc92eb48914 100644 --- a/src/include/binder/copy/bound_file_scan_info.h +++ b/src/include/binder/copy/bound_file_scan_info.h @@ -8,22 +8,18 @@ namespace kuzu { namespace binder { struct BoundFileScanInfo { - function::TableFunction* copyFunc; + function::TableFunction func; std::unique_ptr bindData; binder::expression_vector columns; - std::shared_ptr offset; - BoundFileScanInfo(function::TableFunction* copyFunc, - std::unique_ptr bindData, binder::expression_vector columns, - std::shared_ptr offset) - : copyFunc{copyFunc}, bindData{std::move(bindData)}, columns{std::move(columns)}, - offset{std::move(offset)} {} + BoundFileScanInfo(function::TableFunction func, + std::unique_ptr bindData, binder::expression_vector columns) + : func{func}, bindData{std::move(bindData)}, columns{std::move(columns)} {} EXPLICIT_COPY_DEFAULT_MOVE(BoundFileScanInfo); private: BoundFileScanInfo(const BoundFileScanInfo& other) - : copyFunc{other.copyFunc}, bindData{other.bindData->copy()}, columns{other.columns}, - offset{other.offset} {} + : func{other.func}, bindData{other.bindData->copy()}, columns{other.columns} {} }; } // namespace binder diff --git a/src/include/binder/copy/bound_import_database.h b/src/include/binder/copy/bound_import_database.h index d6ec80b1a25..7dadc43b781 100644 --- a/src/include/binder/copy/bound_import_database.h +++ b/src/include/binder/copy/bound_import_database.h @@ -4,7 +4,7 @@ namespace kuzu { namespace binder { -class BoundImportDatabase : public BoundStatement { +class BoundImportDatabase final : public BoundStatement { public: BoundImportDatabase(std::string filePath, std::string query) : BoundStatement{common::StatementType::IMPORT_DATABASE, diff --git a/src/include/binder/ddl/bound_alter_info.h b/src/include/binder/ddl/bound_alter_info.h index a6c7d6c965e..9fa5515af97 100644 --- a/src/include/binder/ddl/bound_alter_info.h +++ b/src/include/binder/ddl/bound_alter_info.h @@ -51,8 +51,8 @@ struct BoundExtraAddPropertyInfo : public BoundExtraAlterInfo { : propertyName{std::move(propertyName)}, dataType{std::move(dataType)}, defaultValue{std::move(defaultValue)} {} BoundExtraAddPropertyInfo(const BoundExtraAddPropertyInfo& other) - : propertyName{other.propertyName}, dataType{other.dataType}, defaultValue{ - other.defaultValue} {} + : propertyName{other.propertyName}, dataType{other.dataType}, + defaultValue{other.defaultValue} {} inline std::unique_ptr copy() const final { return std::make_unique(*this); diff --git a/src/include/binder/ddl/bound_create_table_info.h b/src/include/binder/ddl/bound_create_table_info.h index ea9d35f10ea..197d9f5faca 100644 --- a/src/include/binder/ddl/bound_create_table_info.h +++ b/src/include/binder/ddl/bound_create_table_info.h @@ -6,23 +6,23 @@ #include "common/types/types.h" namespace kuzu { -namespace catalog { +namespace common { enum class RelMultiplicity : uint8_t; } namespace binder { -struct BoundExtraCreateTableInfo { - virtual ~BoundExtraCreateTableInfo() = default; - virtual inline std::unique_ptr copy() const = 0; +struct BoundExtraCreateCatalogEntryInfo { + virtual ~BoundExtraCreateCatalogEntryInfo() = default; + virtual inline std::unique_ptr copy() const = 0; }; struct BoundCreateTableInfo { common::TableType type; std::string tableName; - std::unique_ptr extraInfo; + std::unique_ptr extraInfo; BoundCreateTableInfo(common::TableType type, std::string tableName, - std::unique_ptr extraInfo) + std::unique_ptr extraInfo) : type{type}, tableName{std::move(tableName)}, extraInfo{std::move(extraInfo)} {} EXPLICIT_COPY_DEFAULT_MOVE(BoundCreateTableInfo); @@ -43,44 +43,57 @@ struct PropertyInfo { PropertyInfo(const PropertyInfo& other) : name{other.name}, type{other.type} {} }; -struct BoundExtraCreateNodeTableInfo : public BoundExtraCreateTableInfo { - common::property_id_t primaryKeyIdx; +struct BoundExtraCreateTableInfo : public BoundExtraCreateCatalogEntryInfo { std::vector propertyInfos; - BoundExtraCreateNodeTableInfo( - common::property_id_t primaryKeyIdx, std::vector propertyInfos) - : primaryKeyIdx{primaryKeyIdx}, propertyInfos{std::move(propertyInfos)} {} + explicit BoundExtraCreateTableInfo(std::vector propertyInfos) + : propertyInfos{std::move(propertyInfos)} {} + + BoundExtraCreateTableInfo(const BoundExtraCreateTableInfo& other) + : BoundExtraCreateTableInfo{copyVector(other.propertyInfos)} {} + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } +}; + +struct BoundExtraCreateNodeTableInfo final : public BoundExtraCreateTableInfo { + common::property_id_t primaryKeyIdx; + + BoundExtraCreateNodeTableInfo(common::property_id_t primaryKeyIdx, + std::vector propertyInfos) + : BoundExtraCreateTableInfo{std::move(propertyInfos)}, primaryKeyIdx{primaryKeyIdx} {} BoundExtraCreateNodeTableInfo(const BoundExtraCreateNodeTableInfo& other) - : primaryKeyIdx{other.primaryKeyIdx}, propertyInfos{copyVector(other.propertyInfos)} {} + : BoundExtraCreateTableInfo{copyVector(other.propertyInfos)}, + primaryKeyIdx{other.primaryKeyIdx} {} - inline std::unique_ptr copy() const final { + std::unique_ptr copy() const override { return std::make_unique(*this); } }; -struct BoundExtraCreateRelTableInfo : public BoundExtraCreateTableInfo { +struct BoundExtraCreateRelTableInfo final : public BoundExtraCreateTableInfo { common::RelMultiplicity srcMultiplicity; common::RelMultiplicity dstMultiplicity; common::table_id_t srcTableID; common::table_id_t dstTableID; - std::vector propertyInfos; BoundExtraCreateRelTableInfo(common::RelMultiplicity srcMultiplicity, common::RelMultiplicity dstMultiplicity, common::table_id_t srcTableID, common::table_id_t dstTableID, std::vector propertyInfos) - : srcMultiplicity{srcMultiplicity}, dstMultiplicity{dstMultiplicity}, - srcTableID{srcTableID}, dstTableID{dstTableID}, propertyInfos{std::move(propertyInfos)} {} + : BoundExtraCreateTableInfo{std::move(propertyInfos)}, srcMultiplicity{srcMultiplicity}, + dstMultiplicity{dstMultiplicity}, srcTableID{srcTableID}, dstTableID{dstTableID} {} BoundExtraCreateRelTableInfo(const BoundExtraCreateRelTableInfo& other) - : srcMultiplicity{other.srcMultiplicity}, dstMultiplicity{other.dstMultiplicity}, - srcTableID{other.srcTableID}, dstTableID{other.dstTableID}, propertyInfos{copyVector( - other.propertyInfos)} {} + : BoundExtraCreateTableInfo{copyVector(other.propertyInfos)}, + srcMultiplicity{other.srcMultiplicity}, dstMultiplicity{other.dstMultiplicity}, + srcTableID{other.srcTableID}, dstTableID{other.dstTableID} {} - inline std::unique_ptr copy() const final { + std::unique_ptr copy() const override { return std::make_unique(*this); } }; -struct BoundExtraCreateRelTableGroupInfo : public BoundExtraCreateTableInfo { +struct BoundExtraCreateRelTableGroupInfo final : public BoundExtraCreateCatalogEntryInfo { std::vector infos; explicit BoundExtraCreateRelTableGroupInfo(std::vector infos) @@ -88,12 +101,12 @@ struct BoundExtraCreateRelTableGroupInfo : public BoundExtraCreateTableInfo { BoundExtraCreateRelTableGroupInfo(const BoundExtraCreateRelTableGroupInfo& other) : infos{copyVector(other.infos)} {} - inline std::unique_ptr copy() const final { + inline std::unique_ptr copy() const override { return std::make_unique(*this); } }; -struct BoundExtraCreateRdfGraphInfo : public BoundExtraCreateTableInfo { +struct BoundExtraCreateRdfGraphInfo final : public BoundExtraCreateCatalogEntryInfo { BoundCreateTableInfo resourceInfo; BoundCreateTableInfo literalInfo; BoundCreateTableInfo resourceTripleInfo; @@ -103,14 +116,14 @@ struct BoundExtraCreateRdfGraphInfo : public BoundExtraCreateTableInfo { BoundCreateTableInfo literalInfo, BoundCreateTableInfo resourceTripleInfo, BoundCreateTableInfo literalTripleInfo) : resourceInfo{std::move(resourceInfo)}, literalInfo{std::move(literalInfo)}, - resourceTripleInfo{std::move(resourceTripleInfo)}, literalTripleInfo{ - std::move(literalTripleInfo)} {} + resourceTripleInfo{std::move(resourceTripleInfo)}, + literalTripleInfo{std::move(literalTripleInfo)} {} BoundExtraCreateRdfGraphInfo(const BoundExtraCreateRdfGraphInfo& other) : resourceInfo{other.resourceInfo.copy()}, literalInfo{other.literalInfo.copy()}, resourceTripleInfo{other.resourceTripleInfo.copy()}, literalTripleInfo{other.literalTripleInfo.copy()} {} - inline std::unique_ptr copy() const final { + inline std::unique_ptr copy() const override { return std::make_unique(*this); } }; diff --git a/src/include/binder/expression/case_expression.h b/src/include/binder/expression/case_expression.h index 39a6648bffd..33f8b2c40f9 100644 --- a/src/include/binder/expression/case_expression.h +++ b/src/include/binder/expression/case_expression.h @@ -9,8 +9,8 @@ struct CaseAlternative { std::shared_ptr whenExpression; std::shared_ptr thenExpression; - CaseAlternative( - std::shared_ptr whenExpression, std::shared_ptr thenExpression) + CaseAlternative(std::shared_ptr whenExpression, + std::shared_ptr thenExpression) : whenExpression{std::move(whenExpression)}, thenExpression{std::move(thenExpression)} {} }; @@ -21,8 +21,8 @@ class CaseExpression : public Expression { : Expression{common::ExpressionType::CASE_ELSE, std::move(dataType), name}, elseExpression{std::move(elseExpression)} {} - inline void addCaseAlternative( - std::shared_ptr when, std::shared_ptr then) { + inline void addCaseAlternative(std::shared_ptr when, + std::shared_ptr then) { caseAlternatives.push_back(make_unique(std::move(when), std::move(then))); } inline size_t getNumCaseAlternatives() const { return caseAlternatives.size(); } diff --git a/src/include/binder/expression/expression.h b/src/include/binder/expression/expression.h index 59b67b717d6..a8fc4a27111 100644 --- a/src/include/binder/expression/expression.h +++ b/src/include/binder/expression/expression.h @@ -46,23 +46,24 @@ class Expression : public std::enable_shared_from_this { : Expression{expressionType, std::move(dataType), expression_vector{child}, std::move(uniqueName)} {} // Create leaf expression - Expression( - common::ExpressionType expressionType, common::LogicalType dataType, std::string uniqueName) - : Expression{ - expressionType, std::move(dataType), expression_vector{}, std::move(uniqueName)} {} + Expression(common::ExpressionType expressionType, common::LogicalType dataType, + std::string uniqueName) + : Expression{expressionType, std::move(dataType), expression_vector{}, + std::move(uniqueName)} {} DELETE_COPY_DEFAULT_MOVE(Expression); virtual ~Expression() = default; - inline void setAlias(const std::string& name) { alias = name; } + void setAlias(const std::string& name) { alias = name; } - inline void setUniqueName(const std::string& name) { uniqueName = name; } - inline std::string getUniqueName() const { + void setUniqueName(const std::string& name) { uniqueName = name; } + std::string getUniqueName() const { KU_ASSERT(!uniqueName.empty()); return uniqueName; } - inline common::LogicalType getDataType() const { return dataType; } - inline common::LogicalType& getDataTypeReference() { return dataType; } + virtual void cast(const common::LogicalType& type); + common::LogicalType getDataType() const { return dataType; } + common::LogicalType& getDataTypeReference() { return dataType; } inline bool hasAlias() const { return !alias.empty(); } inline std::string getAlias() const { return alias; } @@ -107,8 +108,8 @@ struct ExpressionHasher { }; struct ExpressionEquality { - bool operator()( - const std::shared_ptr& left, const std::shared_ptr& right) const { + bool operator()(const std::shared_ptr& left, + const std::shared_ptr& right) const { return left->getUniqueName() == right->getUniqueName(); } }; diff --git a/src/include/binder/expression/expression_util.h b/src/include/binder/expression/expression_util.h index d011185218a..b692875d8b9 100644 --- a/src/include/binder/expression/expression_util.h +++ b/src/include/binder/expression/expression_util.h @@ -6,10 +6,10 @@ namespace kuzu { namespace binder { struct ExpressionUtil { - static bool isExpressionsWithDataType( - const expression_vector& expressions, common::LogicalTypeID dataTypeID); - static expression_vector getExpressionsWithDataType( - const expression_vector& expressions, common::LogicalTypeID dataTypeID); + static bool isExpressionsWithDataType(const expression_vector& expressions, + common::LogicalTypeID dataTypeID); + static expression_vector getExpressionsWithDataType(const expression_vector& expressions, + common::LogicalTypeID dataTypeID); static uint32_t find(Expression* target, expression_vector expressions); @@ -20,12 +20,12 @@ struct ExpressionUtil { // Print as a1=a2 static std::string toString(const expression_pair& expressionPair); - static expression_vector excludeExpression( - const expression_vector& exprs, const Expression& exprToExclude); - static expression_vector excludeExpressions( - const expression_vector& expressions, const expression_vector& expressionsToExclude); + static expression_vector excludeExpression(const expression_vector& exprs, + const Expression& exprToExclude); + static expression_vector excludeExpressions(const expression_vector& expressions, + const expression_vector& expressionsToExclude); - static common::logical_types_t getDataTypes(const expression_vector& expressions); + static common::logical_type_vec_t getDataTypes(const expression_vector& expressions); static expression_vector removeDuplication(const expression_vector& expressions); diff --git a/src/include/binder/expression/function_expression.h b/src/include/binder/expression/function_expression.h index 8123dc4ae53..909f7291e2a 100644 --- a/src/include/binder/expression/function_expression.h +++ b/src/include/binder/expression/function_expression.h @@ -42,7 +42,7 @@ class ScalarFunctionExpression : public FunctionExpression { public: ScalarFunctionExpression(std::string functionName, common::ExpressionType expressionType, std::unique_ptr bindData, expression_vector children, - function::scalar_exec_func execFunc, function::scalar_select_func selectFunc, + function::scalar_func_exec_t execFunc, function::scalar_func_select_t selectFunc, const std::string& uniqueName) : ScalarFunctionExpression{std::move(functionName), expressionType, std::move(bindData), std::move(children), std::move(execFunc), std::move(selectFunc), nullptr, @@ -50,22 +50,22 @@ class ScalarFunctionExpression : public FunctionExpression { ScalarFunctionExpression(std::string functionName, common::ExpressionType expressionType, std::unique_ptr bindData, expression_vector children, - function::scalar_exec_func execFunc, function::scalar_select_func selectFunc, - function::scalar_compile_func compileFunc, const std::string& uniqueName) + function::scalar_func_exec_t execFunc, function::scalar_func_select_t selectFunc, + function::scalar_func_compile_exec_t compileFunc, const std::string& uniqueName) : FunctionExpression{std::move(functionName), expressionType, std::move(bindData), std::move(children), uniqueName}, - execFunc{std::move(execFunc)}, selectFunc{std::move(selectFunc)}, compileFunc{std::move( - compileFunc)} {} + execFunc{std::move(execFunc)}, selectFunc{std::move(selectFunc)}, + compileFunc{std::move(compileFunc)} {} - static std::string getUniqueName( - const std::string& functionName, const expression_vector& children); + static std::string getUniqueName(const std::string& functionName, + const expression_vector& children); std::string toStringInternal() const final; public: - function::scalar_exec_func execFunc; - function::scalar_select_func selectFunc; - function::scalar_compile_func compileFunc; + function::scalar_func_exec_t execFunc; + function::scalar_func_select_t selectFunc; + function::scalar_func_compile_exec_t compileFunc; }; class AggregateFunctionExpression : public FunctionExpression { @@ -85,8 +85,8 @@ class AggregateFunctionExpression : public FunctionExpression { std::move(bindData), std::move(children), uniqueName}, aggregateFunction{std::move(aggregateFunction)} {} - static std::string getUniqueName( - const std::string& functionName, expression_vector& children, bool isDistinct); + static std::string getUniqueName(const std::string& functionName, expression_vector& children, + bool isDistinct); inline bool isDistinct() const { return aggregateFunction->isFunctionDistinct(); } diff --git a/src/include/binder/expression/literal_expression.h b/src/include/binder/expression/literal_expression.h index b8f7ab0ac77..5a49e36603c 100644 --- a/src/include/binder/expression/literal_expression.h +++ b/src/include/binder/expression/literal_expression.h @@ -6,25 +6,21 @@ namespace kuzu { namespace binder { -class LiteralExpression : public Expression { +class LiteralExpression final : public Expression { public: LiteralExpression(std::unique_ptr value, const std::string& uniqueName) : Expression{common::ExpressionType::LITERAL, *value->getDataType(), uniqueName}, value{std::move(value)} {} - inline bool isNull() const { return value->isNull(); } + bool isNull() const { return value->isNull(); } - inline void setDataType(const common::LogicalType& targetType) { - KU_ASSERT(dataType.getLogicalTypeID() == common::LogicalTypeID::ANY && isNull()); - dataType = targetType; - value->setDataType(targetType); - } + void cast(const common::LogicalType& type) override; - inline common::Value* getValue() const { return value.get(); } + common::Value* getValue() const { return value.get(); } std::string toStringInternal() const final { return value->toString(); } - inline std::unique_ptr copy() const final { + std::unique_ptr copy() const final { return std::make_unique(value->copy(), uniqueName); } diff --git a/src/include/binder/expression/node_expression.h b/src/include/binder/expression/node_expression.h index b5b05886bd6..d2d86520499 100644 --- a/src/include/binder/expression/node_expression.h +++ b/src/include/binder/expression/node_expression.h @@ -12,10 +12,10 @@ class NodeExpression : public NodeOrRelExpression { : NodeOrRelExpression{std::move(dataType), std::move(uniqueName), std::move(variableName), std::move(tableIDs)} {} - inline void setInternalID(std::unique_ptr expression) { + void setInternalID(std::unique_ptr expression) { internalID = std::move(expression); } - inline std::shared_ptr getInternalID() const { + std::shared_ptr getInternalID() const { KU_ASSERT(internalID != nullptr); return internalID->copy(); } diff --git a/src/include/binder/expression/node_rel_expression.h b/src/include/binder/expression/node_rel_expression.h index 446cdb00485..3ef320aa93a 100644 --- a/src/include/binder/expression/node_rel_expression.h +++ b/src/include/binder/expression/node_rel_expression.h @@ -40,8 +40,8 @@ class NodeOrRelExpression : public Expression { return tableIDs[0]; } - inline void addPropertyExpression( - const std::string& propertyName, std::unique_ptr property) { + inline void addPropertyExpression(const std::string& propertyName, + std::unique_ptr property) { KU_ASSERT(!propertyNameToIdx.contains(propertyName)); propertyNameToIdx.insert({propertyName, propertyExprs.size()}); propertyExprs.push_back(std::move(property)); diff --git a/src/include/binder/expression/parameter_expression.h b/src/include/binder/expression/parameter_expression.h index 7eae97087f4..127f8e12e3c 100644 --- a/src/include/binder/expression/parameter_expression.h +++ b/src/include/binder/expression/parameter_expression.h @@ -8,24 +8,19 @@ namespace binder { class ParameterExpression : public Expression { public: - explicit ParameterExpression( - const std::string& parameterName, std::shared_ptr value) - : Expression{common::ExpressionType::PARAMETER, - common::LogicalType(common::LogicalTypeID::ANY), createUniqueName(parameterName)}, + explicit ParameterExpression(const std::string& parameterName, + std::shared_ptr value) + : Expression{common::ExpressionType::PARAMETER, common::LogicalType(*value->getDataType()), + createUniqueName(parameterName)}, parameterName(parameterName), value{std::move(value)} {} - inline void setDataType(const common::LogicalType& targetType) { - KU_ASSERT(dataType.getLogicalTypeID() == common::LogicalTypeID::ANY); - dataType = targetType; - value->setDataType(targetType); - } + void cast(const common::LogicalType& type) override; - inline std::shared_ptr getLiteral() const { return value; } - - inline std::string toStringInternal() const final { return "$" + parameterName; } + std::shared_ptr getLiteral() const { return value; } private: - inline static std::string createUniqueName(const std::string& input) { return "$" + input; } + std::string toStringInternal() const final { return "$" + parameterName; } + static std::string createUniqueName(const std::string& input) { return "$" + input; } private: std::string parameterName; diff --git a/src/include/binder/expression/path_expression.h b/src/include/binder/expression/path_expression.h index c8b334652ac..ee23db3a41a 100644 --- a/src/include/binder/expression/path_expression.h +++ b/src/include/binder/expression/path_expression.h @@ -12,8 +12,8 @@ class PathExpression : public Expression { expression_vector children) : Expression{common::ExpressionType::PATH, std::move(dataType), std::move(children), std::move(uniqueName)}, - variableName{std::move(variableName)}, nodeType{std::move(nodeType)}, relType{std::move( - relType)} {} + variableName{std::move(variableName)}, nodeType{std::move(nodeType)}, + relType{std::move(relType)} {} inline std::string getVariableName() const { return variableName; } inline common::LogicalType* getNodeType() const { return nodeType.get(); } diff --git a/src/include/binder/expression/rel_expression.h b/src/include/binder/expression/rel_expression.h index 4e6155cb3b2..687c9bb44fb 100644 --- a/src/include/binder/expression/rel_expression.h +++ b/src/include/binder/expression/rel_expression.h @@ -49,8 +49,8 @@ struct RdfPredicateInfo { std::vector resourceTableIDs; std::shared_ptr predicateID; - RdfPredicateInfo( - std::vector resourceTableIDs, std::shared_ptr predicateID) + RdfPredicateInfo(std::vector resourceTableIDs, + std::shared_ptr predicateID) : resourceTableIDs{std::move(resourceTableIDs)}, predicateID{std::move(predicateID)} {} DELETE_COPY_DEFAULT_MOVE(RdfPredicateInfo); }; @@ -63,8 +63,8 @@ class RelExpression : public NodeOrRelExpression { common::QueryRelType relType) : NodeOrRelExpression{std::move(dataType), std::move(uniqueName), std::move(variableName), std::move(tableIDs)}, - srcNode{std::move(srcNode)}, dstNode{std::move(dstNode)}, - directionType{directionType}, relType{relType} {} + srcNode{std::move(srcNode)}, dstNode{std::move(dstNode)}, directionType{directionType}, + relType{relType} {} inline bool isRecursive() const { return dataType.getLogicalTypeID() == common::LogicalTypeID::RECURSIVE_REL; diff --git a/src/include/binder/expression/subquery_expression.h b/src/include/binder/expression/subquery_expression.h index eb9fcf6f9c6..9953a9100d6 100644 --- a/src/include/binder/expression/subquery_expression.h +++ b/src/include/binder/expression/subquery_expression.h @@ -14,8 +14,8 @@ class SubqueryExpression : public Expression { SubqueryExpression(common::SubqueryType subqueryType, common::LogicalType dataType, QueryGraphCollection queryGraphCollection, std::string uniqueName, std::string rawName) : Expression{common::ExpressionType::SUBQUERY, std::move(dataType), std::move(uniqueName)}, - subqueryType{subqueryType}, - queryGraphCollection{std::move(queryGraphCollection)}, rawName{std::move(rawName)} {} + subqueryType{subqueryType}, queryGraphCollection{std::move(queryGraphCollection)}, + rawName{std::move(rawName)} {} inline common::SubqueryType getSubqueryType() const { return subqueryType; } diff --git a/src/include/binder/expression/variable_expression.h b/src/include/binder/expression/variable_expression.h index 6d2c6a3d5f3..45b7c5d89b7 100644 --- a/src/include/binder/expression/variable_expression.h +++ b/src/include/binder/expression/variable_expression.h @@ -7,8 +7,8 @@ namespace binder { class VariableExpression : public Expression { public: - VariableExpression( - common::LogicalType dataType, std::string uniqueName, std::string variableName) + VariableExpression(common::LogicalType dataType, std::string uniqueName, + std::string variableName) : Expression{common::ExpressionType::VARIABLE, std::move(dataType), std::move(uniqueName)}, variableName{std::move(variableName)} {} diff --git a/src/include/binder/expression_binder.h b/src/include/binder/expression_binder.h index 23ef9398893..5f3fa343d7e 100644 --- a/src/include/binder/expression_binder.h +++ b/src/include/binder/expression_binder.h @@ -4,6 +4,10 @@ #include "parser/expression/parsed_expression.h" namespace kuzu { +namespace main { +class ClientContext; +} + namespace common { class Value; } @@ -17,38 +21,40 @@ class ExpressionBinder { friend class Binder; public: - explicit ExpressionBinder(Binder* queryBinder) : binder{queryBinder} {} + ExpressionBinder(Binder* queryBinder, main::ClientContext* context) + : binder{queryBinder}, context{context} {} std::shared_ptr bindExpression(const parser::ParsedExpression& parsedExpression); - static void resolveAnyDataType(Expression& expression, const common::LogicalType& targetType); - /****** validation *****/ - static void validateExpectedDataType( - const Expression& expression, common::LogicalTypeID target) { + static void validateExpectedDataType(const Expression& expression, + common::LogicalTypeID target) { validateExpectedDataType(expression, std::vector{target}); } - static void validateExpectedDataType( - const Expression& expression, const std::vector& targets); + static void validateExpectedDataType(const Expression& expression, + const std::vector& targets); + // Validate data type. + static void validateDataType(const Expression& expr, const common::LogicalType& expectedType); + // Validate recursive data type top level (used when child type is unknown). + static void validateDataType(const Expression& expr, common::LogicalTypeID expectedTypeID); -private: // TODO(Xiyang): move to an expression rewriter std::shared_ptr foldExpression(const std::shared_ptr& expression); // Boolean expressions. std::shared_ptr bindBooleanExpression( const parser::ParsedExpression& parsedExpression); - std::shared_ptr bindBooleanExpression( - common::ExpressionType expressionType, const expression_vector& children); + std::shared_ptr bindBooleanExpression(common::ExpressionType expressionType, + const expression_vector& children); std::shared_ptr combineBooleanExpressions(common::ExpressionType expressionType, std::shared_ptr left, std::shared_ptr right); // Comparison expressions. std::shared_ptr bindComparisonExpression( const parser::ParsedExpression& parsedExpression); - std::shared_ptr bindComparisonExpression( - common::ExpressionType expressionType, const expression_vector& children); - std::shared_ptr createEqualityComparisonExpression( - std::shared_ptr left, std::shared_ptr right); + std::shared_ptr bindComparisonExpression(common::ExpressionType expressionType, + const expression_vector& children); + std::shared_ptr createEqualityComparisonExpression(std::shared_ptr left, + std::shared_ptr right); // Null operator expressions. std::shared_ptr bindNullOperatorExpression( const parser::ParsedExpression& parsedExpression); @@ -58,18 +64,20 @@ class ExpressionBinder { expression_vector bindStructPropertyStarExpression(const std::shared_ptr& child); std::shared_ptr bindPropertyExpression( const parser::ParsedExpression& parsedExpression); - std::shared_ptr bindNodeOrRelPropertyExpression( - const Expression& child, const std::string& propertyName); - std::shared_ptr bindStructPropertyExpression( - std::shared_ptr child, const std::string& propertyName); + std::shared_ptr bindNodeOrRelPropertyExpression(const Expression& child, + const std::string& propertyName); + std::shared_ptr bindStructPropertyExpression(std::shared_ptr child, + const std::string& propertyName); // Function expressions. std::shared_ptr bindFunctionExpression( const parser::ParsedExpression& parsedExpression); std::shared_ptr bindScalarFunctionExpression( const parser::ParsedExpression& parsedExpression, const std::string& functionName); - std::shared_ptr bindScalarFunctionExpression( - const expression_vector& children, const std::string& functionName); + std::shared_ptr bindScalarFunctionExpression(const expression_vector& children, + const std::string& functionName); + std::shared_ptr bindRewriteFunctionExpression( + const parser::ParsedExpression& parsedExpression); std::shared_ptr bindAggregateFunctionExpression( const parser::ParsedExpression& parsedExpression, const std::string& functionName, bool isDistinct); @@ -78,9 +86,6 @@ class ExpressionBinder { std::shared_ptr rewriteFunctionExpression( const parser::ParsedExpression& parsedExpression, const std::string& functionName); - std::unique_ptr createInternalNodeIDExpression(const Expression& node); - std::shared_ptr bindInternalIDExpression( - const std::shared_ptr& expression); std::shared_ptr bindStartNodeExpression(const Expression& expression); std::shared_ptr bindEndNodeExpression(const Expression& expression); std::shared_ptr bindLabelFunction(const Expression& expression); @@ -99,10 +104,10 @@ class ExpressionBinder { std::shared_ptr bindVariableExpression( const parser::ParsedExpression& parsedExpression); std::shared_ptr bindVariableExpression(const std::string& varName); - std::shared_ptr createVariableExpression( - common::LogicalType logicalType, std::string_view name); - std::shared_ptr createVariableExpression( - common::LogicalType logicalType, std::string name); + std::shared_ptr createVariableExpression(common::LogicalType logicalType, + std::string_view name); + std::shared_ptr createVariableExpression(common::LogicalType logicalType, + std::string name); // Subquery expressions. std::shared_ptr bindSubqueryExpression( const parser::ParsedExpression& parsedExpression); @@ -115,8 +120,8 @@ class ExpressionBinder { const std::shared_ptr& expression, common::LogicalTypeID targetTypeID); static std::shared_ptr implicitCastIfNecessary( const std::shared_ptr& expression, const common::LogicalType& targetType); - static std::shared_ptr implicitCast( - const std::shared_ptr& expression, const common::LogicalType& targetType); + static std::shared_ptr implicitCast(const std::shared_ptr& expression, + const common::LogicalType& targetType); /****** validation *****/ // E.g. SUM(SUM(a.age)) is not allowed @@ -124,6 +129,7 @@ class ExpressionBinder { private: Binder* binder; + main::ClientContext* context; std::unordered_map> parameterMap; }; diff --git a/src/include/binder/expression_visitor.h b/src/include/binder/expression_visitor.h index 86f3e482ec1..353fc23c0c1 100644 --- a/src/include/binder/expression_visitor.h +++ b/src/include/binder/expression_visitor.h @@ -44,8 +44,8 @@ class ExpressionVisitor { static bool isRandom(const Expression& expression); private: - static bool satisfyAny( - const Expression& expression, const std::function& condition); + static bool satisfyAny(const Expression& expression, + const std::function& condition); }; class ExpressionCollector { diff --git a/src/include/binder/query/query_graph.h b/src/include/binder/query/query_graph.h index 258dc0056c3..25ed8d10176 100644 --- a/src/include/binder/query/query_graph.h +++ b/src/include/binder/query/query_graph.h @@ -149,6 +149,9 @@ class QueryGraphCollection { std::vector> getQueryNodes() const; std::vector> getQueryRels() const; +private: + std::vector mergeGraphs(common::idx_t baseGraphIdx); + private: std::vector queryGraphs; }; diff --git a/src/include/binder/query/query_graph_label_analyzer.h b/src/include/binder/query/query_graph_label_analyzer.h index 71b5754e703..02b080d351e 100644 --- a/src/include/binder/query/query_graph_label_analyzer.h +++ b/src/include/binder/query/query_graph_label_analyzer.h @@ -1,6 +1,6 @@ #pragma once -#include "catalog/catalog.h" +#include "main/client_context.h" #include "query_graph.h" namespace kuzu { @@ -8,7 +8,9 @@ namespace binder { class QueryGraphLabelAnalyzer { public: - explicit QueryGraphLabelAnalyzer(const catalog::Catalog& catalog) : catalog{catalog} {} + // TODO(Jiamin): remove catalog + explicit QueryGraphLabelAnalyzer(const main::ClientContext& clientContext) + : clientContext{clientContext} {} void pruneLabel(const QueryGraph& graph); @@ -17,7 +19,7 @@ class QueryGraphLabelAnalyzer { void pruneRel(RelExpression& rel); private: - const catalog::Catalog& catalog; + const main::ClientContext& clientContext; }; } // namespace binder diff --git a/src/include/binder/query/reading_clause/bound_in_query_call.h b/src/include/binder/query/reading_clause/bound_in_query_call.h index 8e3760beda1..05ab3de3752 100644 --- a/src/include/binder/query/reading_clause/bound_in_query_call.h +++ b/src/include/binder/query/reading_clause/bound_in_query_call.h @@ -10,23 +10,23 @@ namespace binder { class BoundInQueryCall : public BoundReadingClause { public: - BoundInQueryCall(function::TableFunction* tableFunc, + BoundInQueryCall(function::TableFunction tableFunc, std::unique_ptr bindData, expression_vector outExprs, std::shared_ptr rowIdxExpr) : BoundReadingClause{common::ClauseType::IN_QUERY_CALL}, tableFunc{tableFunc}, - bindData{std::move(bindData)}, outExprs{std::move(outExprs)}, rowIdxExpr{std::move( - rowIdxExpr)} {} + bindData{std::move(bindData)}, outExprs{std::move(outExprs)}, + rowIdxExpr{std::move(rowIdxExpr)} {} - inline function::TableFunction* getTableFunc() const { return tableFunc; } + function::TableFunction getTableFunc() const { return tableFunc; } - inline const function::TableFuncBindData* getBindData() const { return bindData.get(); } + const function::TableFuncBindData* getBindData() const { return bindData.get(); } - inline expression_vector getOutExprs() const { return outExprs; } + expression_vector getOutExprs() const { return outExprs; } - inline std::shared_ptr getRowIdxExpr() const { return rowIdxExpr; } + std::shared_ptr getRowIdxExpr() const { return rowIdxExpr; } private: - function::TableFunction* tableFunc; + function::TableFunction tableFunc; std::unique_ptr bindData; expression_vector outExprs; std::shared_ptr rowIdxExpr; diff --git a/src/include/binder/query/reading_clause/bound_match_clause.h b/src/include/binder/query/reading_clause/bound_match_clause.h index 728edc1f52a..0f5db8c915d 100644 --- a/src/include/binder/query/reading_clause/bound_match_clause.h +++ b/src/include/binder/query/reading_clause/bound_match_clause.h @@ -8,8 +8,8 @@ namespace binder { class BoundMatchClause : public BoundReadingClause { public: - BoundMatchClause( - QueryGraphCollection queryGraphCollection, common::MatchClauseType matchClauseType) + BoundMatchClause(QueryGraphCollection queryGraphCollection, + common::MatchClauseType matchClauseType) : BoundReadingClause{common::ClauseType::MATCH}, queryGraphCollection{std::move(queryGraphCollection)}, matchClauseType{matchClauseType} {} diff --git a/src/include/binder/query/reading_clause/bound_unwind_clause.h b/src/include/binder/query/reading_clause/bound_unwind_clause.h index 98e1032767d..882f39edfad 100644 --- a/src/include/binder/query/reading_clause/bound_unwind_clause.h +++ b/src/include/binder/query/reading_clause/bound_unwind_clause.h @@ -8,16 +8,20 @@ namespace binder { class BoundUnwindClause : public BoundReadingClause { public: - BoundUnwindClause(std::shared_ptr inExpr, std::shared_ptr outExpr) + BoundUnwindClause(std::shared_ptr inExpr, std::shared_ptr outExpr, + std::shared_ptr idExpr) : BoundReadingClause{common::ClauseType::UNWIND}, inExpr{std::move(inExpr)}, - outExpr{std::move(outExpr)} {} + outExpr{std::move(outExpr)}, idExpr{std::move(idExpr)} {} - inline std::shared_ptr getInExpr() const { return inExpr; } - inline std::shared_ptr getOutExpr() const { return outExpr; } + std::shared_ptr getInExpr() const { return inExpr; } + std::shared_ptr getOutExpr() const { return outExpr; } + std::shared_ptr getIDExpr() const { return idExpr; } private: std::shared_ptr inExpr; std::shared_ptr outExpr; + std::shared_ptr idExpr; }; + } // namespace binder } // namespace kuzu diff --git a/src/include/binder/query/updating_clause/bound_delete_info.h b/src/include/binder/query/updating_clause/bound_delete_info.h index 3553b63b1cc..5edc3c675c2 100644 --- a/src/include/binder/query/updating_clause/bound_delete_info.h +++ b/src/include/binder/query/updating_clause/bound_delete_info.h @@ -14,14 +14,14 @@ struct BoundDeleteInfo { BoundDeleteInfo(UpdateTableType updateTableType, std::shared_ptr nodeOrRel, common::DeleteClauseType deleteClauseType) - : deleteClauseType{deleteClauseType}, updateTableType{updateTableType}, nodeOrRel{std::move( - nodeOrRel)} {} + : deleteClauseType{deleteClauseType}, updateTableType{updateTableType}, + nodeOrRel{std::move(nodeOrRel)} {} EXPLICIT_COPY_DEFAULT_MOVE(BoundDeleteInfo); private: BoundDeleteInfo(const BoundDeleteInfo& other) - : deleteClauseType{other.deleteClauseType}, - updateTableType{other.updateTableType}, nodeOrRel{other.nodeOrRel} {} + : deleteClauseType{other.deleteClauseType}, updateTableType{other.updateTableType}, + nodeOrRel{other.nodeOrRel} {} }; } // namespace binder diff --git a/src/include/binder/query/updating_clause/bound_merge_clause.h b/src/include/binder/query/updating_clause/bound_merge_clause.h index 0e794489dba..fa29b8d4db7 100644 --- a/src/include/binder/query/updating_clause/bound_merge_clause.h +++ b/src/include/binder/query/updating_clause/bound_merge_clause.h @@ -11,91 +11,92 @@ namespace binder { class BoundMergeClause : public BoundUpdatingClause { public: BoundMergeClause(QueryGraphCollection queryGraphCollection, - std::shared_ptr predicate, std::vector insertInfos) - : BoundUpdatingClause{common::ClauseType::MERGE}, queryGraphCollection{std::move( - queryGraphCollection)}, - predicate{std::move(predicate)}, insertInfos{std::move(insertInfos)} {} + std::shared_ptr predicate, std::vector insertInfos, + std::shared_ptr distinctMark) + : BoundUpdatingClause{common::ClauseType::MERGE}, + queryGraphCollection{std::move(queryGraphCollection)}, predicate{std::move(predicate)}, + insertInfos{std::move(insertInfos)}, distinctMark{std::move(distinctMark)} {} - inline const QueryGraphCollection* getQueryGraphCollection() const { - return &queryGraphCollection; - } - inline bool hasPredicate() const { return predicate != nullptr; } - inline std::shared_ptr getPredicate() const { return predicate; } + const QueryGraphCollection* getQueryGraphCollection() const { return &queryGraphCollection; } + bool hasPredicate() const { return predicate != nullptr; } + std::shared_ptr getPredicate() const { return predicate; } - inline const std::vector& getInsertInfosRef() const { return insertInfos; } - inline const std::vector& getOnMatchSetInfosRef() const { + const std::vector& getInsertInfosRef() const { return insertInfos; } + const std::vector& getOnMatchSetInfosRef() const { return onMatchSetPropertyInfos; } - inline const std::vector& getOnCreateSetInfosRef() const { + const std::vector& getOnCreateSetInfosRef() const { return onCreateSetPropertyInfos; } - inline bool hasInsertNodeInfo() const { + bool hasInsertNodeInfo() const { return hasInsertInfo( [](const BoundInsertInfo& info) { return info.tableType == common::TableType::NODE; }); } - inline std::vector getInsertNodeInfos() const { + std::vector getInsertNodeInfos() const { return getInsertInfos( [](const BoundInsertInfo& info) { return info.tableType == common::TableType::NODE; }); } - inline bool hasInsertRelInfo() const { + bool hasInsertRelInfo() const { return hasInsertInfo( [](const BoundInsertInfo& info) { return info.tableType == common::TableType::REL; }); } - inline std::vector getInsertRelInfos() const { + std::vector getInsertRelInfos() const { return getInsertInfos( [](const BoundInsertInfo& info) { return info.tableType == common::TableType::REL; }); } - inline bool hasOnMatchSetNodeInfo() const { + bool hasOnMatchSetNodeInfo() const { return hasOnMatchSetInfo([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::NODE; }); } - inline std::vector getOnMatchSetNodeInfos() const { + std::vector getOnMatchSetNodeInfos() const { return getOnMatchSetInfos([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::NODE; }); } - inline bool hasOnMatchSetRelInfo() const { + bool hasOnMatchSetRelInfo() const { return hasOnMatchSetInfo([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::REL; }); } - inline std::vector getOnMatchSetRelInfos() const { + std::vector getOnMatchSetRelInfos() const { return getOnMatchSetInfos([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::REL; }); } - inline bool hasOnCreateSetNodeInfo() const { + bool hasOnCreateSetNodeInfo() const { return hasOnCreateSetInfo([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::NODE; }); } - inline std::vector getOnCreateSetNodeInfos() const { + std::vector getOnCreateSetNodeInfos() const { return getOnCreateSetInfos([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::NODE; }); } - inline bool hasOnCreateSetRelInfo() const { + bool hasOnCreateSetRelInfo() const { return hasOnCreateSetInfo([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::REL; }); } - inline std::vector getOnCreateSetRelInfos() const { + std::vector getOnCreateSetRelInfos() const { return getOnCreateSetInfos([](const BoundSetPropertyInfo& info) { return info.updateTableType == UpdateTableType::REL; }); } - inline void addOnMatchSetPropertyInfo(BoundSetPropertyInfo setPropertyInfo) { + void addOnMatchSetPropertyInfo(BoundSetPropertyInfo setPropertyInfo) { onMatchSetPropertyInfos.push_back(std::move(setPropertyInfo)); } - inline void addOnCreateSetPropertyInfo(BoundSetPropertyInfo setPropertyInfo) { + void addOnCreateSetPropertyInfo(BoundSetPropertyInfo setPropertyInfo) { onCreateSetPropertyInfos.push_back(std::move(setPropertyInfo)); } + std::shared_ptr getDistinctMark() const { return distinctMark; } + private: bool hasInsertInfo(const std::function& check) const; std::vector getInsertInfos( @@ -121,6 +122,7 @@ class BoundMergeClause : public BoundUpdatingClause { std::vector onMatchSetPropertyInfos; // Update on create std::vector onCreateSetPropertyInfos; + std::shared_ptr distinctMark; }; } // namespace binder diff --git a/src/include/binder/query/updating_clause/bound_set_info.h b/src/include/binder/query/updating_clause/bound_set_info.h index 55959557d5c..e2e8d43b76e 100644 --- a/src/include/binder/query/updating_clause/bound_set_info.h +++ b/src/include/binder/query/updating_clause/bound_set_info.h @@ -13,14 +13,14 @@ struct BoundSetPropertyInfo { BoundSetPropertyInfo(UpdateTableType updateTableType, std::shared_ptr nodeOrRel, expression_pair setItem) - : updateTableType{updateTableType}, nodeOrRel{std::move(nodeOrRel)}, setItem{std::move( - setItem)} {} + : updateTableType{updateTableType}, nodeOrRel{std::move(nodeOrRel)}, + setItem{std::move(setItem)} {} EXPLICIT_COPY_DEFAULT_MOVE(BoundSetPropertyInfo); private: BoundSetPropertyInfo(const BoundSetPropertyInfo& other) - : updateTableType{other.updateTableType}, nodeOrRel{other.nodeOrRel}, setItem{ - other.setItem} {} + : updateTableType{other.updateTableType}, nodeOrRel{other.nodeOrRel}, + setItem{other.setItem} {} }; } // namespace binder diff --git a/src/include/binder/rewriter/match_clause_pattern_label_rewriter.h b/src/include/binder/rewriter/match_clause_pattern_label_rewriter.h index 7ac99537e2a..ad06d9684da 100644 --- a/src/include/binder/rewriter/match_clause_pattern_label_rewriter.h +++ b/src/include/binder/rewriter/match_clause_pattern_label_rewriter.h @@ -8,7 +8,8 @@ namespace binder { class MatchClausePatternLabelRewriter : public BoundStatementVisitor { public: - explicit MatchClausePatternLabelRewriter(const catalog::Catalog& catalog) : analyzer{catalog} {} + explicit MatchClausePatternLabelRewriter(const main::ClientContext& clientContext) + : analyzer{clientContext} {} void visitMatch(const BoundReadingClause& readingClause) final; diff --git a/src/include/binder/visitor/default_type_solver.h b/src/include/binder/visitor/default_type_solver.h new file mode 100644 index 00000000000..3fc5ec965ba --- /dev/null +++ b/src/include/binder/visitor/default_type_solver.h @@ -0,0 +1,21 @@ +#pragma once + +#include "binder/bound_statement_visitor.h" + +namespace kuzu { +namespace binder { + +// Assign a default data type (STRING) for expressions with ANY data type for a given statement. +// E.g. RETURN NULL; Expression NULL can be resolved as any type based on semantic. +// We don't iterate all expressions because +// - predicates must have been resolved to BOOL type +// - lhs expressions for update must have been resolved to column type +// So we only need to resolve for expressions appear in the projection clause. This assumption might +// change as we add more features. +class DefaultTypeSolver final : public BoundStatementVisitor { +private: + void visitProjectionBody(const BoundProjectionBody& projectionBody) override; +}; + +} // namespace binder +} // namespace kuzu diff --git a/src/include/binder/visitor/property_collector.h b/src/include/binder/visitor/property_collector.h index d592de959ed..7c7cb352e17 100644 --- a/src/include/binder/visitor/property_collector.h +++ b/src/include/binder/visitor/property_collector.h @@ -5,6 +5,7 @@ namespace kuzu { namespace binder { +// Collect all property expressions for a given statement. class PropertyCollector final : public BoundStatementVisitor { public: expression_vector getProperties(); diff --git a/src/include/c_api/kuzu.h b/src/include/c_api/kuzu.h index 03e78511ae2..4e88e7837be 100644 --- a/src/include/c_api/kuzu.h +++ b/src/include/c_api/kuzu.h @@ -154,6 +154,7 @@ typedef struct { */ typedef struct { void* _query_result; + bool _is_owned_by_cpp; } kuzu_query_result; /** @@ -292,18 +293,18 @@ typedef enum { KUZU_TIMESTAMP_NS = 38, KUZU_TIMESTAMP_TZ = 39, KUZU_INTERVAL = 40, - KUZU_FIXED_LIST = 41, KUZU_INTERNAL_ID = 42, // variable size types KUZU_STRING = 50, KUZU_BLOB = 51, - KUZU_VAR_LIST = 52, - KUZU_STRUCT = 53, - KUZU_MAP = 54, - KUZU_UNION = 55, - KUZU_RDF_VARIANT = 56, - KUZU_POINTER = 57, - KUZU_UUID = 58 + KUZU_LIST = 52, + KUZU_ARRAY = 53, + KUZU_STRUCT = 54, + KUZU_MAP = 55, + KUZU_UNION = 56, + KUZU_RDF_VARIANT = 57, + KUZU_POINTER = 58, + KUZU_UUID = 59 } kuzu_data_type_id; // Database @@ -315,8 +316,8 @@ typedef enum { * @param system_config The runtime configuration for creating or opening the database. * @return The database instance. */ -KUZU_C_API kuzu_database* kuzu_database_init( - const char* database_path, kuzu_system_config system_config); +KUZU_C_API kuzu_database* kuzu_database_init(const char* database_path, + kuzu_system_config system_config); /** * @brief Destroys the kuzu database instance and frees the allocated memory. * @param database The database instance to destroy. @@ -349,8 +350,8 @@ KUZU_C_API void kuzu_connection_destroy(kuzu_connection* connection); * @param connection The connection instance to set max number of threads for execution. * @param num_threads The maximum number of threads to use for executing queries. */ -KUZU_C_API void kuzu_connection_set_max_num_thread_for_exec( - kuzu_connection* connection, uint64_t num_threads); +KUZU_C_API void kuzu_connection_set_max_num_thread_for_exec(kuzu_connection* connection, + uint64_t num_threads); /** * @brief Returns the maximum number of threads of the connection to use for executing queries. @@ -369,15 +370,15 @@ KUZU_C_API kuzu_query_result* kuzu_connection_query(kuzu_connection* connection, * @param connection The connection instance to prepare the query. * @param query The query to prepare. */ -KUZU_C_API kuzu_prepared_statement* kuzu_connection_prepare( - kuzu_connection* connection, const char* query); +KUZU_C_API kuzu_prepared_statement* kuzu_connection_prepare(kuzu_connection* connection, + const char* query); /** * @brief Executes the prepared_statement using connection. * @param connection The connection instance to execute the prepared_statement. * @param prepared_statement The prepared statement to execute. */ -KUZU_C_API kuzu_query_result* kuzu_connection_execute( - kuzu_connection* connection, kuzu_prepared_statement* prepared_statement); +KUZU_C_API kuzu_query_result* kuzu_connection_execute(kuzu_connection* connection, + kuzu_prepared_statement* prepared_statement); /** * @brief Interrupts the current query execution in the connection. * @param connection The connection instance to interrupt. @@ -388,8 +389,8 @@ KUZU_C_API void kuzu_connection_interrupt(kuzu_connection* connection); * @param connection The connection instance to set query timeout value. * @param timeout_in_ms The timeout value in milliseconds. */ -KUZU_C_API void kuzu_connection_set_query_timeout( - kuzu_connection* connection, uint64_t timeout_in_ms); +KUZU_C_API void kuzu_connection_set_query_timeout(kuzu_connection* connection, + uint64_t timeout_in_ms); // PreparedStatement /** @@ -419,72 +420,72 @@ KUZU_C_API char* kuzu_prepared_statement_get_error_message( * @param param_name The parameter name to bind the value. * @param value The boolean value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_bool( - kuzu_prepared_statement* prepared_statement, const char* param_name, bool value); +KUZU_C_API void kuzu_prepared_statement_bind_bool(kuzu_prepared_statement* prepared_statement, + const char* param_name, bool value); /** * @brief Binds the given int64_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The int64_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_int64( - kuzu_prepared_statement* prepared_statement, const char* param_name, int64_t value); +KUZU_C_API void kuzu_prepared_statement_bind_int64(kuzu_prepared_statement* prepared_statement, + const char* param_name, int64_t value); /** * @brief Binds the given int32_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The int32_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_int32( - kuzu_prepared_statement* prepared_statement, const char* param_name, int32_t value); +KUZU_C_API void kuzu_prepared_statement_bind_int32(kuzu_prepared_statement* prepared_statement, + const char* param_name, int32_t value); /** * @brief Binds the given int16_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The int16_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_int16( - kuzu_prepared_statement* prepared_statement, const char* param_name, int16_t value); +KUZU_C_API void kuzu_prepared_statement_bind_int16(kuzu_prepared_statement* prepared_statement, + const char* param_name, int16_t value); /** * @brief Binds the given int8_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The int8_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_int8( - kuzu_prepared_statement* prepared_statement, const char* param_name, int8_t value); +KUZU_C_API void kuzu_prepared_statement_bind_int8(kuzu_prepared_statement* prepared_statement, + const char* param_name, int8_t value); /** * @brief Binds the given uint64_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The uint64_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_uint64( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint64_t value); +KUZU_C_API void kuzu_prepared_statement_bind_uint64(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint64_t value); /** * @brief Binds the given uint32_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The uint32_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_uint32( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint32_t value); +KUZU_C_API void kuzu_prepared_statement_bind_uint32(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint32_t value); /** * @brief Binds the given uint16_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The uint16_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_uint16( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint16_t value); +KUZU_C_API void kuzu_prepared_statement_bind_uint16(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint16_t value); /** * @brief Binds the given int8_t value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The int8_t value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_uint8( - kuzu_prepared_statement* prepared_statement, const char* param_name, uint8_t value); +KUZU_C_API void kuzu_prepared_statement_bind_uint8(kuzu_prepared_statement* prepared_statement, + const char* param_name, uint8_t value); /** * @brief Binds the given double value to the given parameter name in the prepared statement. @@ -492,24 +493,24 @@ KUZU_C_API void kuzu_prepared_statement_bind_uint8( * @param param_name The parameter name to bind the value. * @param value The double value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_double( - kuzu_prepared_statement* prepared_statement, const char* param_name, double value); +KUZU_C_API void kuzu_prepared_statement_bind_double(kuzu_prepared_statement* prepared_statement, + const char* param_name, double value); /** * @brief Binds the given float value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The float value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_float( - kuzu_prepared_statement* prepared_statement, const char* param_name, float value); +KUZU_C_API void kuzu_prepared_statement_bind_float(kuzu_prepared_statement* prepared_statement, + const char* param_name, float value); /** * @brief Binds the given date value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The date value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_date( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_date_t value); +KUZU_C_API void kuzu_prepared_statement_bind_date(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_date_t value); /** * @brief Binds the given timestamp_ns value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. @@ -549,32 +550,32 @@ KUZU_C_API void kuzu_prepared_statement_bind_timestamp_ms( * @param param_name The parameter name to bind the value. * @param value The timestamp value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_timestamp( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_timestamp_t value); +KUZU_C_API void kuzu_prepared_statement_bind_timestamp(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_timestamp_t value); /** * @brief Binds the given interval value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The interval value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_interval( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_interval_t value); +KUZU_C_API void kuzu_prepared_statement_bind_interval(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_interval_t value); /** * @brief Binds the given string value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The string value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_string( - kuzu_prepared_statement* prepared_statement, const char* param_name, const char* value); +KUZU_C_API void kuzu_prepared_statement_bind_string(kuzu_prepared_statement* prepared_statement, + const char* param_name, const char* value); /** * @brief Binds the given kuzu value to the given parameter name in the prepared statement. * @param prepared_statement The prepared statement instance to bind the value. * @param param_name The parameter name to bind the value. * @param value The kuzu value to bind. */ -KUZU_C_API void kuzu_prepared_statement_bind_value( - kuzu_prepared_statement* prepared_statement, const char* param_name, kuzu_value* value); +KUZU_C_API void kuzu_prepared_statement_bind_value(kuzu_prepared_statement* prepared_statement, + const char* param_name, kuzu_value* value); // QueryResult /** @@ -630,6 +631,20 @@ KUZU_C_API bool kuzu_query_result_has_next(kuzu_query_result* query_result); * @param query_result The query result instance to return. */ KUZU_C_API kuzu_flat_tuple* kuzu_query_result_get_next(kuzu_query_result* query_result); +/** + * @brief Returns true if we have not consumed all query results, false otherwise. Use this function + * for loop results of multiple query statements + * @param query_result The query result instance to check. + */ +KUZU_C_API bool kuzu_query_result_has_next_query_result(kuzu_query_result* query_result); +/** + * @brief Returns the next query result. Use this function to loop multiple query statements' + * results. + * @param query_result The query result instance to return. + */ +KUZU_C_API kuzu_query_result* kuzu_query_result_get_next_query_result( + kuzu_query_result* query_result); + /** * @brief Returns the query result as a string. * @param query_result The query result instance to return. @@ -659,8 +674,8 @@ KUZU_C_API struct ArrowSchema kuzu_query_result_get_arrow_schema(kuzu_query_resu * * It is the caller's responsibility to call the release function to release the underlying data */ -KUZU_C_API struct ArrowArray kuzu_query_result_get_next_arrow_chunk( - kuzu_query_result* query_result, int64_t chunk_size); +KUZU_C_API struct ArrowArray kuzu_query_result_get_next_arrow_chunk(kuzu_query_result* query_result, + int64_t chunk_size); // FlatTuple /** @@ -683,15 +698,14 @@ KUZU_C_API char* kuzu_flat_tuple_to_string(kuzu_flat_tuple* flat_tuple); // DataType // TODO(Chang): Refactor the datatype constructor to follow the cpp way of creating dataTypes. /** - * @brief Creates a data type instance with the given id, childType and fixed_num_elements_in_list. + * @brief Creates a data type instance with the given id, childType and num_elements_in_array. * Caller is responsible for destroying the returned data type instance. * @param id The enum type id of the datatype to create. * @param child_type The child type of the datatype to create(only used for nested dataTypes). - * @param fixed_num_elements_in_list The fixed number of elements in the list(only used for - * FIXED_LIST). + * @param num_elements_in_array The number of elements in the array(only used for ARRAY). */ -KUZU_C_API kuzu_logical_type* kuzu_data_type_create( - kuzu_data_type_id id, kuzu_logical_type* child_type, uint64_t fixed_num_elements_in_list); +KUZU_C_API kuzu_logical_type* kuzu_data_type_create(kuzu_data_type_id id, + kuzu_logical_type* child_type, uint64_t num_elements_in_array); /** * @brief Creates a new data type instance by cloning the given data type instance. * @param data_type The data type instance to clone. @@ -714,10 +728,10 @@ KUZU_C_API bool kuzu_data_type_equals(kuzu_logical_type* data_type1, kuzu_logica */ KUZU_C_API kuzu_data_type_id kuzu_data_type_get_id(kuzu_logical_type* data_type); /** - * @brief Returns the number of elements per list for fixedSizeList. + * @brief Returns the number of elements for array. * @param data_type The data type instance to return. */ -KUZU_C_API uint64_t kuzu_data_type_get_fixed_num_elements_in_list(kuzu_logical_type* data_type); +KUZU_C_API uint64_t kuzu_data_type_get_num_elements_in_array(kuzu_logical_type* data_type); // Value /** @@ -892,13 +906,13 @@ KUZU_C_API void kuzu_value_copy(kuzu_value* value, kuzu_value* other); KUZU_C_API void kuzu_value_destroy(kuzu_value* value); /** * @brief Returns the number of elements per list of the given value. The value must be of type - * FIXED_LIST. - * @param value The FIXED_LIST value to get list size. + * ARRAY. + * @param value The ARRAY value to get list size. */ KUZU_C_API uint64_t kuzu_value_get_list_size(kuzu_value* value); /** - * @brief Returns the element at index of the given value. The value must be of type VAR_LIST. - * @param value The VAR_LIST value to return. + * @brief Returns the element at index of the given value. The value must be of type LIST. + * @param value The LIST value to return. * @param index The index of the element to return. */ KUZU_C_API kuzu_value* kuzu_value_get_list_element(kuzu_value* value, uint64_t index); diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index cc980e33e95..fb6c15ad428 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -2,8 +2,7 @@ #include -#include "catalog/catalog_entry/table_catalog_entry.h" -#include "catalog_content.h" +#include "catalog/catalog_content.h" namespace kuzu { namespace storage { @@ -14,7 +13,7 @@ enum class TransactionAction : uint8_t; class Transaction; } // namespace transaction namespace catalog { - +class TableCatalogEntry; class NodeTableCatalogEntry; class RelTableCatalogEntry; class RelGroupCatalogEntry; @@ -41,44 +40,31 @@ class Catalog { std::vector getRelTableIDs(transaction::Transaction* tx) const; std::string getTableName(transaction::Transaction* tx, common::table_id_t tableID) const; - TableCatalogEntry* getTableCatalogEntry( - transaction::Transaction* tx, common::table_id_t tableID) const; + TableCatalogEntry* getTableCatalogEntry(transaction::Transaction* tx, + common::table_id_t tableID) const; std::vector getNodeTableEntries(transaction::Transaction* tx) const; std::vector getRelTableEntries(transaction::Transaction* tx) const; std::vector getRelTableGroupEntries(transaction::Transaction* tx) const; std::vector getRdfGraphEntries(transaction::Transaction* tx) const; std::vector getTableEntries(transaction::Transaction* tx) const; - std::vector getTableSchemas( - transaction::Transaction* tx, const common::table_id_vector_t& tableIDs) const; - CatalogSet* getFunctions(transaction::Transaction* tx) const; + std::vector getTableSchemas(transaction::Transaction* tx, + const common::table_id_vector_t& tableIDs) const; - common::table_id_t addNodeTableSchema(const binder::BoundCreateTableInfo& info); - common::table_id_t addRelTableSchema(const binder::BoundCreateTableInfo& info); - common::table_id_t addRelTableGroupSchema(const binder::BoundCreateTableInfo& info); - common::table_id_t addRdfGraphSchema(const binder::BoundCreateTableInfo& info); + common::table_id_t createTableSchema(const binder::BoundCreateTableInfo& info); void dropTableSchema(common::table_id_t tableID); - void renameTable(common::table_id_t tableID, const std::string& newName); - - void addNodeProperty(common::table_id_t tableID, const std::string& propertyName, - std::unique_ptr dataType); - void addRelProperty(common::table_id_t tableID, const std::string& propertyName, - std::unique_ptr dataType); - - void dropProperty(common::table_id_t tableID, common::property_id_t propertyID); - - void renameProperty( - common::table_id_t tableID, common::property_id_t propertyID, const std::string& newName); + void alterTableSchema(const binder::BoundAlterInfo& info); void setTableComment(common::table_id_t tableID, const std::string& comment); // ----------------------------- Functions ---------------------------- - common::ExpressionType getFunctionType( - transaction::Transaction* tx, const std::string& name) const; void addFunction(std::string name, function::function_set functionSet); void addBuiltInFunction(std::string name, function::function_set functionSet); + CatalogSet* getFunctions(transaction::Transaction* tx) const; + CatalogEntry* getFunctionEntry(transaction::Transaction* tx, const std::string& name); + bool containsMacro(transaction::Transaction* tx, const std::string& macroName) const; - void addScalarMacroFunction( - std::string name, std::unique_ptr macro); + void addScalarMacroFunction(std::string name, + std::unique_ptr macro); // TODO(Ziyi): pass transaction pointer here. function::ScalarMacroFunction* getScalarMacroFunction(const std::string& name) const { return readOnlyVersion->getScalarMacroFunction(name); @@ -96,20 +82,22 @@ class Catalog { } } - static void saveInitialCatalogToFile( - const std::string& directory, common::VirtualFileSystem* vfs) { - std::make_unique(vfs)->getReadOnlyVersion()->saveToFile( - directory, common::FileVersionType::ORIGINAL); + static void saveInitialCatalogToFile(const std::string& directory, + common::VirtualFileSystem* vfs) { + std::make_unique(vfs)->getReadOnlyVersion()->saveToFile(directory, + common::FileVersionType::ORIGINAL); } private: CatalogContent* getVersion(transaction::Transaction* tx) const; bool hasUpdates() const { return isUpdated; } - void setToUpdated() { isUpdated = true; } void resetToNotUpdated() { isUpdated = false; } + void logCreateTableToWAL(const binder::BoundCreateTableInfo& info, common::table_id_t tableID); + void logAlterTableToWAL(const binder::BoundAlterInfo& info); + protected: // The flat indicates if the readWriteVersion has been updated and is different from the // readOnlyVersion. diff --git a/src/include/catalog/catalog_content.h b/src/include/catalog/catalog_content.h index 2281911185d..965c4cc63be 100644 --- a/src/include/catalog/catalog_content.h +++ b/src/include/catalog/catalog_content.h @@ -1,56 +1,62 @@ #pragma once -#include "binder/ddl/bound_create_table_info.h" -#include "catalog_set.h" +#include "catalog/catalog_set.h" #include "common/cast.h" -#include "function/built_in_function_utils.h" -#include "function/scalar_macro_function.h" namespace kuzu { +namespace binder { +struct BoundAlterInfo; +struct BoundCreateTableInfo; +} // namespace binder namespace common { class Serializer; class Deserializer; class VirtualFileSystem; } // namespace common +namespace function { +struct ScalarMacroFunction; +} // namespace function + namespace catalog { class CatalogContent { friend class Catalog; public: - explicit CatalogContent(common::VirtualFileSystem* vfs); + KUZU_API explicit CatalogContent(common::VirtualFileSystem* vfs); + + virtual ~CatalogContent() = default; CatalogContent(const std::string& directory, common::VirtualFileSystem* vfs); - CatalogContent(std::unique_ptr tables, - std::unordered_map tableNameToIDMap, - common::table_id_t nextTableID, std::unique_ptr functions, - common::VirtualFileSystem* vfs) - : tableNameToIDMap{std::move(tableNameToIDMap)}, nextTableID{nextTableID}, vfs{vfs}, - tables{std::move(tables)}, functions{std::move(functions)} {} + CatalogContent(std::unique_ptr tables, common::table_id_t nextTableID, + std::unique_ptr functions, common::VirtualFileSystem* vfs) + : tables{std::move(tables)}, nextTableID{nextTableID}, vfs{vfs}, + functions{std::move(functions)} {} + + common::table_id_t getTableID(const std::string& tableName) const; + CatalogEntry* getTableCatalogEntry(common::table_id_t tableID) const; void saveToFile(const std::string& directory, common::FileVersionType dbFileType); void readFromFile(const std::string& directory, common::FileVersionType dbFileType); std::unique_ptr copy() const; +protected: + common::table_id_t assignNextTableID() { return nextTableID++; } + private: // ----------------------------- Functions ---------------------------- - common::ExpressionType getFunctionType(const std::string& name) const; - void registerBuiltInFunctions(); bool containMacro(const std::string& macroName) const { return functions->containsEntry(macroName); } void addFunction(std::string name, function::function_set definitions); - void addScalarMacroFunction( - std::string name, std::unique_ptr macro); function::ScalarMacroFunction* getScalarMacroFunction(const std::string& name) const; // ----------------------------- Table entries ---------------------------- - common::table_id_t assignNextTableID() { return nextTableID++; } uint64_t getNumTables() const { return tables->getEntries().size(); } bool containsTable(const std::string& tableName) const; @@ -58,8 +64,6 @@ class CatalogContent { std::string getTableName(common::table_id_t tableID) const; - CatalogEntry* getTableCatalogEntry(common::table_id_t tableID) const; - template std::vector getTableCatalogEntries(CatalogEntryType catalogType) const { std::vector result; @@ -71,23 +75,29 @@ class CatalogContent { return result; } - common::table_id_t getTableID(const std::string& tableName) const; std::vector getTableIDs(CatalogEntryType catalogType) const; - common::table_id_t createNodeTable(const binder::BoundCreateTableInfo& info); - common::table_id_t createRelTable(const binder::BoundCreateTableInfo& info); - common::table_id_t createRelGroup(const binder::BoundCreateTableInfo& info); - common::table_id_t createRDFGraph(const binder::BoundCreateTableInfo& info); + common::table_id_t createTable(const binder::BoundCreateTableInfo& info); void dropTable(common::table_id_t tableID); + void alterTable(const binder::BoundAlterInfo& info); + +private: + std::unique_ptr createNodeTableEntry(common::table_id_t tableID, + const binder::BoundCreateTableInfo& info) const; + std::unique_ptr createRelTableEntry(common::table_id_t tableID, + const binder::BoundCreateTableInfo& info) const; + std::unique_ptr createRelTableGroupEntry(common::table_id_t tableID, + const binder::BoundCreateTableInfo& info); + std::unique_ptr createRdfGraphEntry(common::table_id_t tableID, + const binder::BoundCreateTableInfo& info); void renameTable(common::table_id_t tableID, const std::string& newName); +protected: + std::unique_ptr tables; + private: - // These two maps are maintained as caches. They are not serialized to the catalog file, but - // is re-constructed when reading from the catalog file. - std::unordered_map tableNameToIDMap; common::table_id_t nextTableID; common::VirtualFileSystem* vfs; - std::unique_ptr tables; std::unique_ptr functions; }; diff --git a/src/include/catalog/catalog_entry/aggregate_function_catalog_entry.h b/src/include/catalog/catalog_entry/aggregate_function_catalog_entry.h deleted file mode 100644 index 16a29abb67f..00000000000 --- a/src/include/catalog/catalog_entry/aggregate_function_catalog_entry.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "catalog_entry.h" -#include "function_catalog_entry.h" - -namespace kuzu { -namespace catalog { - -class AggregateFunctionCatalogEntry : public FunctionCatalogEntry { -public: - //===--------------------------------------------------------------------===// - // constructors - //===--------------------------------------------------------------------===// - AggregateFunctionCatalogEntry() = default; - AggregateFunctionCatalogEntry(std::string name, function::function_set functionSet); - - //===--------------------------------------------------------------------===// - // serialization & deserialization - //===--------------------------------------------------------------------===// - std::unique_ptr copy() const override; -}; - -} // namespace catalog -} // namespace kuzu diff --git a/src/include/catalog/catalog_entry/catalog_entry.h b/src/include/catalog/catalog_entry/catalog_entry.h index e2b0ab3e5b2..65e4fedade2 100644 --- a/src/include/catalog/catalog_entry/catalog_entry.h +++ b/src/include/catalog/catalog_entry/catalog_entry.h @@ -9,7 +9,7 @@ namespace kuzu { namespace catalog { -class CatalogEntry { +class KUZU_API CatalogEntry { public: //===--------------------------------------------------------------------===// // constructor & destructor diff --git a/src/include/catalog/catalog_entry/catalog_entry_type.h b/src/include/catalog/catalog_entry/catalog_entry_type.h index f0dcf30f8f5..d44db816aca 100644 --- a/src/include/catalog/catalog_entry/catalog_entry_type.h +++ b/src/include/catalog/catalog_entry/catalog_entry_type.h @@ -13,7 +13,9 @@ enum class CatalogEntryType : uint8_t { SCALAR_MACRO_ENTRY = 4, AGGREGATE_FUNCTION_ENTRY = 5, SCALAR_FUNCTION_ENTRY = 6, - TABLE_FUNCTION_ENTRY = 7, + REWRITE_FUNCTION_ENTRY = 7, + TABLE_FUNCTION_ENTRY = 8, + FOREIGN_TABLE_ENTRY = 9, }; } // namespace catalog diff --git a/src/include/catalog/catalog_entry/function_catalog_entry.h b/src/include/catalog/catalog_entry/function_catalog_entry.h index 8c05b914bad..969f0b077cb 100644 --- a/src/include/catalog/catalog_entry/function_catalog_entry.h +++ b/src/include/catalog/catalog_entry/function_catalog_entry.h @@ -1,7 +1,7 @@ #pragma once #include "catalog_entry.h" -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace catalog { @@ -12,8 +12,8 @@ class FunctionCatalogEntry : public CatalogEntry { // constructors //===--------------------------------------------------------------------===// FunctionCatalogEntry() = default; - FunctionCatalogEntry( - CatalogEntryType entryType, std::string name, function::function_set functionSet); + FunctionCatalogEntry(CatalogEntryType entryType, std::string name, + function::function_set functionSet); //===--------------------------------------------------------------------===// // getters & setters diff --git a/src/include/catalog/catalog_entry/node_table_catalog_entry.h b/src/include/catalog/catalog_entry/node_table_catalog_entry.h index 29903debae9..7cd6ebef09d 100644 --- a/src/include/catalog/catalog_entry/node_table_catalog_entry.h +++ b/src/include/catalog/catalog_entry/node_table_catalog_entry.h @@ -11,8 +11,8 @@ class NodeTableCatalogEntry final : public TableCatalogEntry { // constructors //===--------------------------------------------------------------------===// NodeTableCatalogEntry() = default; - NodeTableCatalogEntry( - std::string name, common::table_id_t tableID, common::property_id_t primaryKeyPID); + NodeTableCatalogEntry(std::string name, common::table_id_t tableID, + common::property_id_t primaryKeyPID); NodeTableCatalogEntry(const NodeTableCatalogEntry& other); //===--------------------------------------------------------------------===// diff --git a/src/include/catalog/catalog_entry/rel_table_catalog_entry.h b/src/include/catalog/catalog_entry/rel_table_catalog_entry.h index 5fedd1dc5bd..7fa776b4bc7 100644 --- a/src/include/catalog/catalog_entry/rel_table_catalog_entry.h +++ b/src/include/catalog/catalog_entry/rel_table_catalog_entry.h @@ -23,6 +23,7 @@ class RelTableCatalogEntry final : public TableCatalogEntry { //===--------------------------------------------------------------------===// bool isParent(common::table_id_t tableID) override; common::TableType getTableType() const override { return common::TableType::REL; } + common::column_id_t getColumnID(common::property_id_t propertyID) const override; common::table_id_t getSrcTableID() const { return srcTableID; } common::table_id_t getDstTableID() const { return dstTableID; } bool isSingleMultiplicity(common::RelDataDirection direction) const; diff --git a/src/include/catalog/catalog_entry/scalar_function_catalog_entry.h b/src/include/catalog/catalog_entry/scalar_function_catalog_entry.h deleted file mode 100644 index 90470208ff1..00000000000 --- a/src/include/catalog/catalog_entry/scalar_function_catalog_entry.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "catalog_entry.h" -#include "function_catalog_entry.h" - -namespace kuzu { -namespace catalog { - -class ScalarFunctionCatalogEntry final : public FunctionCatalogEntry { -public: - //===--------------------------------------------------------------------===// - // constructors - //===--------------------------------------------------------------------===// - ScalarFunctionCatalogEntry() = default; - ScalarFunctionCatalogEntry(std::string name, function::function_set functionSet); - - //===--------------------------------------------------------------------===// - // serialization & deserialization - //===--------------------------------------------------------------------===// - std::unique_ptr copy() const override; -}; - -} // namespace catalog -} // namespace kuzu diff --git a/src/include/catalog/catalog_entry/scalar_macro_catalog_entry.h b/src/include/catalog/catalog_entry/scalar_macro_catalog_entry.h index c211164d954..706d0f2c8dc 100644 --- a/src/include/catalog/catalog_entry/scalar_macro_catalog_entry.h +++ b/src/include/catalog/catalog_entry/scalar_macro_catalog_entry.h @@ -12,8 +12,8 @@ class ScalarMacroCatalogEntry final : public CatalogEntry { // constructors //===--------------------------------------------------------------------===// ScalarMacroCatalogEntry() = default; - ScalarMacroCatalogEntry( - std::string name, std::unique_ptr macroFunction); + ScalarMacroCatalogEntry(std::string name, + std::unique_ptr macroFunction); //===--------------------------------------------------------------------===// // getter & setter diff --git a/src/include/catalog/catalog_entry/table_catalog_entry.h b/src/include/catalog/catalog_entry/table_catalog_entry.h index e3c0ba6d283..cec2160eb6a 100644 --- a/src/include/catalog/catalog_entry/table_catalog_entry.h +++ b/src/include/catalog/catalog_entry/table_catalog_entry.h @@ -5,11 +5,12 @@ #include "catalog/property.h" #include "catalog_entry.h" #include "common/enums/table_type.h" +#include "function/table_functions.h" namespace kuzu { namespace catalog { -class TableCatalogEntry : public CatalogEntry { +class KUZU_API TableCatalogEntry : public CatalogEntry { public: //===--------------------------------------------------------------------===// // constructors @@ -19,7 +20,8 @@ class TableCatalogEntry : public CatalogEntry { : CatalogEntry{catalogType, std::move(name)}, tableID{tableID}, nextPID{0} {} TableCatalogEntry(const TableCatalogEntry& other) : CatalogEntry{other}, tableID{other.tableID}, comment{other.comment}, - nextPID{other.nextPID}, properties{other.properties} {} + nextPID{other.nextPID}, properties{copyVector(other.properties)} {} + TableCatalogEntry& operator=(const TableCatalogEntry&) = delete; //===--------------------------------------------------------------------===// // getter & setter @@ -27,9 +29,10 @@ class TableCatalogEntry : public CatalogEntry { common::table_id_t getTableID() const { return tableID; } std::string getComment() const { return comment; } void setComment(std::string newComment) { comment = std::move(newComment); } - virtual bool isParent(common::table_id_t tableID) = 0; + virtual bool isParent(common::table_id_t /*tableID*/) { return false; }; // TODO(Guodong/Ziyi): This function should be removed. Instead we should use CatalogEntryType. virtual common::TableType getTableType() const = 0; + virtual function::TableFunction getScanFunction() { KU_UNREACHABLE; } //===--------------------------------------------------------------------===// // properties functions @@ -39,7 +42,7 @@ class TableCatalogEntry : public CatalogEntry { bool containProperty(const std::string& propertyName) const; common::property_id_t getPropertyID(const std::string& propertyName) const; const Property* getProperty(common::property_id_t propertyID) const; - common::column_id_t getColumnID(common::property_id_t propertyID) const; + virtual common::column_id_t getColumnID(common::property_id_t propertyID) const; bool containPropertyType(const common::LogicalType& logicalType) const; void addProperty(std::string propertyName, std::unique_ptr dataType); void dropProperty(common::property_id_t propertyID); @@ -49,10 +52,10 @@ class TableCatalogEntry : public CatalogEntry { // serialization & deserialization //===--------------------------------------------------------------------===// void serialize(common::Serializer& serializer) const override; - static std::unique_ptr deserialize( - common::Deserializer& deserializer, CatalogEntryType type); + static std::unique_ptr deserialize(common::Deserializer& deserializer, + CatalogEntryType type); -private: +protected: common::table_id_t tableID; std::string comment; common::property_id_t nextPID; diff --git a/src/include/catalog/catalog_entry/table_function_catalog_entry.h b/src/include/catalog/catalog_entry/table_function_catalog_entry.h deleted file mode 100644 index ba5b8e9d5d9..00000000000 --- a/src/include/catalog/catalog_entry/table_function_catalog_entry.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "function_catalog_entry.h" - -namespace kuzu { -namespace catalog { - -class TableFunctionCatalogEntry : public FunctionCatalogEntry { -public: - //===--------------------------------------------------------------------===// - // constructors - //===--------------------------------------------------------------------===// - TableFunctionCatalogEntry() = default; - TableFunctionCatalogEntry(std::string name, function::function_set functionSet); - - //===--------------------------------------------------------------------===// - // serialization & deserialization - //===--------------------------------------------------------------------===// - std::unique_ptr copy() const override; -}; - -} // namespace catalog -} // namespace kuzu diff --git a/src/include/catalog/catalog_set.h b/src/include/catalog/catalog_set.h index 1850c18548b..367dbbfa69b 100644 --- a/src/include/catalog/catalog_set.h +++ b/src/include/catalog/catalog_set.h @@ -2,7 +2,6 @@ #include "catalog_entry/catalog_entry.h" #include "common/case_insensitive_map.h" -#include "common/serializer/serializer.h" namespace kuzu { namespace catalog { @@ -14,7 +13,7 @@ class CatalogSet { //===--------------------------------------------------------------------===// bool containsEntry(const std::string& name) const; CatalogEntry* getEntry(const std::string& name); - void createEntry(std::unique_ptr entry); + KUZU_API void createEntry(std::unique_ptr entry); void removeEntry(const std::string& name); void renameEntry(const std::string& oldName, const std::string& newName); common::case_insensitive_map_t>& getEntries() { return entries; } diff --git a/src/include/catalog/property.h b/src/include/catalog/property.h index 9d116b5ec15..238fc9d4780 100644 --- a/src/include/catalog/property.h +++ b/src/include/catalog/property.h @@ -18,11 +18,8 @@ class Property { common::INVALID_TABLE_ID} {} Property(std::string name, std::unique_ptr dataType, common::property_id_t propertyID, common::table_id_t tableID) - : name{std::move(name)}, dataType{std::move(dataType)}, - propertyID{propertyID}, tableID{tableID} {} - Property(const Property& other) - : name{other.name}, dataType{other.dataType->copy()}, - propertyID{other.propertyID}, tableID{other.tableID} {} + : name{std::move(name)}, dataType{std::move(dataType)}, propertyID{propertyID}, + tableID{tableID} {} EXPLICIT_COPY_DEFAULT_MOVE(Property); std::string getName() const { return name; } @@ -38,8 +35,12 @@ class Property { void serialize(common::Serializer& serializer) const; static Property deserialize(common::Deserializer& deserializer); - static void toCypher( - const std::vector& properties, std::stringstream& ss); + static std::string toCypher(const std::vector& properties); + +private: + Property(const Property& other) + : name{other.name}, dataType{other.dataType->copy()}, propertyID{other.propertyID}, + tableID{other.tableID} {} private: std::string name; diff --git a/src/include/common/arrow/arrow.h b/src/include/common/arrow/arrow.h index ba480455bb2..160cfd099bd 100644 --- a/src/include/common/arrow/arrow.h +++ b/src/include/common/arrow/arrow.h @@ -54,3 +54,21 @@ struct ArrowArray { #ifdef __cplusplus } #endif + +struct ArrowSchemaWrapper : public ArrowSchema { + ArrowSchemaWrapper() { release = nullptr; } + ~ArrowSchemaWrapper() { + if (release) { + release(this); + } + } +}; + +struct ArrowArrayWrapper : public ArrowArray { + ArrowArrayWrapper() { release = nullptr; } + ~ArrowArrayWrapper() { + if (release) { + release(this); + } + } +}; diff --git a/src/include/common/arrow/arrow_converter.h b/src/include/common/arrow/arrow_converter.h index 6ec50ee25d5..9a51fa75e8b 100644 --- a/src/include/common/arrow/arrow_converter.h +++ b/src/include/common/arrow/arrow_converter.h @@ -4,6 +4,7 @@ #include #include "common/arrow/arrow.h" +#include "common/arrow/arrow_nullmask_tree.h" #include "main/query_result.h" struct ArrowSchema; @@ -23,15 +24,22 @@ struct ArrowConverter { public: static std::unique_ptr toArrowSchema( const std::vector>& typesInfo); - static void toArrowArray( - main::QueryResult& queryResult, ArrowArray* out_array, std::int64_t chunkSize); + static void toArrowArray(main::QueryResult& queryResult, ArrowArray* out_array, + std::int64_t chunkSize); + + static common::LogicalType fromArrowSchema(const ArrowSchema* schema); + static void fromArrowArray(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector, ArrowNullMaskTree* mask, uint64_t srcOffset, uint64_t dstOffset, + uint64_t count); + static void fromArrowArray(const ArrowSchema* schema, const ArrowArray* array, + ValueVector& outputVector); private: static void initializeChild(ArrowSchema& child, const std::string& name = ""); - static void setArrowFormatForStruct( - ArrowSchemaHolder& rootHolder, ArrowSchema& child, const main::DataTypeInfo& typeInfo); - static void setArrowFormat( - ArrowSchemaHolder& rootHolder, ArrowSchema& child, const main::DataTypeInfo& typeInfo); + static void setArrowFormatForStruct(ArrowSchemaHolder& rootHolder, ArrowSchema& child, + const main::DataTypeInfo& typeInfo); + static void setArrowFormat(ArrowSchemaHolder& rootHolder, ArrowSchema& child, + const main::DataTypeInfo& typeInfo); }; } // namespace common diff --git a/src/include/common/arrow/arrow_nullmask_tree.h b/src/include/common/arrow/arrow_nullmask_tree.h new file mode 100644 index 00000000000..85ea6a19a81 --- /dev/null +++ b/src/include/common/arrow/arrow_nullmask_tree.h @@ -0,0 +1,39 @@ +#pragma once + +#include "common/arrow/arrow.h" +#include "common/null_mask.h" +#include "common/vector/value_vector.h" + +namespace kuzu { +namespace common { + +class ArrowNullMaskTree { +public: + ArrowNullMaskTree(const ArrowSchema* schema, const ArrowArray* array, uint64_t srcOffset, + uint64_t count, const NullMask* parentMask = nullptr); + + void copyToValueVector(ValueVector* vec, uint64_t dstOffset, uint64_t count); + bool isNull(int64_t idx) { return mask->isNull(idx + offset); } + ArrowNullMaskTree* getChild(int idx) { return &(*children)[idx]; } + ArrowNullMaskTree* getDictionary() { return dictionary.get(); } + ArrowNullMaskTree operator+(int64_t offset); + +private: + bool copyFromBuffer(const void* buffer, uint64_t srcOffset, uint64_t count); + bool applyParentBitmap(const NullMask* buffer, uint64_t count); + + template + void scanListPushDown(const ArrowSchema* schema, const ArrowArray* array, uint64_t srcOffset, + uint64_t count); + + void scanStructPushDown(const ArrowSchema* schema, const ArrowArray* array, uint64_t srcOffset, + uint64_t count); + + int64_t offset; + std::shared_ptr mask; + std::shared_ptr> children; + std::shared_ptr dictionary; +}; + +} // namespace common +} // namespace kuzu diff --git a/src/include/common/arrow/arrow_row_batch.h b/src/include/common/arrow/arrow_row_batch.h index d73194bd57f..209a5551674 100644 --- a/src/include/common/arrow/arrow_row_batch.h +++ b/src/include/common/arrow/arrow_row_batch.h @@ -44,37 +44,37 @@ struct ArrowVector { // An arrow data chunk consisting of N rows in columnar format. class ArrowRowBatch { public: - ArrowRowBatch( - std::vector> typesInfo, std::int64_t capacity); + ArrowRowBatch(std::vector> typesInfo, + std::int64_t capacity); //! Append a data chunk to the underlying arrow array ArrowArray append(main::QueryResult& queryResult, std::int64_t chunkSize); private: - static std::unique_ptr createVector( - const main::DataTypeInfo& typeInfo, std::int64_t capacity); + static std::unique_ptr createVector(const main::DataTypeInfo& typeInfo, + std::int64_t capacity); static void appendValue(ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value); - static ArrowArray* convertVectorToArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo); - static ArrowArray* convertStructVectorToArray( - ArrowVector& vector, const main::DataTypeInfo& typeInfo); + static ArrowArray* convertVectorToArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo); + static ArrowArray* convertStructVectorToArray(ArrowVector& vector, + const main::DataTypeInfo& typeInfo); static inline void initializeNullBits(ArrowBuffer& validity, std::int64_t capacity) { auto numBytesForValidity = getNumBytesForBits(capacity); validity.resize(numBytesForValidity, 0xFF); } - static void initializeStructVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity); - static void copyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos); + static void initializeStructVector(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + std::int64_t capacity); + static void copyNonNullValue(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + Value* value, std::int64_t pos); static void copyNullValue(ArrowVector* vector, Value* value, std::int64_t pos); template - static void templateInitializeVector( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, std::int64_t capacity); + static void templateInitializeVector(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + std::int64_t capacity); template - static void templateCopyNonNullValue( - ArrowVector* vector, const main::DataTypeInfo& typeInfo, Value* value, std::int64_t pos); + static void templateCopyNonNullValue(ArrowVector* vector, const main::DataTypeInfo& typeInfo, + Value* value, std::int64_t pos); template static void templateCopyNullValue(ArrowVector* vector, std::int64_t pos); template diff --git a/src/include/common/assert.h b/src/include/common/assert.h index cc46a295016..17afa6cb600 100644 --- a/src/include/common/assert.h +++ b/src/include/common/assert.h @@ -6,11 +6,11 @@ namespace kuzu { namespace common { -[[noreturn]] inline void kuAssertFailureInternal( - const char* condition_name, const char* file, int linenr) { +[[noreturn]] inline void kuAssertFailureInternal(const char* condition_name, const char* file, + int linenr) { // LCOV_EXCL_START - throw InternalException(stringFormat( - "Assertion failed in file \"{}\" on line {}: {}", file, linenr, condition_name)); + throw InternalException(stringFormat("Assertion failed in file \"{}\" on line {}: {}", file, + linenr, condition_name)); // LCOV_EXCL_STOP } diff --git a/src/include/common/case_insensitive_map.h b/src/include/common/case_insensitive_map.h index d11ddb146dc..12e0acc2618 100644 --- a/src/include/common/case_insensitive_map.h +++ b/src/include/common/case_insensitive_map.h @@ -1,23 +1,20 @@ #pragma once +#include #include #include -#include "common/string_utils.h" +#include "common/api.h" namespace kuzu { namespace common { struct CaseInsensitiveStringHashFunction { - uint64_t operator()(const std::string& str) const { - return common::StringUtils::caseInsensitiveHash(str); - } + KUZU_API uint64_t operator()(const std::string& str) const; }; struct CaseInsensitiveStringEquality { - bool operator()(const std::string& left, const std::string& right) const { - return common::StringUtils::caseInsensitiveEquals(left, right); - } + KUZU_API bool operator()(const std::string& lhs, const std::string& rhs) const; }; template diff --git a/src/include/common/column_data_format.h b/src/include/common/column_data_format.h index 5f4b3ad8803..ebaa367658c 100644 --- a/src/include/common/column_data_format.h +++ b/src/include/common/column_data_format.h @@ -7,5 +7,5 @@ namespace common { enum class ColumnDataFormat : uint8_t { REGULAR = 0, CSR = 1 }; -} +} // namespace common } // namespace kuzu diff --git a/src/include/common/constants.h b/src/include/common/constants.h index d769cf0cb49..2a1674387ef 100644 --- a/src/include/common/constants.h +++ b/src/include/common/constants.h @@ -173,11 +173,6 @@ struct PlannerKnobs { static constexpr uint64_t SIP_RATIO = 5; }; -struct ClientContextConstants { - // We disable query timeout by default. - static constexpr uint64_t TIMEOUT_IN_MS = 0; -}; - struct OrderByConstants { static constexpr uint64_t NUM_BYTES_FOR_PAYLOAD_IDX = 8; static constexpr uint64_t MIN_SIZE_TO_REDUCE = common::DEFAULT_VECTOR_CAPACITY * 5; diff --git a/src/include/common/copier_config/csv_reader_config.h b/src/include/common/copier_config/csv_reader_config.h index 29496b212c4..60c34b2331d 100644 --- a/src/include/common/copier_config/csv_reader_config.h +++ b/src/include/common/copier_config/csv_reader_config.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "common/constants.h" #include "common/copy_constructors.h" #include "common/types/value/value.h" @@ -23,16 +21,11 @@ struct CSVOption { hasHeader{CopyConstants::DEFAULT_CSV_HAS_HEADER} {} EXPLICIT_COPY_DEFAULT_MOVE(CSVOption); + // TODO: COPY FROM and COPY TO should support transform special options, like '\'. std::string toCypher() const { - std::stringstream ss; - ss << " (escape = '\\" << escapeChar << "' , delim = '" << delimiter << "' , quote = '\\" - << quoteChar << "', header="; - if (hasHeader) { - ss << "true);"; - } else { - ss << "false);"; - } - return ss.str(); + std::string header = hasHeader ? "true" : "false"; + return stringFormat("(escape ='\\{}', delim ='{}', quote='\\{}', header={})", escapeChar, + delimiter, quoteChar, header); } private: diff --git a/src/include/common/copier_config/reader_config.h b/src/include/common/copier_config/reader_config.h index 1b2d187e99b..3fc5c81b76d 100644 --- a/src/include/common/copier_config/reader_config.h +++ b/src/include/common/copier_config/reader_config.h @@ -30,6 +30,7 @@ struct ReaderConfig { std::vector filePaths; std::unordered_map options; + ReaderConfig() = default; ReaderConfig(FileType fileType, std::vector filePaths) : fileType{fileType}, filePaths{std::move(filePaths)} {} EXPLICIT_COPY_DEFAULT_MOVE(ReaderConfig); diff --git a/src/include/common/copy_constructors.h b/src/include/common/copy_constructors.h index cbeebf544bc..7db4d6bc68b 100644 --- a/src/include/common/copy_constructors.h +++ b/src/include/common/copy_constructors.h @@ -27,7 +27,9 @@ DEFAULT_MOVE_ASSN(Object) #define EXPLICIT_COPY_METHOD(Object) \ - Object copy() const { return *this; } + Object copy() const { \ + return *this; \ + } // EXPLICIT_COPY_DEFAULT_MOVE should be the default choice. It expects a PRIVATE copy constructor to // be defined, which will be used by an explicit `copy()` method. For instance: diff --git a/src/include/common/data_chunk/data_chunk_collection.h b/src/include/common/data_chunk/data_chunk_collection.h index e6b0aa89e9f..e3d6db14938 100644 --- a/src/include/common/data_chunk/data_chunk_collection.h +++ b/src/include/common/data_chunk/data_chunk_collection.h @@ -5,36 +5,40 @@ namespace kuzu { namespace common { -// TODO(Guodong/Ziyi): We should extend this to ColumnDataCollection, which takes ResultSet into -// consideration for storage and scan. +// TODO(Guodong): Should rework this to use ColumnChunk. class DataChunkCollection { public: explicit DataChunkCollection(storage::MemoryManager* mm); + DELETE_COPY_DEFAULT_MOVE(DataChunkCollection); void append(DataChunk& chunk); - void append(std::unique_ptr chunk); - std::vector getChunks() const; - + inline const std::vector& getChunks() const { return chunks; } + inline std::vector& getChunksUnsafe() { return chunks; } inline uint64_t getNumChunks() const { return chunks.size(); } - inline DataChunk* getChunk(uint64_t idx) const { + inline const DataChunk& getChunk(uint64_t idx) const { + KU_ASSERT(idx < chunks.size()); + return chunks[idx]; + } + inline DataChunk& getChunkUnsafe(uint64_t idx) { KU_ASSERT(idx < chunks.size()); - return chunks[idx].get(); + return chunks[idx]; } inline void merge(DataChunkCollection* other) { for (auto& chunk : other->chunks) { - append(std::move(chunk)); + merge(std::move(chunk)); } } + void merge(DataChunk chunk); private: - DataChunk* allocateChunk(DataChunk& chunk); + void allocateChunk(DataChunk& chunk); void initTypes(DataChunk& chunk); private: storage::MemoryManager* mm; std::vector types; - std::vector> chunks; + std::vector chunks; }; } // namespace common diff --git a/src/include/common/data_chunk/sel_vector.h b/src/include/common/data_chunk/sel_vector.h index 9b386d4bd70..78517b20d14 100644 --- a/src/include/common/data_chunk/sel_vector.h +++ b/src/include/common/data_chunk/sel_vector.h @@ -11,27 +11,23 @@ class SelectionVector { public: explicit SelectionVector(sel_t capacity) : selectedSize{0} { selectedPositionsBuffer = std::make_unique(capacity); - resetSelectorToUnselected(); + setToUnfiltered(); } - inline bool isUnfiltered() const { - return selectedPositions == (sel_t*)&INCREMENTAL_SELECTED_POS; - } - inline void resetSelectorToUnselected() { - selectedPositions = (sel_t*)&INCREMENTAL_SELECTED_POS; - } - inline void resetSelectorToUnselectedWithSize(sel_t size) { + bool isUnfiltered() const { return selectedPositions == (sel_t*)&INCREMENTAL_SELECTED_POS; } + void setToUnfiltered() { selectedPositions = (sel_t*)&INCREMENTAL_SELECTED_POS; } + void setToUnfiltered(sel_t size) { selectedPositions = (sel_t*)&INCREMENTAL_SELECTED_POS; selectedSize = size; } - inline void resetSelectorToValuePosBuffer() { - selectedPositions = selectedPositionsBuffer.get(); - } - inline void resetSelectorToValuePosBufferWithSize(sel_t size) { + + // Set to filtered is not very accurate. It sets selectedPositions to a mutable array. + void setToFiltered() { selectedPositions = selectedPositionsBuffer.get(); } + void setToFiltered(sel_t size) { selectedPositions = selectedPositionsBuffer.get(); selectedSize = size; } - inline sel_t* getSelectedPositionsBuffer() { return selectedPositionsBuffer.get(); } + sel_t* getMultableBuffer() { return selectedPositionsBuffer.get(); } KUZU_API static const sel_t INCREMENTAL_SELECTED_POS[DEFAULT_VECTOR_CAPACITY]; diff --git a/src/include/common/enums/expression_type.h b/src/include/common/enums/expression_type.h index 3cca4be2c09..50c4f5e9c6a 100644 --- a/src/include/common/enums/expression_type.h +++ b/src/include/common/enums/expression_type.h @@ -6,258 +6,6 @@ namespace kuzu { namespace common { -/** - * Function name is a temporary identifier used for binder because grammar does not parse built in - * functions. After binding, expression type should replace function name and used as identifier. - */ -// aggregate -const char* const COUNT_STAR_FUNC_NAME = "COUNT_STAR"; -const char* const COUNT_FUNC_NAME = "COUNT"; -const char* const SUM_FUNC_NAME = "SUM"; -const char* const AVG_FUNC_NAME = "AVG"; -const char* const MIN_FUNC_NAME = "MIN"; -const char* const MAX_FUNC_NAME = "MAX"; -const char* const COLLECT_FUNC_NAME = "COLLECT"; - -// cast -const char* const CAST_FUNC_NAME = "CAST"; -const char* const CAST_DATE_FUNC_NAME = "DATE"; -const char* const CAST_TO_DATE_FUNC_NAME = "TO_DATE"; -const char* const CAST_TO_TIMESTAMP_FUNC_NAME = "TIMESTAMP"; -const char* const CAST_INTERVAL_FUNC_NAME = "INTERVAL"; -const char* const CAST_TO_INTERVAL_FUNC_NAME = "TO_INTERVAL"; -const char* const CAST_STRING_FUNC_NAME = "STRING"; -const char* const CAST_TO_STRING_FUNC_NAME = "TO_STRING"; -const char* const CAST_TO_DOUBLE_FUNC_NAME = "TO_DOUBLE"; -const char* const CAST_TO_FLOAT_FUNC_NAME = "TO_FLOAT"; -const char* const CAST_TO_SERIAL_FUNC_NAME = "TO_SERIAL"; -const char* const CAST_TO_INT64_FUNC_NAME = "TO_INT64"; -const char* const CAST_TO_INT32_FUNC_NAME = "TO_INT32"; -const char* const CAST_TO_INT16_FUNC_NAME = "TO_INT16"; -const char* const CAST_TO_INT8_FUNC_NAME = "TO_INT8"; -const char* const CAST_TO_UINT64_FUNC_NAME = "TO_UINT64"; -const char* const CAST_TO_UINT32_FUNC_NAME = "TO_UINT32"; -const char* const CAST_TO_UINT16_FUNC_NAME = "TO_UINT16"; -const char* const CAST_TO_UINT8_FUNC_NAME = "TO_UINT8"; -const char* const CAST_BLOB_FUNC_NAME = "BLOB"; -const char* const CAST_TO_BLOB_FUNC_NAME = "TO_BLOB"; -const char* const CAST_UUID_FUNC_NAME = "UUID"; -const char* const CAST_TO_UUID_FUNC_NAME = "TO_UUID"; -const char* const CAST_TO_BOOL_FUNC_NAME = "TO_BOOL"; -const char* const CAST_TO_INT128_FUNC_NAME = "TO_INT128"; - -// list -const char* const LIST_CREATION_FUNC_NAME = "LIST_CREATION"; -const char* const LIST_RANGE_FUNC_NAME = "RANGE"; -const char* const LIST_EXTRACT_FUNC_NAME = "LIST_EXTRACT"; -const char* const LIST_ELEMENT_FUNC_NAME = "LIST_ELEMENT"; -const char* const LIST_CONCAT_FUNC_NAME = "LIST_CONCAT"; -const char* const LIST_CAT_FUNC_NAME = "LIST_CAT"; -const char* const ARRAY_CONCAT_FUNC_NAME = "ARRAY_CONCAT"; -const char* const ARRAY_CAT_FUNC_NAME = "ARRAY_CAT"; -const char* const LIST_APPEND_FUNC_NAME = "LIST_APPEND"; -const char* const ARRAY_APPEND_FUNC_NAME = "ARRAY_APPEND"; -const char* const ARRAY_PUSH_BACK_FUNC_NAME = "ARRAY_PUSH_BACK"; -const char* const LIST_PREPEND_FUNC_NAME = "LIST_PREPEND"; -const char* const ARRAY_PREPEND_FUNC_NAME = "ARRAY_PREPEND"; -const char* const ARRAY_PUSH_FRONT_FUNC_NAME = "ARRAY_PUSH_FRONT"; -const char* const LIST_POSITION_FUNC_NAME = "LIST_POSITION"; -const char* const LIST_INDEXOF_FUNC_NAME = "LIST_INDEXOF"; -const char* const ARRAY_POSITION_FUNC_NAME = "ARRAY_POSITION"; -const char* const ARRAY_INDEXOF_FUNC_NAME = "ARRAY_INDEXOF"; -const char* const LIST_CONTAINS_FUNC_NAME = "LIST_CONTAINS"; -const char* const LIST_HAS_FUNC_NAME = "LIST_HAS"; -const char* const ARRAY_CONTAINS_FUNC_NAME = "ARRAY_CONTAINS"; -const char* const ARRAY_HAS_FUNC_NAME = "ARRAY_HAS"; -const char* const LIST_SLICE_FUNC_NAME = "LIST_SLICE"; -const char* const ARRAY_SLICE_FUNC_NAME = "ARRAY_SLICE"; -const char* const LIST_SUM_FUNC_NAME = "LIST_SUM"; -const char* const LIST_PRODUCT_FUNC_NAME = "LIST_PRODUCT"; -const char* const LIST_SORT_FUNC_NAME = "LIST_SORT"; -const char* const LIST_REVERSE_SORT_FUNC_NAME = "LIST_REVERSE_SORT"; -const char* const LIST_DISTINCT_FUNC_NAME = "LIST_DISTINCT"; -const char* const LIST_UNIQUE_FUNC_NAME = "LIST_UNIQUE"; -const char* const LIST_ANY_VALUE_FUNC_NAME = "LIST_ANY_VALUE"; -const char* const LIST_REVERSE_FUNC_NAME = "LIST_REVERSE"; - -// struct -const char* const STRUCT_PACK_FUNC_NAME = "STRUCT_PACK"; -const char* const STRUCT_EXTRACT_FUNC_NAME = "STRUCT_EXTRACT"; - -// map -const char* const MAP_CREATION_FUNC_NAME = "MAP"; -const char* const MAP_EXTRACT_FUNC_NAME = "MAP_EXTRACT"; -const char* const ELEMENT_AT_FUNC_NAME = "ELEMENT_AT"; // alias of MAP_EXTRACT -const char* const CARDINALITY_FUNC_NAME = "CARDINALITY"; -const char* const MAP_KEYS_FUNC_NAME = "MAP_KEYS"; -const char* const MAP_VALUES_FUNC_NAME = "MAP_VALUES"; - -// union -const char* const UNION_VALUE_FUNC_NAME = "UNION_VALUE"; -const char* const UNION_TAG_FUNC_NAME = "UNION_TAG"; -const char* const UNION_EXTRACT_FUNC_NAME = "UNION_EXTRACT"; - -// comparison -const char* const EQUALS_FUNC_NAME = "EQUALS"; -const char* const NOT_EQUALS_FUNC_NAME = "NOT_EQUALS"; -const char* const GREATER_THAN_FUNC_NAME = "GREATER_THAN"; -const char* const GREATER_THAN_EQUALS_FUNC_NAME = "GREATER_THAN_EQUALS"; -const char* const LESS_THAN_FUNC_NAME = "LESS_THAN"; -const char* const LESS_THAN_EQUALS_FUNC_NAME = "LESS_THAN_EQUALS"; - -// arithmetics operators -const char* const ADD_FUNC_NAME = "+"; -const char* const SUBTRACT_FUNC_NAME = "-"; -const char* const MULTIPLY_FUNC_NAME = "*"; -const char* const DIVIDE_FUNC_NAME = "/"; -const char* const MODULO_FUNC_NAME = "%"; -const char* const POWER_FUNC_NAME = "^"; - -// arithmetics functions -const char* const ABS_FUNC_NAME = "ABS"; -const char* const ACOS_FUNC_NAME = "ACOS"; -const char* const ASIN_FUNC_NAME = "ASIN"; -const char* const ATAN_FUNC_NAME = "ATAN"; -const char* const ATAN2_FUNC_NAME = "ATAN2"; -const char* const BITWISE_XOR_FUNC_NAME = "BITWISE_XOR"; -const char* const BITWISE_AND_FUNC_NAME = "BITWISE_AND"; -const char* const BITWISE_OR_FUNC_NAME = "BITWISE_OR"; -const char* const BITSHIFT_LEFT_FUNC_NAME = "BITSHIFT_LEFT"; -const char* const BITSHIFT_RIGHT_FUNC_NAME = "BITSHIFT_RIGHT"; -const char* const CBRT_FUNC_NAME = "CBRT"; -const char* const CEIL_FUNC_NAME = "CEIL"; -const char* const CEILING_FUNC_NAME = "CEILING"; -const char* const COS_FUNC_NAME = "COS"; -const char* const COT_FUNC_NAME = "COT"; -const char* const DEGREES_FUNC_NAME = "DEGREES"; -const char* const EVEN_FUNC_NAME = "EVEN"; -const char* const FACTORIAL_FUNC_NAME = "FACTORIAL"; -const char* const FLOOR_FUNC_NAME = "FLOOR"; -const char* const GAMMA_FUNC_NAME = "GAMMA"; -const char* const LGAMMA_FUNC_NAME = "LGAMMA"; -const char* const LN_FUNC_NAME = "LN"; -const char* const LOG_FUNC_NAME = "LOG"; -const char* const LOG2_FUNC_NAME = "LOG2"; -const char* const LOG10_FUNC_NAME = "LOG10"; -const char* const NEGATE_FUNC_NAME = "NEGATE"; -const char* const PI_FUNC_NAME = "PI"; -const char* const POW_FUNC_NAME = "POW"; -const char* const RADIANS_FUNC_NAME = "RADIANS"; -const char* const ROUND_FUNC_NAME = "ROUND"; -const char* const SIN_FUNC_NAME = "SIN"; -const char* const SIGN_FUNC_NAME = "SIGN"; -const char* const SQRT_FUNC_NAME = "SQRT"; -const char* const TAN_FUNC_NAME = "TAN"; - -// string -const char* const ARRAY_EXTRACT_FUNC_NAME = "ARRAY_EXTRACT"; -const char* const CONCAT_FUNC_NAME = "CONCAT"; -const char* const CONTAINS_FUNC_NAME = "CONTAINS"; -const char* const ENDS_WITH_FUNC_NAME = "ENDS_WITH"; -const char* const LCASE_FUNC_NAME = "LCASE"; -const char* const LEFT_FUNC_NAME = "LEFT"; -const char* const LENGTH_FUNC_NAME = "LENGTH"; -const char* const LOWER_FUNC_NAME = "LOWER"; -const char* const LPAD_FUNC_NAME = "LPAD"; -const char* const LTRIM_FUNC_NAME = "LTRIM"; -const char* const PREFIX_FUNC_NAME = "PREFIX"; -const char* const REPEAT_FUNC_NAME = "REPEAT"; -const char* const REVERSE_FUNC_NAME = "REVERSE"; -const char* const RIGHT_FUNC_NAME = "RIGHT"; -const char* const RPAD_FUNC_NAME = "RPAD"; -const char* const RTRIM_FUNC_NAME = "RTRIM"; -const char* const STARTS_WITH_FUNC_NAME = "STARTS_WITH"; -const char* const SUBSTR_FUNC_NAME = "SUBSTR"; -const char* const SUBSTRING_FUNC_NAME = "SUBSTRING"; -const char* const SUFFIX_FUNC_NAME = "SUFFIX"; -const char* const TRIM_FUNC_NAME = "TRIM"; -const char* const UCASE_FUNC_NAME = "UCASE"; -const char* const UPPER_FUNC_NAME = "UPPER"; -const char* const REGEXP_FULL_MATCH_FUNC_NAME = "REGEXP_FULL_MATCH"; -const char* const REGEXP_MATCHES_FUNC_NAME = "REGEXP_MATCHES"; -const char* const REGEXP_REPLACE_FUNC_NAME = "REGEXP_REPLACE"; -const char* const REGEXP_EXTRACT_FUNC_NAME = "REGEXP_EXTRACT"; -const char* const REGEXP_EXTRACT_ALL_FUNC_NAME = "REGEXP_EXTRACT_ALL"; -const char* const SIZE_FUNC_NAME = "SIZE"; -const char* const LEVENSHTEIN_FUNC_NAME = "LEVENSHTEIN"; - -// Date functions. -const char* const DATE_PART_FUNC_NAME = "DATE_PART"; -const char* const DATEPART_FUNC_NAME = "DATEPART"; -const char* const DATE_TRUNC_FUNC_NAME = "DATE_TRUNC"; -const char* const DATETRUNC_FUNC_NAME = "DATETRUNC"; -const char* const DAYNAME_FUNC_NAME = "DAYNAME"; -const char* const GREATEST_FUNC_NAME = "GREATEST"; -const char* const LAST_DAY_FUNC_NAME = "LAST_DAY"; -const char* const LEAST_FUNC_NAME = "LEAST"; -const char* const MAKE_DATE_FUNC_NAME = "MAKE_DATE"; -const char* const MONTHNAME_FUNC_NAME = "MONTHNAME"; - -// Timestamp functions. -const char* const CENTURY_FUNC_NAME = "CENTURY"; -const char* const EPOCH_MS_FUNC_NAME = "EPOCH_MS"; -const char* const TO_TIMESTAMP_FUNC_NAME = "TO_TIMESTAMP"; - -// Interval functions. -const char* const TO_YEARS_FUNC_NAME = "TO_YEARS"; -const char* const TO_MONTHS_FUNC_NAME = "TO_MONTHS"; -const char* const TO_DAYS_FUNC_NAME = "TO_DAYS"; -const char* const TO_HOURS_FUNC_NAME = "TO_HOURS"; -const char* const TO_MINUTES_FUNC_NAME = "TO_MINUTES"; -const char* const TO_SECONDS_FUNC_NAME = "TO_SECONDS"; -const char* const TO_MILLISECONDS_FUNC_NAME = "TO_MILLISECONDS"; -const char* const TO_MICROSECONDS_FUNC_NAME = "TO_MICROSECONDS"; - -// Node/Rel functions. -const char* const ID_FUNC_NAME = "ID"; -const char* const LABEL_FUNC_NAME = "LABEL"; -const char* const OFFSET_FUNC_NAME = "OFFSET"; -const char* const START_NODE_FUNC_NAME = "START_NODE"; -const char* const END_NODE_FUNC_NAME = "END_NODE"; - -// Path functions -const char* const NODES_FUNC_NAME = "NODES"; -const char* const RELS_FUNC_NAME = "RELS"; -const char* const PROPERTIES_FUNC_NAME = "PROPERTIES"; -const char* const IS_TRAIL_FUNC_NAME = "IS_TRAIL"; -const char* const IS_ACYCLIC_FUNC_NAME = "IS_ACYCLIC"; - -// Blob functions -const char* const OCTET_LENGTH_FUNC_NAME = "OCTET_LENGTH"; -const char* const ENCODE_FUNC_NAME = "ENCODE"; -const char* const DECODE_FUNC_NAME = "DECODE"; - -// UUID functions -const char* const GEN_RANDOM_UUID_FUNC_NAME = "GEN_RANDOM_UUID"; - -// RDF functions -const char* const TYPE_FUNC_NAME = "TYPE"; -const char* const VALIDATE_PREDICATE_FUNC_NAME = "VALIDATE_PREDICATE"; - -// Table functions -const char* const TABLE_INFO_FUNC_NAME = "TABLE_INFO"; -const char* const DB_VERSION_FUNC_NAME = "DB_VERSION"; -const char* const CURRENT_SETTING_FUNC_NAME = "CURRENT_SETTING"; -const char* const SHOW_TABLES_FUNC_NAME = "SHOW_TABLES"; -const char* const SHOW_CONNECTION_FUNC_NAME = "SHOW_CONNECTION"; -const char* const STORAGE_INFO_FUNC_NAME = "STORAGE_INFO"; -// Table functions - read functions -const char* const READ_PARQUET_FUNC_NAME = "READ_PARQUET"; -const char* const READ_NPY_FUNC_NAME = "READ_NPY"; -const char* const READ_CSV_SERIAL_FUNC_NAME = "READ_CSV_SERIAL"; -const char* const READ_CSV_PARALLEL_FUNC_NAME = "READ_CSV_PARALLEL"; -const char* const READ_RDF_RESOURCE_FUNC_NAME = "READ_RDF_RESOURCE"; -const char* const READ_RDF_LITERAL_FUNC_NAME = "READ_RDF_LITERAL"; -const char* const READ_RDF_RESOURCE_TRIPLE_FUNC_NAME = "READ_RDF_RESOURCE_TRIPLE"; -const char* const READ_RDF_LITERAL_TRIPLE_FUNC_NAME = "READ_RDF_LITERAL_TRIPLE"; -const char* const READ_RDF_ALL_TRIPLE_FUNC_NAME = "READ_RDF_ALL_TRIPLE"; -const char* const IN_MEM_READ_RDF_RESOURCE_FUNC_NAME = "IN_MEM_READ_RDF_RESOURCE"; -const char* const IN_MEM_READ_RDF_LITERAL_FUNC_NAME = "IN_MEM_READ_RDF_LITERAL"; -const char* const IN_MEM_READ_RDF_RESOURCE_TRIPLE_FUNC_NAME = "IN_MEM_READ_RDF_RESOURCE_TRIPLE"; -const char* const IN_MEM_READ_RDF_LITERAL_TRIPLE_FUNC_NAME = "IN_MEM_READ_RDF_LITERAL_TRIPLE"; -const char* const READ_PANDAS_FUNC_NAME = "READ_PANDAS"; -const char* const READ_FTABLE_FUNC_NAME = "READ_FTABLE"; - enum class ExpressionType : uint8_t { // Boolean Connection Expressions diff --git a/src/include/common/enums/scan_source_type.h b/src/include/common/enums/scan_source_type.h new file mode 100644 index 00000000000..90468f57a17 --- /dev/null +++ b/src/include/common/enums/scan_source_type.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace kuzu { +namespace common { + +enum class ScanSourceType : uint8_t { + EMPTY = 0, + FILE = 1, + OBJECT = 2, + QUERY = 3, +}; + +} +} // namespace kuzu diff --git a/src/include/common/enums/statement_type.h b/src/include/common/enums/statement_type.h index ac439eb70f0..6bc13472b90 100644 --- a/src/include/common/enums/statement_type.h +++ b/src/include/common/enums/statement_type.h @@ -20,6 +20,8 @@ enum class StatementType : uint8_t { EXTENSION = 31, EXPORT_DATABASE = 32, IMPORT_DATABASE = 33, + ATTACH_DATABASE = 34, + DETACH_DATABASE = 35, }; struct StatementTypeUtils { diff --git a/src/include/common/enums/table_type.h b/src/include/common/enums/table_type.h index eab71d76fd2..b41d9137418 100644 --- a/src/include/common/enums/table_type.h +++ b/src/include/common/enums/table_type.h @@ -13,6 +13,7 @@ enum class TableType : uint8_t { REL = 2, RDF = 3, REL_GROUP = 4, + FOREIGN = 5, }; struct TableTypeUtils { diff --git a/src/include/common/exception/message.h b/src/include/common/exception/message.h index bf6cd9bb301..99028d515fc 100644 --- a/src/include/common/exception/message.h +++ b/src/include/common/exception/message.h @@ -6,33 +6,25 @@ namespace kuzu { namespace common { +// Add exception only if you need to throw it in multiple places. struct ExceptionMessage { + // Primary key. static std::string duplicatePKException(const std::string& pkString); static std::string nonExistentPKException(const std::string& pkString); static std::string invalidPKType(const std::string& type); - static inline std::string nullPKException() { - return "Found NULL, which violates the non-null constraint of the primary key column."; - } - static inline std::string notAllowCopyOnNonEmptyTableException() { - return "COPY commands can only be executed once on a table."; - } + static std::string nullPKException(); + // Bulk insertion. + static std::string notAllowCopyOnNonEmptyTableException(); + // Long string. static std::string overLargeStringPKValueException(uint64_t length); static std::string overLargeStringValueException(uint64_t length); - static std::string violateDeleteNodeWithConnectedEdgesConstraint( - const std::string& tableName, const std::string& offset, const std::string& direction); - static std::string violateRelMultiplicityConstraint( - const std::string& tableName, const std::string& offset, const std::string& direction); - - static inline std::string validateCopyNPYByColumnException() { - return "Please use COPY FROM BY COLUMN statement for copying npy files."; - } - static inline std::string validateCopyCSVParquetByColumnException() { - return "Please use COPY FROM statement for copying csv and parquet files."; - } - static inline std::string validateCopyToCSVParquetExtensionsException() { - return "COPY TO currently only supports csv and parquet files."; - } - static std::string validateCopyNpyNotForRelTablesException(const std::string& tableName); + // Foreign key. + static std::string violateDeleteNodeWithConnectedEdgesConstraint(const std::string& tableName, + const std::string& offset, const std::string& direction); + static std::string violateRelMultiplicityConstraint(const std::string& tableName, + const std::string& offset, const std::string& direction); + // Binding exception + static std::string variableNotInScope(const std::string& varName); }; } // namespace common diff --git a/src/include/common/file_system/file_system.h b/src/include/common/file_system/file_system.h index dce4f2c0db1..89a2b27a082 100644 --- a/src/include/common/file_system/file_system.h +++ b/src/include/common/file_system/file_system.h @@ -24,17 +24,21 @@ class KUZU_API FileSystem { virtual std::unique_ptr openFile(const std::string& path, int flags, main::ClientContext* context = nullptr, FileLockType lock_type = FileLockType::NO_LOCK) = 0; - virtual std::vector glob( - main::ClientContext* context, const std::string& path) const = 0; + virtual std::vector glob(main::ClientContext* context, + const std::string& path) const = 0; virtual void overwriteFile(const std::string& from, const std::string& to) const; + virtual void copyFile(const std::string& from, const std::string& to) const; + virtual void createDir(const std::string& dir) const; virtual void removeFileIfExists(const std::string& path) const; virtual bool fileOrPathExists(const std::string& path) const; + virtual std::string expandPath(main::ClientContext* context, const std::string& path) const; + static std::string joinPath(const std::string& base, const std::string& part); static std::string getFileExtension(const std::filesystem::path& path); @@ -42,13 +46,13 @@ class KUZU_API FileSystem { virtual bool canHandleFile(const std::string& /*path*/) const { KU_UNREACHABLE; } protected: - virtual void readFromFile( - FileInfo* fileInfo, void* buffer, uint64_t numBytes, uint64_t position) const = 0; + virtual void readFromFile(FileInfo* fileInfo, void* buffer, uint64_t numBytes, + uint64_t position) const = 0; virtual int64_t readFile(FileInfo* fileInfo, void* buf, size_t nbyte) const = 0; - virtual void writeFile( - FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, uint64_t offset) const; + virtual void writeFile(FileInfo* fileInfo, const uint8_t* buffer, uint64_t numBytes, + uint64_t offset) const; virtual int64_t seek(FileInfo* fileInfo, uint64_t offset, int whence) const = 0; diff --git a/src/include/common/file_system/local_file_system.h b/src/include/common/file_system/local_file_system.h index caad85db2b5..f34ec930ed2 100644 --- a/src/include/common/file_system/local_file_system.h +++ b/src/include/common/file_system/local_file_system.h @@ -31,20 +31,24 @@ class LocalFileSystem final : public FileSystem { main::ClientContext* context = nullptr, FileLockType lock_type = FileLockType::NO_LOCK) override; - std::vector glob( - main::ClientContext* context, const std::string& path) const override; + std::vector glob(main::ClientContext* context, + const std::string& path) const override; void overwriteFile(const std::string& from, const std::string& to) const override; + void copyFile(const std::string& from, const std::string& to) const override; + void createDir(const std::string& dir) const override; void removeFileIfExists(const std::string& path) const override; bool fileOrPathExists(const std::string& path) const override; + std::string expandPath(main::ClientContext* context, const std::string& path) const override; + protected: - void readFromFile( - FileInfo* fileInfo, void* buffer, uint64_t numBytes, uint64_t position) const override; + void readFromFile(FileInfo* fileInfo, void* buffer, uint64_t numBytes, + uint64_t position) const override; int64_t readFile(FileInfo* fileInfo, void* buf, size_t nbyte) const override; diff --git a/src/include/common/file_system/virtual_file_system.h b/src/include/common/file_system/virtual_file_system.h index 851380e6e7c..32199652016 100644 --- a/src/include/common/file_system/virtual_file_system.h +++ b/src/include/common/file_system/virtual_file_system.h @@ -19,8 +19,8 @@ class VirtualFileSystem final : public FileSystem { main::ClientContext* context = nullptr, FileLockType lockType = FileLockType::NO_LOCK) override; - std::vector glob( - main::ClientContext* context, const std::string& path) const override; + std::vector glob(main::ClientContext* context, + const std::string& path) const override; void overwriteFile(const std::string& from, const std::string& to) const override; @@ -30,9 +30,11 @@ class VirtualFileSystem final : public FileSystem { bool fileOrPathExists(const std::string& path) const override; + std::string expandPath(main::ClientContext* context, const std::string& path) const override; + protected: - void readFromFile( - FileInfo* fileInfo, void* buffer, uint64_t numBytes, uint64_t position) const override; + void readFromFile(FileInfo* fileInfo, void* buffer, uint64_t numBytes, + uint64_t position) const override; int64_t readFile(FileInfo* fileInfo, void* buf, size_t nbyte) const override; diff --git a/src/include/common/null_mask.h b/src/include/common/null_mask.h index 0f6c31e1826..b588d85ff7d 100644 --- a/src/include/common/null_mask.h +++ b/src/include/common/null_mask.h @@ -9,6 +9,8 @@ namespace kuzu { namespace common { +class ArrowNullMaskTree; + constexpr uint64_t NULL_BITMASKS_WITH_SINGLE_ONE[64] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, @@ -66,6 +68,7 @@ const uint64_t NULL_HIGH_MASKS[65] = {0x0, 0x8000000000000000, 0xc00000000000000 0xfffffffffffffffe, 0xffffffffffffffff}; class NullMask { + friend class ArrowNullMaskTree; public: static constexpr uint64_t NO_NULL_ENTRY = 0; @@ -133,12 +136,12 @@ class NullMask { uint64_t* dstNullEntries, uint64_t dstOffset, uint64_t numBitsToCopy, bool invert = false); bool copyFromNullBits(const uint64_t* srcNullEntries, uint64_t srcOffset, uint64_t dstOffset, - uint64_t numBitsToCopy); + uint64_t numBitsToCopy, bool invert = false); // Sets the given number of bits to null (if isNull is true) or non-null (if isNull is false), // starting at the offset - static void setNullRange( - uint64_t* nullEntries, uint64_t offset, uint64_t numBitsToSet, bool isNull); + static void setNullRange(uint64_t* nullEntries, uint64_t offset, uint64_t numBitsToSet, + bool isNull); void setNullFromRange(uint64_t offset, uint64_t numBitsToSet, bool isNull); @@ -147,8 +150,8 @@ class NullMask { private: static inline std::pair getNullEntryAndBitPos(uint64_t pos) { auto nullEntryPos = pos >> NUM_BITS_PER_NULL_ENTRY_LOG2; - return std::make_pair( - nullEntryPos, pos - (nullEntryPos << NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2)); + return std::make_pair(nullEntryPos, + pos - (nullEntryPos << NullMask::NUM_BITS_PER_NULL_ENTRY_LOG2)); } private: diff --git a/src/include/common/serializer/buffered_serializer.h b/src/include/common/serializer/buffered_serializer.h index d51e65d107b..0291928890f 100644 --- a/src/include/common/serializer/buffered_serializer.h +++ b/src/include/common/serializer/buffered_serializer.h @@ -35,8 +35,8 @@ class BufferedSerializer : public Writer { template void write(T element) { - static_assert( - std::is_trivially_destructible(), "Write element must be trivially destructible"); + static_assert(std::is_trivially_destructible(), + "Write element must be trivially destructible"); write(reinterpret_cast(&element), sizeof(T)); } diff --git a/src/include/common/serializer/deserializer.h b/src/include/common/serializer/deserializer.h index a0cbf596d02..198486f04f1 100644 --- a/src/include/common/serializer/deserializer.h +++ b/src/include/common/serializer/deserializer.h @@ -17,8 +17,8 @@ class Deserializer { explicit Deserializer(std::unique_ptr reader) : reader(std::move(reader)) {} template - requires std::is_trivially_destructible::value || - std::is_same::value void deserializeValue(T& value) { + requires std::is_trivially_destructible::value || std::is_same::value + void deserializeValue(T& value) { reader->read((uint8_t*)&value, sizeof(T)); } @@ -50,7 +50,7 @@ class Deserializer { deserializeValue(vectorSize); values.resize(vectorSize); for (auto& value : values) { - if constexpr (requires(Deserializer & deser) { T::deserialize(deser); }) { + if constexpr (requires(Deserializer& deser) { T::deserialize(deser); }) { value = T::deserialize(*this); } else { deserializeValue(value); diff --git a/src/include/common/serializer/serializer.h b/src/include/common/serializer/serializer.h index 74c60076828..aac1ee12d0b 100644 --- a/src/include/common/serializer/serializer.h +++ b/src/include/common/serializer/serializer.h @@ -17,8 +17,8 @@ class Serializer { explicit Serializer(std::shared_ptr writer) : writer(std::move(writer)) {} template - requires std::is_trivially_destructible::value || - std::is_same::value void serializeValue(const T& value) { + requires std::is_trivially_destructible::value || std::is_same::value + void serializeValue(const T& value) { writer->write((uint8_t*)&value, sizeof(T)); } @@ -53,7 +53,7 @@ class Serializer { uint64_t vectorSize = values.size(); serializeValue(vectorSize); for (auto& value : values) { - if constexpr (requires(Serializer & ser) { value.serialize(ser); }) { + if constexpr (requires(Serializer& ser) { value.serialize(ser); }) { value.serialize(*this); } else { serializeValue(value); diff --git a/src/include/common/string_format.h b/src/include/common/string_format.h index 9c11134726a..2f4d53f942d 100644 --- a/src/include/common/string_format.h +++ b/src/include/common/string_format.h @@ -11,7 +11,9 @@ namespace common { namespace string_format_detail { #define MAP_STD_TO_STRING(typ) \ - inline std::string map(typ v) { return std::to_string(v); } + inline std::string map(typ v) { \ + return std::to_string(v); \ + } MAP_STD_TO_STRING(short) MAP_STD_TO_STRING(unsigned short) @@ -26,7 +28,9 @@ MAP_STD_TO_STRING(double) #undef MAP_STD_TO_STRING #define MAP_SELF(typ) \ - inline typ map(typ v) { return v; } + inline typ map(typ v) { \ + return v; \ + } MAP_SELF(const char*); // Also covers std::string MAP_SELF(std::string_view) @@ -65,8 +69,8 @@ inline void stringFormatHelper(std::string& ret, std::string_view format, Args&& } template -inline void stringFormatHelper( - std::string& ret, std::string_view format, Arg&& arg, Args&&... args) { +inline void stringFormatHelper(std::string& ret, std::string_view format, Arg&& arg, + Args&&... args) { size_t bracket = format.find('{'); if (bracket == std::string_view::npos) { throw InternalException("Too many values for string_format."); @@ -75,8 +79,8 @@ inline void stringFormatHelper( if (format.substr(bracket, 4) == "{{}}") { // Escaped {}. ret += "{}"; - return stringFormatHelper( - ret, format.substr(bracket + 4), std::forward(arg), std::forward(args)...); + return stringFormatHelper(ret, format.substr(bracket + 4), std::forward(arg), + std::forward(args)...); } else if (format.substr(bracket, 2) == "{}") { // Formatted {}. ret += map(arg); @@ -84,8 +88,8 @@ inline void stringFormatHelper( } // Something else. ret.push_back('{'); - return stringFormatHelper( - ret, format.substr(bracket + 1), std::forward(arg), std::forward(args)...); + return stringFormatHelper(ret, format.substr(bracket + 1), std::forward(arg), + std::forward(args)...); } } // namespace string_format_detail diff --git a/src/include/common/string_utils.h b/src/include/common/string_utils.h index 4bdee469534..a50893e874b 100644 --- a/src/include/common/string_utils.h +++ b/src/include/common/string_utils.h @@ -11,10 +11,10 @@ namespace common { class StringUtils { public: - static std::vector splitComma(const std::string& input); + KUZU_API static std::vector splitComma(const std::string& input); - KUZU_API static std::vector split( - const std::string& input, const std::string& delimiter, bool ignoreEmptyStringParts = true); + KUZU_API static std::vector split(const std::string& input, + const std::string& delimiter, bool ignoreEmptyStringParts = true); static std::vector splitBySpace(const std::string& input); @@ -39,8 +39,8 @@ class StringUtils { static inline std::string ltrim(const std::string& input) { auto s = input; - s.erase( - s.begin(), find_if(s.begin(), s.end(), [](unsigned char ch) { return !isspace(ch); })); + s.erase(s.begin(), + find_if(s.begin(), s.end(), [](unsigned char ch) { return !isspace(ch); })); return s; } @@ -58,8 +58,8 @@ class StringUtils { static void removeCStringWhiteSpaces(const char*& input, uint64_t& len); - static void replaceAll( - std::string& str, const std::string& search, const std::string& replacement); + static void replaceAll(std::string& str, const std::string& search, + const std::string& replacement); static std::string extractStringBetween(const std::string& input, char delimiterStart, char delimiterEnd, bool includeDelimiter = false); diff --git a/src/include/common/task_system/progress_bar.h b/src/include/common/task_system/progress_bar.h new file mode 100644 index 00000000000..abd01f393b2 --- /dev/null +++ b/src/include/common/task_system/progress_bar.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +#include "common/metric.h" + +namespace kuzu { +namespace common { + +/** + * @brief Progress bar for tracking the progress of a pipeline. Prints the progress of each query + * pipeline and the overall progress. + */ +class ProgressBar { + +public: + ProgressBar() + : numPipelines{0}, numPipelinesFinished{0}, prevCurPipelineProgress{0.0}, + trackProgress{false}, printing{false}, queryTimer{std::make_unique(true)}, + showProgressAfter{1000} {}; + + void addPipeline(); + + void finishPipeline(); + + void endProgress(); + + void addJobsToPipeline(int jobs); + + void finishJobsInPipeline(int jobs); + + void startProgress(); + + void toggleProgressBarPrinting(bool enable); + + void setShowProgressAfter(uint64_t showProgressAfter); + + void updateProgress(double curPipelineProgress); + +private: + inline void setGreenFont() const { std::cerr << "\033[1;32m"; } + + inline void setDefaultFont() const { std::cerr << "\033[0m"; } + + void printProgressBar(double curPipelineProgress); + + void resetProgressBar(); + + bool shouldPrintProgress() const; + +private: + uint32_t numPipelines; + uint32_t numPipelinesFinished; + double prevCurPipelineProgress; + std::mutex progressBarLock; + bool trackProgress; + bool printing; + std::unique_ptr queryTimer; + uint64_t showProgressAfter; +}; + +} // namespace common +} // namespace kuzu diff --git a/src/include/common/task_system/task.h b/src/include/common/task_system/task.h index 8e46df2b4c3..7c0ec99f4ef 100644 --- a/src/include/common/task_system/task.h +++ b/src/include/common/task_system/task.h @@ -35,7 +35,7 @@ class Task { // already acquired. So do not attempt to acquire the task lock inside. If needed we can // make the deregister function release the lock before calling finalize and drop this // assumption. - virtual void finalizeIfNecessary(){}; + virtual void finalizeIfNecessary() {}; void addChildTask(std::unique_ptr child) { child->parent = this; diff --git a/src/include/common/task_system/task_scheduler.h b/src/include/common/task_system/task_scheduler.h index 5c6a1e54c21..0fa129bfe10 100644 --- a/src/include/common/task_system/task_scheduler.h +++ b/src/include/common/task_system/task_scheduler.h @@ -46,8 +46,8 @@ class TaskScheduler { // whether or not the given task or one of its dependencies errors, when this function // returns, no task related to the given task will be in the task queue. Further no worker // thread will be working on the given task. - void scheduleTaskAndWaitOrError( - const std::shared_ptr& task, processor::ExecutionContext* context); + void scheduleTaskAndWaitOrError(const std::shared_ptr& task, + processor::ExecutionContext* context); private: std::shared_ptr pushTaskIntoQueue(const std::shared_ptr& task); diff --git a/src/include/common/timer.h b/src/include/common/timer.h index 8295babc85a..aabe69a2107 100644 --- a/src/include/common/timer.h +++ b/src/include/common/timer.h @@ -22,7 +22,7 @@ class Timer { finished = true; } - double getDuration() { + double getDuration() const { if (finished) { auto duration = stopTime - startTime; return (double)std::chrono::duration_cast(duration).count(); @@ -30,7 +30,7 @@ class Timer { throw Exception("Timer is still running."); } - uint64_t getElapsedTimeInMS() { + uint64_t getElapsedTimeInMS() const { auto now = std::chrono::high_resolution_clock::now(); auto duration = now - startTime; auto count = std::chrono::duration_cast(duration).count(); diff --git a/src/include/common/type_utils.h b/src/include/common/type_utils.h index 43b03dbd2ae..5d06b4b4aca 100644 --- a/src/include/common/type_utils.h +++ b/src/include/common/type_utils.h @@ -34,21 +34,16 @@ class TypeUtils { std::is_same::value || std::is_same::value); return std::to_string(val); } - // Fixed list does not have a physical class. So we cannot reuse above toString template. - // dummyVector is used to avoid clang-tidy check and should be removed once we unify - // Fixed-LIST in memory layout with VAR-LIST. - static std::string fixedListToString( - const uint8_t* val, const common::LogicalType& type, ValueVector* dummyVector); static std::string nodeToString(const struct_entry_t& val, ValueVector* vector); static std::string relToString(const struct_entry_t& val, ValueVector* vector); - static inline void encodeOverflowPtr( - uint64_t& overflowPtr, page_idx_t pageIdx, uint16_t pageOffset) { + static inline void encodeOverflowPtr(uint64_t& overflowPtr, page_idx_t pageIdx, + uint16_t pageOffset) { memcpy(&overflowPtr, &pageIdx, 4); memcpy(((uint8_t*)&overflowPtr) + 4, &pageOffset, 2); } - static inline void decodeOverflowPtr( - uint64_t overflowPtr, page_idx_t& pageIdx, uint16_t& pageOffset) { + static inline void decodeOverflowPtr(uint64_t overflowPtr, page_idx_t& pageIdx, + uint16_t& pageOffset) { pageIdx = 0; memcpy(&pageIdx, &overflowPtr, 4); memcpy(&pageOffset, ((uint8_t*)&overflowPtr) + 4, 2); @@ -80,7 +75,8 @@ class TypeUtils { return common::PhysicalTypeID::INT128; } else if constexpr (std::is_same_v) { return common::PhysicalTypeID::INTERVAL; - } else if constexpr (std::is_same_v) { + } else if constexpr (std::same_as || std::same_as || + std::same_as) { return common::PhysicalTypeID::STRING; } else { KU_UNREACHABLE; @@ -177,7 +173,8 @@ class TypeUtils { return func(blob_t()); case LogicalTypeID::UUID: return func(ku_uuid_t()); - case LogicalTypeID::VAR_LIST: + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: return func(list_entry_t()); case LogicalTypeID::MAP: return func(map_entry_t()); @@ -189,11 +186,9 @@ class TypeUtils { case LogicalTypeID::UNION: return func(union_entry_t()); /* NOLINTEND(bugprone-branch-clone)*/ - case LogicalTypeID::FIXED_LIST: case LogicalTypeID::ANY: case LogicalTypeID::POINTER: case LogicalTypeID::RDF_VARIANT: - // FIXED_LIST has no type KU_UNREACHABLE; } } @@ -235,13 +230,13 @@ class TypeUtils { return func(internalID_t()); case PhysicalTypeID::STRING: return func(ku_string_t()); - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::LIST: return func(list_entry_t()); + case PhysicalTypeID::STRUCT: + return func(struct_entry_t()); /* NOLINTEND(bugprone-branch-clone)*/ case PhysicalTypeID::ANY: - case PhysicalTypeID::FIXED_LIST: case PhysicalTypeID::POINTER: - case PhysicalTypeID::STRUCT: // Unsupported type KU_UNREACHABLE; } diff --git a/src/include/common/types/cast_helpers.h b/src/include/common/types/cast_helpers.h index 697bb40154c..d75289f1c42 100644 --- a/src/include/common/types/cast_helpers.h +++ b/src/include/common/types/cast_helpers.h @@ -213,8 +213,8 @@ struct IntervalToStringCast { length += 2; } - static void FormatIntervalValue( - int32_t value, char buffer[], uint64_t& length, const char* name, uint64_t name_len) { + static void FormatIntervalValue(int32_t value, char buffer[], uint64_t& length, + const char* name, uint64_t name_len) { if (value == 0) { return; } diff --git a/src/include/common/types/date_t.h b/src/include/common/types/date_t.h index 1413fdfe46e..2b760535186 100644 --- a/src/include/common/types/date_t.h +++ b/src/include/common/types/date_t.h @@ -73,8 +73,8 @@ class Date { // Convert a date object to a string in the format "YYYY-MM-DD" KUZU_API static std::string toString(date_t date); // Try to convert text in a buffer to a date; returns true if parsing was successful - KUZU_API static bool tryConvertDate( - const char* buf, uint64_t len, uint64_t& pos, date_t& result); + KUZU_API static bool tryConvertDate(const char* buf, uint64_t len, uint64_t& pos, + date_t& result); // private: // Returns true if (year) is a leap year, and false otherwise @@ -83,14 +83,14 @@ class Date { // date KUZU_API static bool isValid(int32_t year, int32_t month, int32_t day); // Extract the year, month and day from a given date object - KUZU_API static void convert( - date_t date, int32_t& out_year, int32_t& out_month, int32_t& out_day); + KUZU_API static void convert(date_t date, int32_t& out_year, int32_t& out_month, + int32_t& out_day); // Create a Date object from a specified (year, month, day) combination KUZU_API static date_t fromDate(int32_t year, int32_t month, int32_t day); // Helper function to parse two digits from a string (e.g. "30" -> 30, "03" -> 3, "3" -> 3) - KUZU_API static bool parseDoubleDigit( - const char* buf, uint64_t len, uint64_t& pos, int32_t& result); + KUZU_API static bool parseDoubleDigit(const char* buf, uint64_t len, uint64_t& pos, + int32_t& result); KUZU_API static int32_t monthDays(int32_t year, int32_t month); diff --git a/src/include/common/types/dtime_t.h b/src/include/common/types/dtime_t.h index 81d8bc3a26f..05f20355ee7 100644 --- a/src/include/common/types/dtime_t.h +++ b/src/include/common/types/dtime_t.h @@ -39,28 +39,28 @@ class Time { public: // Convert a string in the format "hh:mm:ss" to a time object KUZU_API static dtime_t fromCString(const char* buf, uint64_t len); - KUZU_API static bool tryConvertInterval( - const char* buf, uint64_t len, uint64_t& pos, dtime_t& result); - KUZU_API static bool tryConvertTime( - const char* buf, uint64_t len, uint64_t& pos, dtime_t& result); + KUZU_API static bool tryConvertInterval(const char* buf, uint64_t len, uint64_t& pos, + dtime_t& result); + KUZU_API static bool tryConvertTime(const char* buf, uint64_t len, uint64_t& pos, + dtime_t& result); // Convert a time object to a string in the format "hh:mm:ss" KUZU_API static std::string toString(dtime_t time); - KUZU_API static dtime_t fromTime( - int32_t hour, int32_t minute, int32_t second, int32_t microseconds = 0); + KUZU_API static dtime_t fromTime(int32_t hour, int32_t minute, int32_t second, + int32_t microseconds = 0); // Extract the time from a given timestamp object - KUZU_API static void convert( - dtime_t time, int32_t& out_hour, int32_t& out_min, int32_t& out_sec, int32_t& out_micros); + KUZU_API static void convert(dtime_t time, int32_t& out_hour, int32_t& out_min, + int32_t& out_sec, int32_t& out_micros); - KUZU_API static bool isValid( - int32_t hour, int32_t minute, int32_t second, int32_t milliseconds); + KUZU_API static bool isValid(int32_t hour, int32_t minute, int32_t second, + int32_t milliseconds); private: static bool tryConvertInternal(const char* buf, uint64_t len, uint64_t& pos, dtime_t& result); - static dtime_t fromTimeInternal( - int32_t hour, int32_t minute, int32_t second, int32_t microseconds = 0); + static dtime_t fromTimeInternal(int32_t hour, int32_t minute, int32_t second, + int32_t microseconds = 0); }; } // namespace common diff --git a/src/include/common/types/interval_t.h b/src/include/common/types/interval_t.h index 5d74cb13ae9..90696c2b32b 100644 --- a/src/include/common/types/interval_t.h +++ b/src/include/common/types/interval_t.h @@ -97,8 +97,8 @@ class Interval { KUZU_API static interval_t fromCString(const char* str, uint64_t len); KUZU_API static std::string toString(interval_t interval); KUZU_API static bool greaterThan(const interval_t& left, const interval_t& right); - KUZU_API static void normalizeIntervalEntries( - interval_t input, int64_t& months, int64_t& days, int64_t& micros); + KUZU_API static void normalizeIntervalEntries(interval_t input, int64_t& months, int64_t& days, + int64_t& micros); KUZU_API static void tryGetDatePartSpecifier(std::string specifier, DatePartSpecifier& result); KUZU_API static int32_t getIntervalPart(DatePartSpecifier specifier, interval_t& timestamp); KUZU_API static int64_t getMicro(const interval_t& val); diff --git a/src/include/common/types/ku_string.h b/src/include/common/types/ku_string.h index 327f683e460..72594d3d5a4 100644 --- a/src/include/common/types/ku_string.h +++ b/src/include/common/types/ku_string.h @@ -4,10 +4,12 @@ #include #include +#include "common/api.h" + namespace kuzu { namespace common { -struct ku_string_t { +struct KUZU_API ku_string_t { static constexpr uint64_t PREFIX_LENGTH = 4; static constexpr uint64_t INLINED_SUFFIX_LENGTH = 8; @@ -25,7 +27,11 @@ struct ku_string_t { static bool isShortString(uint32_t len) { return len <= SHORT_STR_LENGTH; } - inline const uint8_t* getData() const { + const uint8_t* getData() const { + return isShortString(len) ? prefix : reinterpret_cast(overflowPtr); + } + + uint8_t* getDataUnsafe() { return isShortString(len) ? prefix : reinterpret_cast(overflowPtr); } @@ -34,20 +40,20 @@ struct ku_string_t { void set(const std::string& value); void set(const char* value, uint64_t length); void set(const ku_string_t& value); - inline void setShortString(const char* value, uint64_t length) { + void setShortString(const char* value, uint64_t length) { this->len = length; memcpy(prefix, value, length); } - inline void setLongString(const char* value, uint64_t length) { + void setLongString(const char* value, uint64_t length) { this->len = length; memcpy(prefix, value, PREFIX_LENGTH); memcpy(reinterpret_cast(overflowPtr), value, length); } - inline void setShortString(const ku_string_t& value) { + void setShortString(const ku_string_t& value) { this->len = value.len; memcpy(prefix, value.prefix, value.len); } - inline void setLongString(const ku_string_t& value) { + void setLongString(const ku_string_t& value) { this->len = value.len; memcpy(prefix, value.prefix, PREFIX_LENGTH); memcpy(reinterpret_cast(overflowPtr), reinterpret_cast(value.overflowPtr), diff --git a/src/include/common/types/timestamp_t.h b/src/include/common/types/timestamp_t.h index f5b4379efdf..790c99eaaaf 100644 --- a/src/include/common/types/timestamp_t.h +++ b/src/include/common/types/timestamp_t.h @@ -103,11 +103,11 @@ class Timestamp { KUZU_API static int64_t getEpochSeconds(const timestamp_t& timestamp); - KUZU_API static bool tryParseUTCOffset( - const char* str, uint64_t& pos, uint64_t len, int& hour_offset, int& minute_offset); + KUZU_API static bool tryParseUTCOffset(const char* str, uint64_t& pos, uint64_t len, + int& hour_offset, int& minute_offset); - static std::string getTimestampConversionExceptionMsg( - const char* str, uint64_t len, const std::string& typeID = "TIMESTAMP") { + static std::string getTimestampConversionExceptionMsg(const char* str, uint64_t len, + const std::string& typeID = "TIMESTAMP") { return "Error occurred during parsing " + typeID + ". Given: \"" + std::string(str, len) + "\". Expected format: (YYYY-MM-DD hh:mm:ss[.zzzzzz][+-TT[:tt]])"; } diff --git a/src/include/common/types/types.h b/src/include/common/types/types.h index a0b90450d98..f97ea733641 100644 --- a/src/include/common/types/types.h +++ b/src/include/common/types/types.h @@ -8,6 +8,7 @@ #include "common/api.h" #include "common/assert.h" #include "common/types/internal_id_t.h" +#include "common/types/interval_t.h" namespace kuzu { namespace processor { @@ -32,6 +33,7 @@ constexpr property_id_t INVALID_PROPERTY_ID = UINT32_MAX; using column_id_t = property_id_t; constexpr column_id_t INVALID_COLUMN_ID = INVALID_PROPERTY_ID; using vector_idx_t = uint32_t; +using idx_t = uint32_t; constexpr vector_idx_t INVALID_VECTOR_IDX = UINT32_MAX; using block_idx_t = uint64_t; constexpr block_idx_t INVALID_BLOCK_IDX = UINT64_MAX; @@ -46,6 +48,7 @@ constexpr node_group_idx_t INVALID_NODE_GROUP_IDX = UINT64_MAX; using partition_idx_t = uint64_t; constexpr partition_idx_t INVALID_PARTITION_IDX = UINT64_MAX; using length_t = uint64_t; +using list_size_t = uint32_t; // System representation for a variable-sized overflow value. struct overflow_value_t { @@ -57,10 +60,10 @@ struct overflow_value_t { struct list_entry_t { common::offset_t offset; - uint64_t size; + list_size_t size; - list_entry_t() : offset{INVALID_OFFSET}, size{UINT64_MAX} {} - list_entry_t(common::offset_t offset, uint64_t size) : offset{offset}, size{size} {} + list_entry_t() : offset{INVALID_OFFSET}, size{UINT32_MAX} {} + list_entry_t(common::offset_t offset, list_size_t size) : offset{offset}, size{size} {} }; struct struct_entry_t { @@ -82,10 +85,16 @@ template concept HashablePrimitive = ((std::integral && !std::is_same_v) || std::floating_point || std::is_same_v); template -concept IndexHashable = ((std::integral && !std::is_same_v) || std::floating_point || - std::is_same_v || - std::is_same_v || - std::is_same_v); +concept IndexHashable = + ((std::integral && !std::is_same_v) || std::floating_point || + std::is_same_v || std::is_same_v || + std::is_same_v || std::same_as); + +template +concept HashableTypes = (std::integral || std::floating_point || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v); enum class KUZU_API LogicalTypeID : uint8_t { ANY = 0, @@ -115,21 +124,21 @@ enum class KUZU_API LogicalTypeID : uint8_t { TIMESTAMP_NS = 38, TIMESTAMP_TZ = 39, INTERVAL = 40, - FIXED_LIST = 41, INTERNAL_ID = 42, STRING = 50, BLOB = 51, - VAR_LIST = 52, - STRUCT = 53, - MAP = 54, - UNION = 55, - RDF_VARIANT = 56, - POINTER = 57, + LIST = 52, + ARRAY = 53, + STRUCT = 54, + MAP = 55, + UNION = 56, + RDF_VARIANT = 57, + POINTER = 58, - UUID = 58 + UUID = 59 }; enum class PhysicalTypeID : uint8_t { @@ -152,8 +161,7 @@ enum class PhysicalTypeID : uint8_t { // Variable size types. STRING = 20, - FIXED_LIST = 21, - VAR_LIST = 22, + LIST = 22, STRUCT = 23, POINTER = 24, }; @@ -172,13 +180,13 @@ class ExtraTypeInfo { virtual void serializeInternal(Serializer& serializer) const = 0; }; -class VarListTypeInfo : public ExtraTypeInfo { +class ListTypeInfo : public ExtraTypeInfo { public: - VarListTypeInfo() = default; - explicit VarListTypeInfo(std::unique_ptr childType) + ListTypeInfo() = default; + explicit ListTypeInfo(std::unique_ptr childType) : childType{std::move(childType)} {} inline LogicalType* getChildType() const { return childType.get(); } - bool operator==(const VarListTypeInfo& other) const; + bool operator==(const ListTypeInfo& other) const; std::unique_ptr copy() const override; static std::unique_ptr deserialize(Deserializer& deserializer); @@ -190,14 +198,13 @@ class VarListTypeInfo : public ExtraTypeInfo { std::unique_ptr childType; }; -class FixedListTypeInfo : public VarListTypeInfo { +class ArrayTypeInfo : public ListTypeInfo { public: - FixedListTypeInfo() = default; - explicit FixedListTypeInfo( - std::unique_ptr childType, uint64_t fixedNumElementsInList) - : VarListTypeInfo{std::move(childType)}, fixedNumElementsInList{fixedNumElementsInList} {} - inline uint64_t getNumValuesInList() const { return fixedNumElementsInList; } - bool operator==(const FixedListTypeInfo& other) const; + ArrayTypeInfo() = default; + explicit ArrayTypeInfo(std::unique_ptr childType, uint64_t numElements) + : ListTypeInfo{std::move(childType)}, numElements{numElements} {} + inline uint64_t getNumElements() const { return numElements; } + bool operator==(const ArrayTypeInfo& other) const; static std::unique_ptr deserialize(Deserializer& deserializer); std::unique_ptr copy() const override; @@ -205,7 +212,7 @@ class FixedListTypeInfo : public VarListTypeInfo { void serializeInternal(Serializer& serializer) const override; private: - uint64_t fixedNumElementsInList; + uint64_t numElements; }; class StructField { @@ -262,8 +269,8 @@ class StructTypeInfo : public ExtraTypeInfo { class LogicalType { friend class LogicalTypeUtils; friend struct StructType; - friend struct VarListType; - friend struct FixedListType; + friend struct ListType; + friend struct ArrayType; public: KUZU_API LogicalType() : typeID{LogicalTypeID::ANY}, extraTypeInfo{nullptr} { @@ -297,10 +304,12 @@ class LogicalType { static std::unique_ptr deserialize(Deserializer& deserializer); - std::unique_ptr copy() const; + KUZU_API std::unique_ptr copy() const; static std::vector> copy( const std::vector>& types); + static std::vector copy(const std::vector& types); + static std::vector copy(const std::vector& types); static std::unique_ptr ANY() { return std::make_unique(LogicalTypeID::ANY); @@ -308,6 +317,9 @@ class LogicalType { static std::unique_ptr BOOL() { return std::make_unique(LogicalTypeID::BOOL); } + static std::unique_ptr HASH() { + return std::make_unique(LogicalTypeID::INT64); + } static std::unique_ptr INT64() { return std::make_unique(LogicalTypeID::INT64); } @@ -393,22 +405,27 @@ class LogicalType { static KUZU_API std::unique_ptr UNION(std::vector&& fields); - static KUZU_API std::unique_ptr VAR_LIST(std::unique_ptr childType); + static KUZU_API std::unique_ptr LIST(std::unique_ptr childType); template - static inline std::unique_ptr VAR_LIST(T&& childType) { - return LogicalType::VAR_LIST(std::make_unique(std::forward(childType))); + static inline std::unique_ptr LIST(T&& childType) { + return LogicalType::LIST(std::make_unique(std::forward(childType))); } - static KUZU_API std::unique_ptr MAP( - std::unique_ptr keyType, std::unique_ptr valueType); + static KUZU_API std::unique_ptr MAP(std::unique_ptr keyType, + std::unique_ptr valueType); template static inline std::unique_ptr MAP(T&& keyType, T&& valueType) { return LogicalType::MAP(std::make_unique(std::forward(keyType)), std::make_unique(std::forward(valueType))); } - static KUZU_API std::unique_ptr FIXED_LIST( - std::unique_ptr childType, uint64_t fixedNumElementsInList); + static KUZU_API std::unique_ptr ARRAY(std::unique_ptr childType, + uint64_t numElements); + template + static inline std::unique_ptr ARRAY(T&& childType, uint64_t numElements) { + return LogicalType::ARRAY(std::make_unique(std::forward(childType)), + numElements); + } private: friend struct CAPIHelper; @@ -422,41 +439,43 @@ class LogicalType { std::unique_ptr extraTypeInfo; }; +// TODO: Should remove `logical_types_t`. using logical_types_t = std::vector>; +using logical_type_vec_t = std::vector; -struct VarListType { +struct ListType { static inline LogicalType* getChildType(const LogicalType* type) { - KU_ASSERT(type->getPhysicalType() == PhysicalTypeID::VAR_LIST); - auto varListTypeInfo = reinterpret_cast(type->extraTypeInfo.get()); - return varListTypeInfo->getChildType(); + KU_ASSERT(type->getPhysicalType() == PhysicalTypeID::LIST); + auto listTypeInfo = reinterpret_cast(type->extraTypeInfo.get()); + return listTypeInfo->getChildType(); } }; -struct FixedListType { +struct ArrayType { static inline LogicalType* getChildType(const LogicalType* type) { - KU_ASSERT(type->getLogicalTypeID() == LogicalTypeID::FIXED_LIST); - auto fixedListTypeInfo = reinterpret_cast(type->extraTypeInfo.get()); - return fixedListTypeInfo->getChildType(); + KU_ASSERT(type->getLogicalTypeID() == LogicalTypeID::ARRAY); + auto arrayTypeInfo = reinterpret_cast(type->extraTypeInfo.get()); + return arrayTypeInfo->getChildType(); } - static inline uint64_t getNumValuesInList(const LogicalType* type) { - KU_ASSERT(type->getLogicalTypeID() == LogicalTypeID::FIXED_LIST); - auto fixedListTypeInfo = reinterpret_cast(type->extraTypeInfo.get()); - return fixedListTypeInfo->getNumValuesInList(); + static inline uint64_t getNumElements(const LogicalType* type) { + KU_ASSERT(type->getLogicalTypeID() == LogicalTypeID::ARRAY); + auto arrayTypeInfo = reinterpret_cast(type->extraTypeInfo.get()); + return arrayTypeInfo->getNumElements(); } }; struct NodeType { - static inline void setExtraTypeInfo( - LogicalType& type, std::unique_ptr extraTypeInfo) { + static inline void setExtraTypeInfo(LogicalType& type, + std::unique_ptr extraTypeInfo) { KU_ASSERT(type.getLogicalTypeID() == LogicalTypeID::NODE); type.setExtraTypeInfo(std::move(extraTypeInfo)); } }; struct RelType { - static inline void setExtraTypeInfo( - LogicalType& type, std::unique_ptr extraTypeInfo) { + static inline void setExtraTypeInfo(LogicalType& type, + std::unique_ptr extraTypeInfo) { KU_ASSERT(type.getLogicalTypeID() == LogicalTypeID::REL); type.setExtraTypeInfo(std::move(extraTypeInfo)); } @@ -514,12 +533,12 @@ struct StructType { struct MapType { static inline LogicalType* getKeyType(const LogicalType* type) { KU_ASSERT(type->getLogicalTypeID() == LogicalTypeID::MAP); - return StructType::getFieldTypes(VarListType::getChildType(type))[0]; + return StructType::getFieldTypes(ListType::getChildType(type))[0]; } static inline LogicalType* getValueType(const LogicalType* type) { KU_ASSERT(type->getLogicalTypeID() == LogicalTypeID::MAP); - return StructType::getFieldTypes(VarListType::getChildType(type))[1]; + return StructType::getFieldTypes(ListType::getChildType(type))[1]; } }; @@ -556,7 +575,7 @@ struct PhysicalTypeUtils { class LogicalTypeUtils { public: KUZU_API static std::string toString(LogicalTypeID dataTypeID); - static std::string toString(const std::vector& dataTypes); + KUZU_API static std::string toString(const std::vector& dataTypes); KUZU_API static std::string toString(const std::vector& dataTypeIDs); KUZU_API static LogicalType dataTypeFromString(const std::string& dataTypeString); static uint32_t getRowLayoutSize(const LogicalType& logicalType); @@ -571,8 +590,8 @@ class LogicalTypeUtils { private: static LogicalTypeID dataTypeIDFromString(const std::string& trimmedStr); static std::vector parseStructFields(const std::string& structTypeStr); - static std::unique_ptr parseVarListType(const std::string& trimmedStr); - static std::unique_ptr parseFixedListType(const std::string& trimmedStr); + static std::unique_ptr parseListType(const std::string& trimmedStr); + static std::unique_ptr parseArrayType(const std::string& trimmedStr); static std::vector parseStructTypeInfo(const std::string& structTypeStr); static std::unique_ptr parseStructType(const std::string& trimmedStr); static std::unique_ptr parseMapType(const std::string& trimmedStr); diff --git a/src/include/common/types/value/value.h b/src/include/common/types/value/value.h index dc30bd38af2..7ac3e380267 100644 --- a/src/include/common/types/value/value.h +++ b/src/include/common/types/value/value.h @@ -152,8 +152,8 @@ class Value { * @param dataType the logical type of the value. * @param children a vector of children values. */ - KUZU_API explicit Value( - std::unique_ptr dataType, std::vector> children); + KUZU_API explicit Value(std::unique_ptr dataType, + std::vector> children); /** * @param other the value to copy from. */ @@ -236,8 +236,7 @@ class Value { Value(); explicit Value(const LogicalType& dataType); - void copyFromFixedList(const uint8_t* fixedList); - void copyFromVarList(ku_list_t& list, const LogicalType& childType); + void copyFromList(ku_list_t& list, const LogicalType& childType); void copyFromStruct(const uint8_t* kuStruct); void copyFromUnion(const uint8_t* kuUnion); diff --git a/src/include/common/vector/auxiliary_buffer.h b/src/include/common/vector/auxiliary_buffer.h index 3f281ad9a6a..d2e74bbea99 100644 --- a/src/include/common/vector/auxiliary_buffer.h +++ b/src/include/common/vector/auxiliary_buffer.h @@ -37,8 +37,8 @@ class StructAuxiliaryBuffer : public AuxiliaryBuffer { public: StructAuxiliaryBuffer(const LogicalType& type, storage::MemoryManager* memoryManager); - inline void referenceChildVector( - vector_idx_t idx, std::shared_ptr vectorToReference) { + inline void referenceChildVector(vector_idx_t idx, + std::shared_ptr vectorToReference) { childrenVectors[idx] = std::move(vectorToReference); } inline const std::vector>& getFieldVectors() const { @@ -69,19 +69,17 @@ class ListAuxiliaryBuffer : public AuxiliaryBuffer { public: ListAuxiliaryBuffer(const LogicalType& dataVectorType, storage::MemoryManager* memoryManager); - inline void setDataVector(std::shared_ptr vector) { - dataVector = std::move(vector); - } - inline ValueVector* getDataVector() const { return dataVector.get(); } - inline std::shared_ptr getSharedDataVector() const { return dataVector; } + void setDataVector(std::shared_ptr vector) { dataVector = std::move(vector); } + ValueVector* getDataVector() const { return dataVector.get(); } + std::shared_ptr getSharedDataVector() const { return dataVector; } - list_entry_t addList(uint64_t listSize); + list_entry_t addList(list_size_t listSize); - inline uint64_t getSize() const { return size; } + uint64_t getSize() const { return size; } - inline void resetSize() { size = 0; } + void resetSize() { size = 0; } - void resize(uint64_t numValues); + KUZU_API void resize(uint64_t numValues); private: void resizeDataVector(ValueVector* dataVector); @@ -96,8 +94,8 @@ class ListAuxiliaryBuffer : public AuxiliaryBuffer { class AuxiliaryBufferFactory { public: - static std::unique_ptr getAuxiliaryBuffer( - LogicalType& type, storage::MemoryManager* memoryManager); + static std::unique_ptr getAuxiliaryBuffer(LogicalType& type, + storage::MemoryManager* memoryManager); }; } // namespace common diff --git a/src/include/common/vector/value_vector.h b/src/include/common/vector/value_vector.h index 5a1fd9f170f..5f9afe437ec 100644 --- a/src/include/common/vector/value_vector.h +++ b/src/include/common/vector/value_vector.h @@ -17,9 +17,8 @@ class Value; //! A Vector represents values of the same data type. //! The capacity of a ValueVector is either 1 (sequence) or DEFAULT_VECTOR_CAPACITY. -class ValueVector { +class KUZU_API ValueVector { friend class ListVector; - friend class FixedListVector; friend class ListAuxiliaryBuffer; friend class StructVector; friend class StringVector; @@ -29,64 +28,68 @@ class ValueVector { explicit ValueVector(LogicalType dataType, storage::MemoryManager* memoryManager = nullptr); explicit ValueVector(LogicalTypeID dataTypeID, storage::MemoryManager* memoryManager = nullptr) : ValueVector(LogicalType(dataTypeID), memoryManager) { - KU_ASSERT(dataTypeID != LogicalTypeID::VAR_LIST); + KU_ASSERT(dataTypeID != LogicalTypeID::LIST); } - KUZU_API ~ValueVector() = default; + ~ValueVector() = default; void setState(const std::shared_ptr& state_); - inline void setAllNull() { nullMask->setAllNull(); } - inline void setAllNonNull() { nullMask->setAllNonNull(); } + void setAllNull() { nullMask->setAllNull(); } + void setAllNonNull() { nullMask->setAllNonNull(); } // On return true, there are no null. On return false, there may or may not be nulls. - inline bool hasNoNullsGuarantee() const { return nullMask->hasNoNullsGuarantee(); } - inline void setNullRange(uint32_t startPos, uint32_t len, bool value) { + bool hasNoNullsGuarantee() const { return nullMask->hasNoNullsGuarantee(); } + void setNullRange(uint32_t startPos, uint32_t len, bool value) { nullMask->setNullFromRange(startPos, len, value); } - inline const uint64_t* getNullMaskData() { return nullMask->getData(); } - KUZU_API void setNull(uint32_t pos, bool isNull); - inline uint8_t isNull(uint32_t pos) const { return nullMask->isNull(pos); } - inline void setAsSingleNullEntry() { + const uint64_t* getNullMaskData() { return nullMask->getData(); } + void setNull(uint32_t pos, bool isNull); + uint8_t isNull(uint32_t pos) const { return nullMask->isNull(pos); } + void setAsSingleNullEntry() { state->selVector->selectedSize = 1; setNull(state->selVector->selectedPositions[0], true); } bool setNullFromBits(const uint64_t* srcNullEntries, uint64_t srcOffset, uint64_t dstOffset, - uint64_t numBitsToCopy); + uint64_t numBitsToCopy, bool invert = false); - inline uint32_t getNumBytesPerValue() const { return numBytesPerValue; } + uint32_t getNumBytesPerValue() const { return numBytesPerValue; } // TODO(Guodong): Rename this to getValueRef template - inline T& getValue(uint32_t pos) const { + const T& getValue(uint32_t pos) const { return ((T*)valueBuffer.get())[pos]; } template - KUZU_API void setValue(uint32_t pos, T val); + T& getValue(uint32_t pos) { + return ((T*)valueBuffer.get())[pos]; + } + template + void setValue(uint32_t pos, T val); // copyFromRowData assumes rowData is non-NULL. void copyFromRowData(uint32_t pos, const uint8_t* rowData); // copyToRowData assumes srcVectorData is non-NULL. - void copyToRowData( - uint32_t pos, uint8_t* rowData, InMemOverflowBuffer* rowOverflowBuffer) const; + void copyToRowData(uint32_t pos, uint8_t* rowData, + InMemOverflowBuffer* rowOverflowBuffer) const; // copyFromVectorData assumes srcVectorData is non-NULL. - void copyFromVectorData( - uint8_t* dstData, const ValueVector* srcVector, const uint8_t* srcVectorData); + void copyFromVectorData(uint8_t* dstData, const ValueVector* srcVector, + const uint8_t* srcVectorData); void copyFromVectorData(uint64_t dstPos, const ValueVector* srcVector, uint64_t srcPos); void copyFromValue(uint64_t pos, const Value& value); - std::unique_ptr getAsValue(uint64_t pos); + std::unique_ptr getAsValue(uint64_t pos) const; - inline uint8_t* getData() const { return valueBuffer.get(); } + uint8_t* getData() const { return valueBuffer.get(); } - inline offset_t readNodeOffset(uint32_t pos) const { + offset_t readNodeOffset(uint32_t pos) const { KU_ASSERT(dataType.getLogicalTypeID() == LogicalTypeID::INTERNAL_ID); return getValue(pos).offset; } - inline void setSequential() { _isSequential = true; } - inline bool isSequential() const { return _isSequential; } + void setSequential() { _isSequential = true; } + bool isSequential() const { return _isSequential; } - KUZU_API void resetAuxiliaryBuffer(); + void resetAuxiliaryBuffer(); // If there is still non-null values after discarding, return true. Otherwise, return false. // For an unflat vector, its selection vector is also updated to the resultSelVector. @@ -108,7 +111,7 @@ class ValueVector { std::unique_ptr auxiliaryBuffer; }; -class StringVector { +class KUZU_API StringVector { public: static inline InMemOverflowBuffer* getInMemOverflowBuffer(ValueVector* vector) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); @@ -118,22 +121,23 @@ class StringVector { } static void addString(ValueVector* vector, uint32_t vectorPos, ku_string_t& srcStr); - static void addString( - ValueVector* vector, uint32_t vectorPos, const char* srcStr, uint64_t length); + static void addString(ValueVector* vector, uint32_t vectorPos, const char* srcStr, + uint64_t length); static void addString(ValueVector* vector, uint32_t vectorPos, const std::string& srcStr); // Add empty string with space reserved for the provided size // Returned value can be modified to set the string contents static ku_string_t& reserveString(ValueVector* vector, uint32_t vectorPos, uint64_t length); + static void reserveString(ValueVector* vector, ku_string_t& dstStr, uint64_t length); static void addString(ValueVector* vector, ku_string_t& dstStr, ku_string_t& srcStr); - static void addString( - ValueVector* vector, ku_string_t& dstStr, const char* srcStr, uint64_t length); - static void addString( - kuzu::common::ValueVector* vector, ku_string_t& dstStr, const std::string& srcStr); + static void addString(ValueVector* vector, ku_string_t& dstStr, const char* srcStr, + uint64_t length); + static void addString(kuzu::common::ValueVector* vector, ku_string_t& dstStr, + const std::string& srcStr); static void copyToRowData(const ValueVector* vector, uint32_t pos, uint8_t* rowData, InMemOverflowBuffer* rowOverflowBuffer); }; -struct BlobVector { +struct KUZU_API BlobVector { static void addBlob(ValueVector* vector, uint32_t pos, const char* data, uint32_t length) { StringVector::addString(vector, pos, data, length); } @@ -142,52 +146,51 @@ struct BlobVector { } }; -class ListVector { +class KUZU_API ListVector { public: - static inline void setDataVector( - const ValueVector* vector, std::shared_ptr dataVector) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static void setDataVector(const ValueVector* vector, std::shared_ptr dataVector) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); auto listBuffer = ku_dynamic_cast(vector->auxiliaryBuffer.get()); listBuffer->setDataVector(std::move(dataVector)); } - static inline ValueVector* getDataVector(const ValueVector* vector) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static ValueVector* getDataVector(const ValueVector* vector) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); return ku_dynamic_cast( vector->auxiliaryBuffer.get()) ->getDataVector(); } - static inline std::shared_ptr getSharedDataVector(const ValueVector* vector) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static std::shared_ptr getSharedDataVector(const ValueVector* vector) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); return ku_dynamic_cast( vector->auxiliaryBuffer.get()) ->getSharedDataVector(); } - static inline uint64_t getDataVectorSize(const ValueVector* vector) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static uint64_t getDataVectorSize(const ValueVector* vector) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); return ku_dynamic_cast( vector->auxiliaryBuffer.get()) ->getSize(); } - static inline uint8_t* getListValues(const ValueVector* vector, const list_entry_t& listEntry) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static uint8_t* getListValues(const ValueVector* vector, const list_entry_t& listEntry) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); auto dataVector = getDataVector(vector); return dataVector->getData() + dataVector->getNumBytesPerValue() * listEntry.offset; } - static inline uint8_t* getListValuesWithOffset( - const ValueVector* vector, const list_entry_t& listEntry, offset_t elementOffsetInList) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static uint8_t* getListValuesWithOffset(const ValueVector* vector, + const list_entry_t& listEntry, offset_t elementOffsetInList) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); return getListValues(vector, listEntry) + elementOffsetInList * getDataVector(vector)->getNumBytesPerValue(); } - static inline list_entry_t addList(ValueVector* vector, uint64_t listSize) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); + static list_entry_t addList(ValueVector* vector, uint64_t listSize) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::LIST); return ku_dynamic_cast( vector->auxiliaryBuffer.get()) ->addList(listSize); } - static inline void resizeDataVector(ValueVector* vector, uint64_t numValues) { + static void resizeDataVector(ValueVector* vector, uint64_t numValues) { ku_dynamic_cast(vector->auxiliaryBuffer.get()) ->resize(numValues); } @@ -197,34 +200,11 @@ class ListVector { InMemOverflowBuffer* rowOverflowBuffer); static void copyFromVectorData(ValueVector* dstVector, uint8_t* dstData, const ValueVector* srcVector, const uint8_t* srcData); - static void appendDataVector( - ValueVector* dstVector, ValueVector* srcDataVector, uint64_t numValuesToAppend); + static void appendDataVector(ValueVector* dstVector, ValueVector* srcDataVector, + uint64_t numValuesToAppend); static void sliceDataVector(ValueVector* vectorToSlice, uint64_t offset, uint64_t numValues); }; -class FixedListVector { -public: - template - static void getAsValue(ValueVector* vector, std::vector>& children, - uint64_t pos, uint64_t numElements); -}; - -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements); -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements); -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements); -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements); -template<> -void FixedListVector::getAsValue(ValueVector* vector, - std::vector>& children, uint64_t pos, uint64_t numElements); - class StructVector { public: static inline const std::vector>& getFieldVectors( @@ -234,8 +214,8 @@ class StructVector { ->getFieldVectors(); } - static inline std::shared_ptr getFieldVector( - const ValueVector* vector, struct_field_idx_t idx) { + static inline std::shared_ptr getFieldVector(const ValueVector* vector, + struct_field_idx_t idx) { return ku_dynamic_cast( vector->auxiliaryBuffer.get()) ->getFieldVectors()[idx]; @@ -275,15 +255,15 @@ class UnionVector { static inline void referenceVector(ValueVector* vector, union_field_idx_t fieldIdx, std::shared_ptr vectorToReference) { - StructVector::referenceVector( - vector, UnionType::getInternalFieldIdx(fieldIdx), std::move(vectorToReference)); + StructVector::referenceVector(vector, UnionType::getInternalFieldIdx(fieldIdx), + std::move(vectorToReference)); } static inline void setTagField(ValueVector* vector, union_field_idx_t tag) { KU_ASSERT(vector->dataType.getLogicalTypeID() == LogicalTypeID::UNION); for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - vector->setValue( - vector->state->selVector->selectedPositions[i], tag); + vector->setValue(vector->state->selVector->selectedPositions[i], + tag); } } }; diff --git a/src/include/expression_evaluator/case_evaluator.h b/src/include/expression_evaluator/case_evaluator.h index acd5c9e77a5..7c81bc9961e 100644 --- a/src/include/expression_evaluator/case_evaluator.h +++ b/src/include/expression_evaluator/case_evaluator.h @@ -24,8 +24,8 @@ struct CaseAlternativeEvaluator { void init(const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager); inline std::unique_ptr clone() const { - return make_unique( - whenEvaluator->clone(), thenEvaluator->clone()); + return make_unique(whenEvaluator->clone(), + thenEvaluator->clone()); } }; @@ -35,11 +35,11 @@ class CaseExpressionEvaluator : public ExpressionEvaluator { std::vector> alternativeEvaluators, std::unique_ptr elseEvaluator) : ExpressionEvaluator{}, expression{std::move(expression)}, - alternativeEvaluators{std::move(alternativeEvaluators)}, elseEvaluator{ - std::move(elseEvaluator)} {} + alternativeEvaluators{std::move(alternativeEvaluators)}, + elseEvaluator{std::move(elseEvaluator)} {} - void init( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void init(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; void evaluate(main::ClientContext* clientContext) override; @@ -48,8 +48,8 @@ class CaseExpressionEvaluator : public ExpressionEvaluator { std::unique_ptr clone() override; protected: - void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; private: void fillSelected(const common::SelectionVector& selVector, common::ValueVector* srcVector); diff --git a/src/include/expression_evaluator/expression_evaluator.h b/src/include/expression_evaluator/expression_evaluator.h index 6e9d7260683..29bbf57469b 100644 --- a/src/include/expression_evaluator/expression_evaluator.h +++ b/src/include/expression_evaluator/expression_evaluator.h @@ -29,8 +29,8 @@ class ExpressionEvaluator { virtual std::unique_ptr clone() = 0; protected: - virtual void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) = 0; + virtual void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) = 0; void resolveResultStateFromChildren(const std::vector& inputEvaluators); diff --git a/src/include/expression_evaluator/function_evaluator.h b/src/include/expression_evaluator/function_evaluator.h index 123c87eb539..3cb6fd83051 100644 --- a/src/include/expression_evaluator/function_evaluator.h +++ b/src/include/expression_evaluator/function_evaluator.h @@ -14,11 +14,11 @@ class FunctionExpressionEvaluator : public ExpressionEvaluator { public: FunctionExpressionEvaluator(std::shared_ptr expression, std::vector> children) - : ExpressionEvaluator{std::move(children)}, - expression{std::move(expression)}, execFunc{nullptr}, selectFunc{nullptr} {} + : ExpressionEvaluator{std::move(children)}, expression{std::move(expression)}, + execFunc{nullptr}, selectFunc{nullptr} {} - void init( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void init(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; void evaluate(main::ClientContext* clientContext) override; @@ -27,13 +27,13 @@ class FunctionExpressionEvaluator : public ExpressionEvaluator { std::unique_ptr clone() override; protected: - void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; private: std::shared_ptr expression; - function::scalar_exec_func execFunc; - function::scalar_select_func selectFunc; + function::scalar_func_exec_t execFunc; + function::scalar_func_select_t selectFunc; std::vector> parameters; }; diff --git a/src/include/expression_evaluator/literal_evaluator.h b/src/include/expression_evaluator/literal_evaluator.h index 13996ee3442..4d02e7f1495 100644 --- a/src/include/expression_evaluator/literal_evaluator.h +++ b/src/include/expression_evaluator/literal_evaluator.h @@ -25,8 +25,8 @@ class LiteralExpressionEvaluator : public ExpressionEvaluator { } protected: - void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; private: std::shared_ptr value; diff --git a/src/include/expression_evaluator/node_rel_evaluator.h b/src/include/expression_evaluator/node_rel_evaluator.h index af2b5d2639d..ce357906601 100644 --- a/src/include/expression_evaluator/node_rel_evaluator.h +++ b/src/include/expression_evaluator/node_rel_evaluator.h @@ -18,8 +18,8 @@ class NodeRelExpressionEvaluator final : public ExpressionEvaluator { void evaluate(main::ClientContext* clientContext) override; - bool select( - common::SelectionVector& /*selVector*/, main::ClientContext* /*clientContext*/) override { + bool select(common::SelectionVector& /*selVector*/, + main::ClientContext* /*clientContext*/) override { KU_UNREACHABLE; } @@ -33,8 +33,8 @@ class NodeRelExpressionEvaluator final : public ExpressionEvaluator { } private: - void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; private: std::shared_ptr nodeOrRel; diff --git a/src/include/expression_evaluator/path_evaluator.h b/src/include/expression_evaluator/path_evaluator.h index 8ae31f0444b..e0c22e650c7 100644 --- a/src/include/expression_evaluator/path_evaluator.h +++ b/src/include/expression_evaluator/path_evaluator.h @@ -16,13 +16,13 @@ class PathExpressionEvaluator final : public ExpressionEvaluator { std::vector> children) : ExpressionEvaluator{std::move(children)}, expression{std::move(expression)} {} - void init( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void init(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; void evaluate(main::ClientContext* clientContext) override; - bool select( - common::SelectionVector& /*selVector*/, main::ClientContext* /*clientContext*/) override { + bool select(common::SelectionVector& /*selVector*/, + main::ClientContext* /*clientContext*/) override { KU_UNREACHABLE; } @@ -52,8 +52,8 @@ class PathExpressionEvaluator final : public ExpressionEvaluator { std::vector relFieldVectors; }; - void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; + void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* memoryManager) override; void copyNodes(common::sel_t resultPos, bool isEmptyRels); uint64_t copyRels(common::sel_t resultPos); diff --git a/src/include/expression_evaluator/reference_evaluator.h b/src/include/expression_evaluator/reference_evaluator.h index 8f897130592..1eb2a431ed9 100644 --- a/src/include/expression_evaluator/reference_evaluator.h +++ b/src/include/expression_evaluator/reference_evaluator.h @@ -23,8 +23,8 @@ class ReferenceExpressionEvaluator : public ExpressionEvaluator { } protected: - inline void resolveResultVector( - const processor::ResultSet& resultSet, storage::MemoryManager* /*memoryManager*/) override { + inline void resolveResultVector(const processor::ResultSet& resultSet, + storage::MemoryManager* /*memoryManager*/) override { resultVector = resultSet.dataChunks[vectorPos.dataChunkPos]->valueVectors[vectorPos.valueVectorPos]; } diff --git a/src/include/extension/extension.h b/src/include/extension/extension.h index 6b7288a5d02..05529c759bb 100644 --- a/src/include/extension/extension.h +++ b/src/include/extension/extension.h @@ -38,12 +38,10 @@ struct ExtensionUtils { struct ExtensionOptions { std::unordered_map extensionOptions; - void addExtensionOption( - std::string name, common::LogicalTypeID type, common::Value defaultValue); + void addExtensionOption(std::string name, common::LogicalTypeID type, + common::Value defaultValue); main::ExtensionOption* getExtensionOption(std::string name); - - std::unordered_map& getExtensionOptions(); }; } // namespace extension diff --git a/src/include/function/aggregate/avg.h b/src/include/function/aggregate/avg.h index 4fc0467918c..c42d3b9d53a 100644 --- a/src/include/function/aggregate/avg.h +++ b/src/include/function/aggregate/avg.h @@ -48,8 +48,8 @@ struct AvgFunction { updateSingleValue(reinterpret_cast(state_), input, pos, multiplicity); } - static void updateSingleValue( - AvgState* state, common::ValueVector* input, uint32_t pos, uint64_t multiplicity) { + static void updateSingleValue(AvgState* state, common::ValueVector* input, uint32_t pos, + uint64_t multiplicity) { T val = input->getValue(pos); for (auto i = 0u; i < multiplicity; ++i) { if (state->isNull) { @@ -62,8 +62,8 @@ struct AvgFunction { state->count += multiplicity; } - static void combine( - uint8_t* state_, uint8_t* otherState_, storage::MemoryManager* /*memoryManager*/) { + static void combine(uint8_t* state_, uint8_t* otherState_, + storage::MemoryManager* /*memoryManager*/) { auto* otherState = reinterpret_cast(otherState_); if (otherState->isNull) { return; diff --git a/src/include/function/aggregate/base_count.h b/src/include/function/aggregate/base_count.h index 4181b55c5d3..47dff0289a5 100644 --- a/src/include/function/aggregate/base_count.h +++ b/src/include/function/aggregate/base_count.h @@ -23,8 +23,8 @@ struct BaseCountFunction { return state; } - static void combine( - uint8_t* state_, uint8_t* otherState_, storage::MemoryManager* /*memoryManager*/) { + static void combine(uint8_t* state_, uint8_t* otherState_, + storage::MemoryManager* /*memoryManager*/) { auto state = reinterpret_cast(state_); auto otherState = reinterpret_cast(otherState_); state->count += otherState->count; diff --git a/src/include/function/aggregate/collect.h b/src/include/function/aggregate/collect.h index 1474c0968cd..18128121037 100644 --- a/src/include/function/aggregate/collect.h +++ b/src/include/function/aggregate/collect.h @@ -2,12 +2,12 @@ #include "function/aggregate_function.h" #include "processor/result/factorized_table.h" -#include "storage/storage_utils.h" namespace kuzu { namespace function { struct CollectFunction { + static constexpr const char* name = "COLLECT"; struct CollectState : public AggregateState { CollectState() : factorizedTable{nullptr} {} @@ -18,8 +18,8 @@ struct CollectFunction { outputVector->setValue(pos, listEntry); auto outputDataVector = common::ListVector::getDataVector(outputVector); for (auto i = 0u; i < listEntry.size; i++) { - outputDataVector->copyFromRowData( - listEntry.offset + i, factorizedTable->getTuple(i)); + outputDataVector->copyFromRowData(listEntry.offset + i, + factorizedTable->getTuple(i)); } // CollectStates are stored in factorizedTable entries. When the factorizedTable is // destructed, the destructor of CollectStates won't be called. Therefore, we need to @@ -30,82 +30,29 @@ struct CollectFunction { std::unique_ptr factorizedTable; }; - static std::unique_ptr initialize() { return std::make_unique(); } + static std::unique_ptr initialize(); static void updateAll(uint8_t* state_, common::ValueVector* input, uint64_t multiplicity, - storage::MemoryManager* memoryManager) { - KU_ASSERT(!input->state->isFlat()); - auto state = reinterpret_cast(state_); - if (input->hasNoNullsGuarantee()) { - for (auto i = 0u; i < input->state->selVector->selectedSize; ++i) { - auto pos = input->state->selVector->selectedPositions[i]; - updateSingleValue(state, input, pos, multiplicity, memoryManager); - } - } else { - for (auto i = 0u; i < input->state->selVector->selectedSize; ++i) { - auto pos = input->state->selVector->selectedPositions[i]; - if (!input->isNull(pos)) { - updateSingleValue(state, input, pos, multiplicity, memoryManager); - } - } - } - } + storage::MemoryManager* memoryManager); - static inline void updatePos(uint8_t* state_, common::ValueVector* input, uint64_t multiplicity, - uint32_t pos, storage::MemoryManager* memoryManager) { - auto state = reinterpret_cast(state_); - updateSingleValue(state, input, pos, multiplicity, memoryManager); - } + static void updatePos(uint8_t* state_, common::ValueVector* input, uint64_t multiplicity, + uint32_t pos, storage::MemoryManager* memoryManager); - static void initCollectStateIfNecessary( - CollectState* state, storage::MemoryManager* memoryManager, common::LogicalType& dataType) { - if (state->factorizedTable == nullptr) { - auto tableSchema = std::make_unique(); - tableSchema->appendColumn( - std::make_unique(false /* isUnflat */, - 0 /* dataChunkPos */, storage::StorageUtils::getDataTypeSize(dataType))); - state->factorizedTable = - std::make_unique(memoryManager, std::move(tableSchema)); - } - } + static void initCollectStateIfNecessary(CollectState* state, + storage::MemoryManager* memoryManager, common::LogicalType& dataType); static void updateSingleValue(CollectState* state, common::ValueVector* input, uint32_t pos, - uint64_t multiplicity, storage::MemoryManager* memoryManager) { - initCollectStateIfNecessary(state, memoryManager, input->dataType); - for (auto i = 0u; i < multiplicity; ++i) { - auto tuple = state->factorizedTable->appendEmptyTuple(); - state->isNull = false; - input->copyToRowData(pos, tuple, state->factorizedTable->getInMemOverflowBuffer()); - } - } + uint64_t multiplicity, storage::MemoryManager* memoryManager); - static void combine( - uint8_t* state_, uint8_t* otherState_, storage::MemoryManager* /*memoryManager*/) { - auto otherState = reinterpret_cast(otherState_); - if (otherState->isNull) { - return; - } - auto state = reinterpret_cast(state_); - if (state->isNull) { - state->factorizedTable = std::move(otherState->factorizedTable); - state->isNull = false; - } else { - state->factorizedTable->merge(*otherState->factorizedTable); - } - otherState->factorizedTable.reset(); - } + static void combine(uint8_t* state_, uint8_t* otherState_, + storage::MemoryManager* /*memoryManager*/); static void finalize(uint8_t* /*state_*/) {} - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* definition) { - KU_ASSERT(arguments.size() == 1); - auto aggFuncDefinition = reinterpret_cast(definition); - aggFuncDefinition->parameterTypeIDs[0] = arguments[0]->dataType.getLogicalTypeID(); - auto returnType = common::LogicalType::VAR_LIST( - std::make_unique(arguments[0]->dataType)); - return std::make_unique(std::move(returnType)); - } + static std::unique_ptr bindFunc(const binder::expression_vector& arguments, + Function* definition); + + static function_set getFunctionSet(); }; } // namespace function diff --git a/src/include/function/aggregate/count.h b/src/include/function/aggregate/count.h index 30d7c8d9ad8..e8aaf9839e1 100644 --- a/src/include/function/aggregate/count.h +++ b/src/include/function/aggregate/count.h @@ -6,6 +6,7 @@ namespace kuzu { namespace function { struct CountFunction : public BaseCountFunction { + static constexpr const char* name = "COUNT"; static void updateAll(uint8_t* state_, common::ValueVector* input, uint64_t multiplicity, storage::MemoryManager* memoryManager); @@ -17,6 +18,8 @@ struct CountFunction : public BaseCountFunction { } static void paramRewriteFunc(binder::expression_vector& arguments); + + static function_set getFunctionSet(); }; } // namespace function diff --git a/src/include/function/aggregate/count_star.h b/src/include/function/aggregate/count_star.h index 4612b26bb61..b45959dff79 100644 --- a/src/include/function/aggregate/count_star.h +++ b/src/include/function/aggregate/count_star.h @@ -6,22 +6,15 @@ namespace kuzu { namespace function { struct CountStarFunction : public BaseCountFunction { + static constexpr const char* name = "COUNT_STAR"; static void updateAll(uint8_t* state_, common::ValueVector* input, uint64_t multiplicity, - storage::MemoryManager* /*memoryManager*/) { - auto state = reinterpret_cast(state_); - KU_ASSERT(input == nullptr); - (void)input; - state->count += multiplicity; - } + storage::MemoryManager* /*memoryManager*/); static void updatePos(uint8_t* state_, common::ValueVector* input, uint64_t multiplicity, - uint32_t /*pos*/, storage::MemoryManager* /*memoryManager*/) { - auto state = reinterpret_cast(state_); - KU_ASSERT(input == nullptr); - (void)input; - state->count += multiplicity; - } + uint32_t /*pos*/, storage::MemoryManager* /*memoryManager*/); + + static function_set getFunctionSet(); }; } // namespace function diff --git a/src/include/function/aggregate/min_max.h b/src/include/function/aggregate/min_max.h index a5c83f9e068..bcebb5a7848 100644 --- a/src/include/function/aggregate/min_max.h +++ b/src/include/function/aggregate/min_max.h @@ -66,8 +66,8 @@ struct MinMaxFunction { } template - static void combine( - uint8_t* state_, uint8_t* otherState_, storage::MemoryManager* memoryManager) { + static void combine(uint8_t* state_, uint8_t* otherState_, + storage::MemoryManager* memoryManager) { auto* otherState = reinterpret_cast(otherState_); if (otherState->isNull) { return; @@ -91,8 +91,8 @@ struct MinMaxFunction { }; template<> -void MinMaxFunction::MinMaxState::setVal( - common::ku_string_t& val_, storage::MemoryManager* memoryManager) { +void MinMaxFunction::MinMaxState::setVal(common::ku_string_t& val_, + storage::MemoryManager* memoryManager) { if (overflowBuffer == nullptr) { overflowBuffer = std::make_unique(memoryManager); } diff --git a/src/include/function/aggregate/sum.h b/src/include/function/aggregate/sum.h index 2a991e24d83..02d1f47823c 100644 --- a/src/include/function/aggregate/sum.h +++ b/src/include/function/aggregate/sum.h @@ -46,8 +46,8 @@ struct SumFunction { updateSingleValue(state, input, pos, multiplicity); } - static void updateSingleValue( - SumState* state, common::ValueVector* input, uint32_t pos, uint64_t multiplicity) { + static void updateSingleValue(SumState* state, common::ValueVector* input, uint32_t pos, + uint64_t multiplicity) { T val = input->getValue(pos); for (auto j = 0u; j < multiplicity; ++j) { if (state->isNull) { @@ -59,8 +59,8 @@ struct SumFunction { } } - static void combine( - uint8_t* state_, uint8_t* otherState_, storage::MemoryManager* /*memoryManager*/) { + static void combine(uint8_t* state_, uint8_t* otherState_, + storage::MemoryManager* /*memoryManager*/) { auto* otherState = reinterpret_cast(otherState_); if (otherState->isNull) { return; diff --git a/src/include/function/aggregate_function.h b/src/include/function/aggregate_function.h index ebd939f9815..864afbee2c6 100644 --- a/src/include/function/aggregate_function.h +++ b/src/include/function/aggregate_function.h @@ -75,8 +75,8 @@ struct AggregateFunction final : public BaseScalarFunction { return updatePosFunc(state, input, multiplicity, pos, memoryManager); } - inline void combineState( - uint8_t* state, uint8_t* otherState, storage::MemoryManager* memoryManager) const { + inline void combineState(uint8_t* state, uint8_t* otherState, + storage::MemoryManager* memoryManager) const { return combineFunc(state, otherState, memoryManager); } @@ -122,14 +122,38 @@ class AggregateFunctionUtil { common::LogicalTypeID inputType, common::LogicalTypeID resultType, bool isDistinct); static std::unique_ptr getAvgFunc(const std::string name, common::LogicalTypeID inputType, common::LogicalTypeID resultType, bool isDistinct); - static std::unique_ptr getMinFunc( - common::LogicalTypeID inputType, bool isDistinct); - static std::unique_ptr getMaxFunc( - common::LogicalTypeID inputType, bool isDistinct); + static std::unique_ptr getMinFunc(common::LogicalTypeID inputType, + bool isDistinct); + static std::unique_ptr getMaxFunc(common::LogicalTypeID inputType, + bool isDistinct); template static std::unique_ptr getMinMaxFunction(const std::string name, common::LogicalTypeID inputType, common::LogicalTypeID resultType, bool isDistinct); }; +struct AggregateSumFunction { + static constexpr const char* name = "SUM"; + + static function_set getFunctionSet(); +}; + +struct AggregateAvgFunction { + static constexpr const char* name = "AVG"; + + static function_set getFunctionSet(); +}; + +struct AggregateMinFunction { + static constexpr const char* name = "MIN"; + + static function_set getFunctionSet(); +}; + +struct AggregateMaxFunction { + static constexpr const char* name = "MAX"; + + static function_set getFunctionSet(); +}; + } // namespace function } // namespace kuzu diff --git a/src/include/function/arithmetic/vector_arithmetic_functions.h b/src/include/function/arithmetic/vector_arithmetic_functions.h index 99adf58cd89..2de1215a51e 100644 --- a/src/include/function/arithmetic/vector_arithmetic_functions.h +++ b/src/include/function/arithmetic/vector_arithmetic_functions.h @@ -1,280 +1,235 @@ #pragma once -#include "common/types/int128_t.h" -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { -struct ArithmeticFunction { - template - static std::unique_ptr getUnaryFunction( - std::string name, common::LogicalTypeID operandTypeID) { - function::scalar_exec_func execFunc; - getUnaryExecFunc(operandTypeID, execFunc); - return std::make_unique(std::move(name), - std::vector{operandTypeID}, operandTypeID, execFunc); - } - - template - static std::unique_ptr getUnaryFunction( - std::string name, common::LogicalTypeID operandTypeID, common::LogicalTypeID resultTypeID) { - return std::make_unique(std::move(name), - std::vector{operandTypeID}, resultTypeID, - ScalarFunction::UnaryExecFunction); - } - - template - static inline std::unique_ptr getBinaryFunction( - std::string name, common::LogicalTypeID operandTypeID) { - function::scalar_exec_func execFunc; - getBinaryExecFunc(operandTypeID, execFunc); - return std::make_unique(std::move(name), - std::vector{operandTypeID, operandTypeID}, operandTypeID, - execFunc); - } - - template - static inline std::unique_ptr getBinaryFunction( - std::string name, common::LogicalTypeID operandTypeID, common::LogicalTypeID resultTypeID) { - return std::make_unique(std::move(name), - std::vector{operandTypeID, operandTypeID}, resultTypeID, - ScalarFunction::BinaryExecFunction); - } - -private: - template - static void getUnaryExecFunc(common::LogicalTypeID operandTypeID, scalar_exec_func& func) { - switch (operandTypeID) { - case common::LogicalTypeID::SERIAL: - case common::LogicalTypeID::INT64: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::INT32: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::INT16: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::INT8: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::UINT64: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::UINT32: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::UINT16: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::UINT8: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::INT128: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::DOUBLE: { - func = ScalarFunction::UnaryExecFunction; - } break; - case common::LogicalTypeID::FLOAT: { - func = ScalarFunction::UnaryExecFunction; - } break; - default: - KU_UNREACHABLE; - } - } - - template - static void getBinaryExecFunc(common::LogicalTypeID operandTypeID, scalar_exec_func& func) { - switch (operandTypeID) { - case common::LogicalTypeID::SERIAL: - case common::LogicalTypeID::INT64: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::INT32: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::INT16: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::INT8: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::UINT64: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::UINT32: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::UINT16: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::UINT8: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::INT128: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::DOUBLE: { - func = ScalarFunction::BinaryExecFunction; - } break; - case common::LogicalTypeID::FLOAT: { - func = ScalarFunction::BinaryExecFunction; - } break; - default: - KU_UNREACHABLE; - } - } -}; - struct AddFunction { + static constexpr const char* name = "+"; + static function_set getFunctionSet(); }; struct SubtractFunction { + static constexpr const char* name = "-"; + static function_set getFunctionSet(); }; struct MultiplyFunction { + static constexpr const char* name = "*"; + static function_set getFunctionSet(); }; struct DivideFunction { + static constexpr const char* name = "/"; + static function_set getFunctionSet(); }; struct ModuloFunction { + static constexpr const char* name = "%"; + static function_set getFunctionSet(); }; struct PowerFunction { + static constexpr const char* name = "^"; + + static constexpr const char* alias = "POW"; + static function_set getFunctionSet(); }; struct AbsFunction { + static constexpr const char* name = "ABS"; + static function_set getFunctionSet(); }; struct AcosFunction { + static constexpr const char* name = "ACOS"; + static function_set getFunctionSet(); }; struct AsinFunction { + static constexpr const char* name = "ASIN"; + static function_set getFunctionSet(); }; struct AtanFunction { + static constexpr const char* name = "ATAN"; + static function_set getFunctionSet(); }; struct Atan2Function { + static constexpr const char* name = "ATAN2"; + static function_set getFunctionSet(); }; struct BitwiseXorFunction { + static constexpr const char* name = "BITWISE_XOR"; + static function_set getFunctionSet(); }; struct BitwiseAndFunction { + static constexpr const char* name = "BITWISE_AND"; + static function_set getFunctionSet(); }; struct BitwiseOrFunction { + static constexpr const char* name = "BITWISE_OR"; + static function_set getFunctionSet(); }; struct BitShiftLeftFunction { + static constexpr const char* name = "BITSHIFT_LEFT"; + static function_set getFunctionSet(); }; struct BitShiftRightFunction { + static constexpr const char* name = "BITSHIFT_RIGHT"; + static function_set getFunctionSet(); }; struct CbrtFunction { + static constexpr const char* name = "CBRT"; + static function_set getFunctionSet(); }; struct CeilFunction { + static constexpr const char* name = "CEIL"; + + static constexpr const char* alias = "CEILING"; + static function_set getFunctionSet(); }; struct CosFunction { + static constexpr const char* name = "COS"; + static function_set getFunctionSet(); }; struct CotFunction { + static constexpr const char* name = "COT"; + static function_set getFunctionSet(); }; struct DegreesFunction { + static constexpr const char* name = "DEGREES"; + static function_set getFunctionSet(); }; struct EvenFunction { + static constexpr const char* name = "EVEN"; + static function_set getFunctionSet(); }; struct FactorialFunction { + static constexpr const char* name = "FACTORIAL"; + static function_set getFunctionSet(); }; struct FloorFunction { + static constexpr const char* name = "FLOOR"; + static function_set getFunctionSet(); }; struct GammaFunction { + static constexpr const char* name = "GAMMA"; + static function_set getFunctionSet(); }; struct LgammaFunction { + static constexpr const char* name = "LGAMMA"; + static function_set getFunctionSet(); }; struct LnFunction { + static constexpr const char* name = "LN"; + static function_set getFunctionSet(); }; struct LogFunction { + static constexpr const char* name = "LOG"; + + static constexpr const char* alias = "LOG10"; + static function_set getFunctionSet(); }; struct Log2Function { + static constexpr const char* name = "LOG2"; + static function_set getFunctionSet(); }; struct NegateFunction { + static constexpr const char* name = "NEGATE"; + static function_set getFunctionSet(); }; struct PiFunction { + static constexpr const char* name = "PI"; + static function_set getFunctionSet(); }; struct RadiansFunction { + static constexpr const char* name = "RADIANS"; + static function_set getFunctionSet(); }; struct RoundFunction { + static constexpr const char* name = "ROUND"; + static function_set getFunctionSet(); }; struct SinFunction { + static constexpr const char* name = "SIN"; + static function_set getFunctionSet(); }; struct SignFunction { + static constexpr const char* name = "SIGN"; + static function_set getFunctionSet(); }; struct SqrtFunction { + static constexpr const char* name = "SQRT"; + static function_set getFunctionSet(); }; struct TanFunction { + static constexpr const char* name = "TAN"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/array/functions/array_cosine_similarity.h b/src/include/function/array/functions/array_cosine_similarity.h new file mode 100644 index 00000000000..3130eecaa3a --- /dev/null +++ b/src/include/function/array/functions/array_cosine_similarity.h @@ -0,0 +1,33 @@ +#pragma once + +#include "math.h" + +#include "common/vector/value_vector.h" + +namespace kuzu { +namespace function { + +struct ArrayCosineSimilarity { + template + static inline void operation(common::list_entry_t& left, common::list_entry_t& right, T& result, + common::ValueVector& leftVector, common::ValueVector& rightVector, + common::ValueVector& /*resultVector*/) { + auto leftElements = (T*)common::ListVector::getListValues(&leftVector, left); + auto rightElements = (T*)common::ListVector::getListValues(&rightVector, right); + T distance = 0; + T normLeft = 0; + T normRight = 0; + for (auto i = 0u; i < left.size; i++) { + auto x = leftElements[i]; + auto y = rightElements[i]; + distance += x * y; + normLeft += x * x; + normRight += y * y; + } + auto similarity = distance / (std::sqrt(normLeft) * std::sqrt(normRight)); + result = std::max(static_cast(-1), std::min(similarity, static_cast(1))); + } +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/array/functions/array_cross_product.h b/src/include/function/array/functions/array_cross_product.h new file mode 100644 index 00000000000..f30c1ba6340 --- /dev/null +++ b/src/include/function/array/functions/array_cross_product.h @@ -0,0 +1,24 @@ +#pragma once + +#include "common/vector/value_vector.h" + +namespace kuzu { +namespace function { + +template +struct ArrayCrossProduct { + static inline void operation(common::list_entry_t& left, common::list_entry_t& right, + common::list_entry_t& result, common::ValueVector& leftVector, + common::ValueVector& rightVector, common::ValueVector& resultVector) { + auto leftElements = (T*)common::ListVector::getListValues(&leftVector, left); + auto rightElements = (T*)common::ListVector::getListValues(&rightVector, right); + result = common::ListVector::addList(&resultVector, left.size); + auto resultElements = (T*)common::ListVector::getListValues(&resultVector, result); + resultElements[0] = leftElements[1] * rightElements[2] - leftElements[2] * rightElements[1]; + resultElements[1] = leftElements[2] * rightElements[0] - leftElements[0] * rightElements[2]; + resultElements[2] = leftElements[0] * rightElements[1] - leftElements[1] * rightElements[0]; + } +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/array/functions/array_distance.h b/src/include/function/array/functions/array_distance.h new file mode 100644 index 00000000000..1975343b336 --- /dev/null +++ b/src/include/function/array/functions/array_distance.h @@ -0,0 +1,27 @@ +#pragma once + +#include "math.h" + +#include "common/vector/value_vector.h" + +namespace kuzu { +namespace function { + +struct ArrayDistance { + template + static inline void operation(common::list_entry_t& left, common::list_entry_t& right, T& result, + common::ValueVector& leftVector, common::ValueVector& rightVector, + common::ValueVector& /*resultVector*/) { + auto leftElements = (T*)common::ListVector::getListValues(&leftVector, left); + auto rightElements = (T*)common::ListVector::getListValues(&rightVector, right); + result = 0; + for (auto i = 0u; i < left.size; i++) { + auto diff = leftElements[i] - rightElements[i]; + result += diff * diff; + } + result = std::sqrt(result); + } +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/array/functions/array_inner_product.h b/src/include/function/array/functions/array_inner_product.h new file mode 100644 index 00000000000..d1853e5cf7d --- /dev/null +++ b/src/include/function/array/functions/array_inner_product.h @@ -0,0 +1,23 @@ +#pragma once + +#include "common/vector/value_vector.h" + +namespace kuzu { +namespace function { + +struct ArrayInnerProduct { + template + static inline void operation(common::list_entry_t& left, common::list_entry_t& right, T& result, + common::ValueVector& leftVector, common::ValueVector& rightVector, + common::ValueVector& /*resultVector*/) { + auto leftElements = (T*)common::ListVector::getListValues(&leftVector, left); + auto rightElements = (T*)common::ListVector::getListValues(&rightVector, right); + result = 0; + for (auto i = 0u; i < left.size; i++) { + result += leftElements[i] * rightElements[i]; + } + } +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/array/vector_array_functions.h b/src/include/function/array/vector_array_functions.h new file mode 100644 index 00000000000..3f1ef650643 --- /dev/null +++ b/src/include/function/array/vector_array_functions.h @@ -0,0 +1,80 @@ +#pragma once + +#include "function/function.h" +#include "function/list/vector_list_functions.h" + +namespace kuzu { +namespace function { + +struct ArrayValueFunction { + static constexpr const char* name = "ARRAY_VALUE"; + + static function_set getFunctionSet(); +}; + +struct ArrayCrossProductFunction { + static constexpr const char* name = "ARRAY_CROSS_PRODUCT"; + + static function_set getFunctionSet(); +}; + +struct ArrayCosineSimilarityFunction { + static constexpr const char* name = "ARRAY_COSINE_SIMILARITY"; + + static function_set getFunctionSet(); +}; + +struct ArrayDistanceFunction { + static constexpr const char* name = "ARRAY_DISTANCE"; + + static function_set getFunctionSet(); +}; + +struct ArrayInnerProductFunction { + static constexpr const char* name = "ARRAY_INNER_PRODUCT"; + + static function_set getFunctionSet(); +}; + +struct ArrayDotProductFunction { + static constexpr const char* name = "ARRAY_DOT_PRODUCT"; + + static function_set getFunctionSet(); +}; + +struct ArrayConcatFunction : public ListConcatFunction { + static constexpr const char* name = "ARRAY_CONCAT"; + + static constexpr const char* alias = "ARRAY_CAT"; +}; + +struct ArrayAppendFunction : public ListAppendFunction { + static constexpr const char* name = "ARRAY_APPEND"; + + static constexpr const char* alias = "ARRAY_PUSH_BACK"; +}; + +struct ArrayPrependFunction : public ListPrependFunction { + static constexpr const char* name = "ARRAY_PREPEND"; + + static constexpr const char* alias = "ARRAY_PUSH_FRONT"; +}; + +struct ArrayPositionFunction : public ListPositionFunction { + static constexpr const char* name = "ARRAY_POSITION"; + + static constexpr const char* alias = "ARRAY_INDEXOF"; +}; + +struct ArrayContainsFunction : public ListContainsFunction { + static constexpr const char* name = "ARRAY_CONTAINS"; + + static constexpr const char* alias = "ARRAY_HAS"; +}; + +struct ArraySliceFunction : public ListSliceFunction { + static constexpr const char* name = "ARRAY_SLICE"; +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/binary_function_executor.h b/src/include/function/binary_function_executor.h index b3399910ee4..c41afd9df94 100644 --- a/src/include/function/binary_function_executor.h +++ b/src/include/function/binary_function_executor.h @@ -86,8 +86,8 @@ struct BinaryFunctionExecutor { auto resPos = result.state->selVector->selectedPositions[0]; result.setNull(resPos, left.isNull(lPos) || right.isNull(rPos)); if (!result.isNull(resPos)) { - executeOnValue( - left, right, result, lPos, rPos, resPos, dataPtr); + executeOnValue(left, right, + result, lPos, rPos, resPos, dataPtr); } } @@ -101,14 +101,14 @@ struct BinaryFunctionExecutor { } else if (right.hasNoNullsGuarantee()) { if (right.state->selVector->isUnfiltered()) { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { - executeOnValue( - left, right, result, lPos, i, i, dataPtr); + executeOnValue(left, + right, result, lPos, i, i, dataPtr); } } else { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { auto rPos = right.state->selVector->selectedPositions[i]; - executeOnValue( - left, right, result, lPos, rPos, rPos, dataPtr); + executeOnValue(left, + right, result, lPos, rPos, rPos, dataPtr); } } } else { @@ -116,8 +116,8 @@ struct BinaryFunctionExecutor { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { result.setNull(i, right.isNull(i)); // left is always not null if (!result.isNull(i)) { - executeOnValue( - left, right, result, lPos, i, i, dataPtr); + executeOnValue(left, + right, result, lPos, i, i, dataPtr); } } } else { @@ -125,8 +125,8 @@ struct BinaryFunctionExecutor { auto rPos = right.state->selVector->selectedPositions[i]; result.setNull(rPos, right.isNull(rPos)); // left is always not null if (!result.isNull(rPos)) { - executeOnValue( - left, right, result, lPos, rPos, rPos, dataPtr); + executeOnValue(left, + right, result, lPos, rPos, rPos, dataPtr); } } } @@ -143,14 +143,14 @@ struct BinaryFunctionExecutor { } else if (left.hasNoNullsGuarantee()) { if (left.state->selVector->isUnfiltered()) { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { - executeOnValue( - left, right, result, i, rPos, i, dataPtr); + executeOnValue(left, + right, result, i, rPos, i, dataPtr); } } else { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { auto lPos = left.state->selVector->selectedPositions[i]; - executeOnValue( - left, right, result, lPos, rPos, lPos, dataPtr); + executeOnValue(left, + right, result, lPos, rPos, lPos, dataPtr); } } } else { @@ -158,8 +158,8 @@ struct BinaryFunctionExecutor { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { result.setNull(i, left.isNull(i)); // right is always not null if (!result.isNull(i)) { - executeOnValue( - left, right, result, i, rPos, i, dataPtr); + executeOnValue(left, + right, result, i, rPos, i, dataPtr); } } } else { @@ -167,8 +167,8 @@ struct BinaryFunctionExecutor { auto lPos = left.state->selVector->selectedPositions[i]; result.setNull(lPos, left.isNull(lPos)); // right is always not null if (!result.isNull(lPos)) { - executeOnValue( - left, right, result, lPos, rPos, lPos, dataPtr); + executeOnValue(left, + right, result, lPos, rPos, lPos, dataPtr); } } } @@ -183,14 +183,14 @@ struct BinaryFunctionExecutor { if (left.hasNoNullsGuarantee() && right.hasNoNullsGuarantee()) { if (result.state->selVector->isUnfiltered()) { for (uint64_t i = 0; i < result.state->selVector->selectedSize; i++) { - executeOnValue( - left, right, result, i, i, i, dataPtr); + executeOnValue(left, + right, result, i, i, i, dataPtr); } } else { for (uint64_t i = 0; i < result.state->selVector->selectedSize; i++) { auto pos = result.state->selVector->selectedPositions[i]; - executeOnValue( - left, right, result, pos, pos, pos, dataPtr); + executeOnValue(left, + right, result, pos, pos, pos, dataPtr); } } } else { @@ -198,8 +198,8 @@ struct BinaryFunctionExecutor { for (uint64_t i = 0; i < result.state->selVector->selectedSize; i++) { result.setNull(i, left.isNull(i) || right.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - left, right, result, i, i, i, dataPtr); + executeOnValue(left, + right, result, i, i, i, dataPtr); } } } else { @@ -207,8 +207,8 @@ struct BinaryFunctionExecutor { auto pos = result.state->selVector->selectedPositions[i]; result.setNull(pos, left.isNull(pos) || right.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - left, right, result, pos, pos, pos, dataPtr); + executeOnValue(left, + right, result, pos, pos, pos, dataPtr); } } } @@ -221,53 +221,53 @@ struct BinaryFunctionExecutor { common::ValueVector& result, void* dataPtr) { result.resetAuxiliaryBuffer(); if (left.state->isFlat() && right.state->isFlat()) { - executeBothFlat( - left, right, result, dataPtr); + executeBothFlat(left, right, + result, dataPtr); } else if (left.state->isFlat() && !right.state->isFlat()) { - executeFlatUnFlat( - left, right, result, dataPtr); + executeFlatUnFlat(left, right, + result, dataPtr); } else if (!left.state->isFlat() && right.state->isFlat()) { - executeUnFlatFlat( - left, right, result, dataPtr); + executeUnFlatFlat(left, right, + result, dataPtr); } else if (!left.state->isFlat() && !right.state->isFlat()) { - executeBothUnFlat( - left, right, result, dataPtr); + executeBothUnFlat(left, right, + result, dataPtr); } else { KU_ASSERT(false); } } template - static void execute( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { - executeSwitch( - left, right, result, nullptr /* dataPtr */); + static void execute(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { + executeSwitch(left, right, + result, nullptr /* dataPtr */); } template - static void executeString( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { - executeSwitch( - left, right, result, nullptr /* dataPtr */); + static void executeString(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { + executeSwitch(left, + right, result, nullptr /* dataPtr */); } template - static void executeListStruct( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void executeListStruct(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { executeSwitch( left, right, result, nullptr /* dataPtr */); } template - static void executeListExtract( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void executeListExtract(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { executeSwitch( left, right, result, nullptr /* dataPtr */); } template - static void executeComparison( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void executeComparison(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { executeSwitch( left, right, result, nullptr /* dataPtr */); } @@ -275,8 +275,8 @@ struct BinaryFunctionExecutor { template static void executeUDF(common::ValueVector& left, common::ValueVector& right, common::ValueVector& result, void* dataPtr) { - executeSwitch( - left, right, result, dataPtr); + executeSwitch(left, + right, result, dataPtr); } struct BinarySelectWrapper { @@ -321,32 +321,32 @@ struct BinaryFunctionExecutor { } template - static bool selectFlatUnFlat( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectFlatUnFlat(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { auto lPos = left.state->selVector->selectedPositions[0]; uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionsBuffer = selVector.getMultableBuffer(); if (left.isNull(lPos)) { return numSelectedValues; } else if (right.hasNoNullsGuarantee()) { if (right.state->selVector->isUnfiltered()) { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { - selectOnValue( - left, right, lPos, i, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, lPos, i, + i, numSelectedValues, selectedPositionsBuffer); } } else { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { auto rPos = right.state->selVector->selectedPositions[i]; - selectOnValue( - left, right, lPos, rPos, rPos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, lPos, + rPos, rPos, numSelectedValues, selectedPositionsBuffer); } } } else { if (right.state->selVector->isUnfiltered()) { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { if (!right.isNull(i)) { - selectOnValue( - left, right, lPos, i, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, + lPos, i, i, numSelectedValues, selectedPositionsBuffer); } } } else { @@ -364,32 +364,32 @@ struct BinaryFunctionExecutor { } template - static bool selectUnFlatFlat( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectUnFlatFlat(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { auto rPos = right.state->selVector->selectedPositions[0]; uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionsBuffer = selVector.getMultableBuffer(); if (right.isNull(rPos)) { return numSelectedValues; } else if (left.hasNoNullsGuarantee()) { if (left.state->selVector->isUnfiltered()) { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { - selectOnValue( - left, right, i, rPos, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, i, rPos, + i, numSelectedValues, selectedPositionsBuffer); } } else { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { auto lPos = left.state->selVector->selectedPositions[i]; - selectOnValue( - left, right, lPos, rPos, lPos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, lPos, + rPos, lPos, numSelectedValues, selectedPositionsBuffer); } } } else { if (left.state->selVector->isUnfiltered()) { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { if (!left.isNull(i)) { - selectOnValue( - left, right, i, rPos, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, i, + rPos, i, numSelectedValues, selectedPositionsBuffer); } } } else { @@ -408,21 +408,21 @@ struct BinaryFunctionExecutor { // Right, left, and result vectors share the same selectedPositions. template - static bool selectBothUnFlat( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectBothUnFlat(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionsBuffer = selVector.getMultableBuffer(); if (left.hasNoNullsGuarantee() && right.hasNoNullsGuarantee()) { if (left.state->selVector->isUnfiltered()) { for (auto i = 0u; i < left.state->selVector->selectedSize; i++) { - selectOnValue( - left, right, i, i, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, i, i, i, + numSelectedValues, selectedPositionsBuffer); } } else { for (auto i = 0u; i < left.state->selVector->selectedSize; i++) { auto pos = left.state->selVector->selectedPositions[i]; - selectOnValue( - left, right, pos, pos, pos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, pos, + pos, pos, numSelectedValues, selectedPositionsBuffer); } } } else { @@ -430,8 +430,8 @@ struct BinaryFunctionExecutor { for (uint64_t i = 0; i < left.state->selVector->selectedSize; i++) { auto isNull = left.isNull(i) || right.isNull(i); if (!isNull) { - selectOnValue( - left, right, i, i, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, i, + i, i, numSelectedValues, selectedPositionsBuffer); } } } else { @@ -439,8 +439,8 @@ struct BinaryFunctionExecutor { auto pos = left.state->selVector->selectedPositions[i]; auto isNull = left.isNull(pos) || right.isNull(pos); if (!isNull) { - selectOnValue( - left, right, pos, pos, pos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, pos, + pos, pos, numSelectedValues, selectedPositionsBuffer); } } } @@ -451,29 +451,29 @@ struct BinaryFunctionExecutor { // BOOLEAN (AND, OR, XOR) template - static bool select( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool select(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { if (left.state->isFlat() && right.state->isFlat()) { return selectBothFlat(left, right); } else if (left.state->isFlat() && !right.state->isFlat()) { - return selectFlatUnFlat( - left, right, selVector); + return selectFlatUnFlat(left, right, + selVector); } else if (!left.state->isFlat() && right.state->isFlat()) { - return selectUnFlatFlat( - left, right, selVector); + return selectUnFlatFlat(left, right, + selVector); } else { - return selectBothUnFlat( - left, right, selVector); + return selectBothUnFlat(left, right, + selVector); } } // COMPARISON (GT, GTE, LT, LTE, EQ, NEQ) template - static bool selectComparison( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectComparison(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { if (left.state->isFlat() && right.state->isFlat()) { - return selectBothFlat( - left, right); + return selectBothFlat(left, + right); } else if (left.state->isFlat() && !right.state->isFlat()) { return selectFlatUnFlat( left, right, selVector); diff --git a/src/include/function/blob/functions/decode_function.h b/src/include/function/blob/functions/decode_function.h index 0f07e8956cd..95ceb9062db 100644 --- a/src/include/function/blob/functions/decode_function.h +++ b/src/include/function/blob/functions/decode_function.h @@ -8,8 +8,8 @@ namespace kuzu { namespace function { struct Decode { - static inline void operation( - common::blob_t& input, common::ku_string_t& result, common::ValueVector& resultVector) { + static inline void operation(common::blob_t& input, common::ku_string_t& result, + common::ValueVector& resultVector) { if (utf8proc::Utf8Proc::analyze(reinterpret_cast(input.value.getData()), input.value.len) == utf8proc::UnicodeType::INVALID) { throw common::RuntimeException( diff --git a/src/include/function/blob/functions/encode_function.h b/src/include/function/blob/functions/encode_function.h index 39d07563862..abcc282287d 100644 --- a/src/include/function/blob/functions/encode_function.h +++ b/src/include/function/blob/functions/encode_function.h @@ -7,8 +7,8 @@ namespace kuzu { namespace function { struct Encode { - static inline void operation( - common::ku_string_t& input, common::blob_t& result, common::ValueVector& resultVector) { + static inline void operation(common::ku_string_t& input, common::blob_t& result, + common::ValueVector& resultVector) { common::StringVector::addString(&resultVector, result.value, input); } }; diff --git a/src/include/function/blob/vector_blob_functions.h b/src/include/function/blob/vector_blob_functions.h index 5e0b04f39ff..6c252b476e4 100644 --- a/src/include/function/blob/vector_blob_functions.h +++ b/src/include/function/blob/vector_blob_functions.h @@ -1,19 +1,25 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct OctetLengthFunctions { + static constexpr const char* name = "OCTET_LENGTH"; + static function_set getFunctionSet(); }; struct EncodeFunctions { + static constexpr const char* name = "ENCODE"; + static function_set getFunctionSet(); }; struct DecodeFunctions { + static constexpr const char* name = "DECODE"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/boolean/boolean_function_executor.h b/src/include/function/boolean/boolean_function_executor.h index 2b79d6f8eab..c5958e9f412 100644 --- a/src/include/function/boolean/boolean_function_executor.h +++ b/src/include/function/boolean/boolean_function_executor.h @@ -32,8 +32,8 @@ struct BinaryBooleanFunctionExecutor { } template - static inline void executeBothFlat( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static inline void executeBothFlat(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { auto lPos = left.state->selVector->selectedPositions[0]; auto rPos = right.state->selVector->selectedPositions[0]; auto resPos = result.state->selVector->selectedPositions[0]; @@ -41,8 +41,8 @@ struct BinaryBooleanFunctionExecutor { } template - static void executeFlatUnFlat( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void executeFlatUnFlat(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { auto lPos = left.state->selVector->selectedPositions[0]; if (right.state->selVector->isUnfiltered()) { if (right.hasNoNullsGuarantee() && !left.isNull(lPos)) { @@ -70,8 +70,8 @@ struct BinaryBooleanFunctionExecutor { } template - static void executeUnFlatFlat( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void executeUnFlatFlat(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { auto rPos = right.state->selVector->selectedPositions[0]; if (left.state->selVector->isUnfiltered()) { if (left.hasNoNullsGuarantee() && !right.isNull(rPos)) { @@ -99,8 +99,8 @@ struct BinaryBooleanFunctionExecutor { } template - static void executeBothUnFlat( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void executeBothUnFlat(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { KU_ASSERT(left.state == right.state); if (left.state->selVector->isUnfiltered()) { if (left.hasNoNullsGuarantee() && right.hasNoNullsGuarantee()) { @@ -128,8 +128,8 @@ struct BinaryBooleanFunctionExecutor { } template - static void execute( - common::ValueVector& left, common::ValueVector& right, common::ValueVector& result) { + static void execute(common::ValueVector& left, common::ValueVector& right, + common::ValueVector& result) { KU_ASSERT(left.dataType.getLogicalTypeID() == common::LogicalTypeID::BOOL && right.dataType.getLogicalTypeID() == common::LogicalTypeID::BOOL && result.dataType.getLogicalTypeID() == common::LogicalTypeID::BOOL); @@ -166,21 +166,21 @@ struct BinaryBooleanFunctionExecutor { } template - static bool selectFlatUnFlat( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectFlatUnFlat(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { auto lPos = left.state->selVector->selectedPositions[0]; uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionsBuffer = selVector.getMultableBuffer(); if (right.state->selVector->isUnfiltered()) { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { - selectOnValue( - left, right, lPos, i, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, lPos, i, i, numSelectedValues, + selectedPositionsBuffer); } } else { for (auto i = 0u; i < right.state->selVector->selectedSize; ++i) { auto rPos = right.state->selVector->selectedPositions[i]; - selectOnValue( - left, right, lPos, rPos, rPos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, lPos, rPos, rPos, numSelectedValues, + selectedPositionsBuffer); } } selVector.selectedSize = numSelectedValues; @@ -188,21 +188,21 @@ struct BinaryBooleanFunctionExecutor { } template - static bool selectUnFlatFlat( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectUnFlatFlat(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { auto rPos = right.state->selVector->selectedPositions[0]; uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionsBuffer = selVector.getMultableBuffer(); if (left.state->selVector->isUnfiltered()) { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { - selectOnValue( - left, right, i, rPos, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, i, rPos, i, numSelectedValues, + selectedPositionsBuffer); } } else { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { auto lPos = left.state->selVector->selectedPositions[i]; - selectOnValue( - left, right, lPos, rPos, lPos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, lPos, rPos, lPos, numSelectedValues, + selectedPositionsBuffer); } } selVector.selectedSize = numSelectedValues; @@ -210,20 +210,20 @@ struct BinaryBooleanFunctionExecutor { } template - static bool selectBothUnFlat( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool selectBothUnFlat(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionsBuffer = selVector.getMultableBuffer(); if (left.state->selVector->isUnfiltered()) { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { - selectOnValue( - left, right, i, i, i, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, i, i, i, numSelectedValues, + selectedPositionsBuffer); } } else { for (auto i = 0u; i < left.state->selVector->selectedSize; ++i) { auto pos = left.state->selVector->selectedPositions[i]; - selectOnValue( - left, right, pos, pos, pos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(left, right, pos, pos, pos, numSelectedValues, + selectedPositionsBuffer); } } selVector.selectedSize = numSelectedValues; @@ -231,8 +231,8 @@ struct BinaryBooleanFunctionExecutor { } template - static bool select( - common::ValueVector& left, common::ValueVector& right, common::SelectionVector& selVector) { + static bool select(common::ValueVector& left, common::ValueVector& right, + common::SelectionVector& selVector) { KU_ASSERT(left.dataType.getLogicalTypeID() == common::LogicalTypeID::BOOL && right.dataType.getLogicalTypeID() == common::LogicalTypeID::BOOL); if (left.state->isFlat() && right.state->isFlat()) { @@ -288,8 +288,8 @@ struct UnaryBooleanOperationExecutor { static inline void selectOnValue(common::ValueVector& operand, uint64_t operandPos, uint64_t& numSelectedValues, common::sel_t* selectedPositionsBuffer) { uint8_t resultValue = 0; - FUNC::operation( - operand.getValue(operandPos), operand.isNull(operandPos), resultValue); + FUNC::operation(operand.getValue(operandPos), operand.isNull(operandPos), + resultValue); selectedPositionsBuffer[numSelectedValues] = operandPos; numSelectedValues += resultValue == true; } @@ -303,7 +303,7 @@ struct UnaryBooleanOperationExecutor { return resultValue == true; } else { uint64_t numSelectedValues = 0; - auto selectedPositionBuffer = selVector.getSelectedPositionsBuffer(); + auto selectedPositionBuffer = selVector.getMultableBuffer(); if (operand.state->selVector->isUnfiltered()) { for (auto i = 0ul; i < operand.state->selVector->selectedSize; i++) { selectOnValue(operand, i, numSelectedValues, selectedPositionBuffer); diff --git a/src/include/function/boolean/boolean_functions.h b/src/include/function/boolean/boolean_functions.h index f90a8b57433..c09f013888c 100644 --- a/src/include/function/boolean/boolean_functions.h +++ b/src/include/function/boolean/boolean_functions.h @@ -36,8 +36,8 @@ const uint8_t NULL_BOOL = 2; * - T - T 2 * */ struct And { - static inline void operation( - bool left, bool right, uint8_t& result, bool isLeftNull, bool isRightNull) { + static inline void operation(bool left, bool right, uint8_t& result, bool isLeftNull, + bool isRightNull) { if ((!left && !isLeftNull) || (!right && !isRightNull)) { result = false; } else if (isLeftNull || isRightNull) { @@ -64,8 +64,8 @@ struct And { * - T - T 2 * */ struct Or { - static inline void operation( - bool left, bool right, uint8_t& result, bool isLeftNull, bool isRightNull) { + static inline void operation(bool left, bool right, uint8_t& result, bool isLeftNull, + bool isRightNull) { if ((left && !isLeftNull) || (right && !isRightNull)) { result = true; } else if (isLeftNull || isRightNull) { @@ -92,8 +92,8 @@ struct Or { * - T - T 2 * */ struct Xor { - static inline void operation( - bool left, bool right, uint8_t& result, bool isLeftNull, bool isRightNull) { + static inline void operation(bool left, bool right, uint8_t& result, bool isLeftNull, + bool isRightNull) { if (isLeftNull || isRightNull) { result = NULL_BOOL; } else { diff --git a/src/include/function/boolean/vector_boolean_functions.h b/src/include/function/boolean/vector_boolean_functions.h index 0eec1ee40cf..76252c8cd61 100644 --- a/src/include/function/boolean/vector_boolean_functions.h +++ b/src/include/function/boolean/vector_boolean_functions.h @@ -9,10 +9,10 @@ namespace function { class VectorBooleanFunction { public: static void bindExecFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func); + const binder::expression_vector& children, scalar_func_exec_t& func); static void bindSelectFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func); + const binder::expression_vector& children, scalar_func_select_t& func); private: template @@ -48,16 +48,16 @@ class VectorBooleanFunction { } static void bindBinaryExecFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func); + const binder::expression_vector& children, scalar_func_exec_t& func); static void bindBinarySelectFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func); + const binder::expression_vector& children, scalar_func_select_t& func); static void bindUnaryExecFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func); + const binder::expression_vector& children, scalar_func_exec_t& func); static void bindUnarySelectFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func); + const binder::expression_vector& children, scalar_func_select_t& func); }; } // namespace function diff --git a/src/include/function/built_in_function_utils.h b/src/include/function/built_in_function_utils.h index e93577f9755..ae8d19d0a78 100644 --- a/src/include/function/built_in_function_utils.h +++ b/src/include/function/built_in_function_utils.h @@ -1,7 +1,7 @@ #pragma once #include "aggregate_function.h" -#include "scalar_function.h" +#include "function.h" namespace kuzu { namespace catalog { @@ -24,8 +24,8 @@ class BuiltInFunctionsUtils { const std::vector& inputTypes, bool isDistinct, catalog::CatalogSet* catalogSet); - static uint32_t getCastCost( - common::LogicalTypeID inputTypeID, common::LogicalTypeID targetTypeID); + static uint32_t getCastCost(common::LogicalTypeID inputTypeID, + common::LogicalTypeID targetTypeID); private: // TODO(Xiyang): move casting cost related functions to binder. @@ -67,8 +67,8 @@ class BuiltInFunctionsUtils { static Function* getBestMatch(std::vector& functions); - static uint32_t getFunctionCost( - const std::vector& inputTypes, Function* function, bool isOverload); + static uint32_t getFunctionCost(const std::vector& inputTypes, + Function* function, bool isOverload); static uint32_t matchParameters(const std::vector& inputTypes, const std::vector& targetTypeIDs, bool isOverload); static uint32_t matchVarLengthParameters(const std::vector& inputTypes, @@ -79,47 +79,6 @@ class BuiltInFunctionsUtils { static void validateSpecialCases(std::vector& candidateFunctions, const std::string& name, const std::vector& inputTypes, function::function_set& set); - - // Scalar functions. - static void registerScalarFunctions(catalog::CatalogSet* catalogSet); - static void registerComparisonFunctions(catalog::CatalogSet* catalogSet); - static void registerArithmeticFunctions(catalog::CatalogSet* catalogSet); - static void registerDateFunctions(catalog::CatalogSet* catalogSet); - static void registerTimestampFunctions(catalog::CatalogSet* catalogSet); - static void registerIntervalFunctions(catalog::CatalogSet* catalogSet); - static void registerBlobFunctions(catalog::CatalogSet* catalogSet); - static void registerUUIDFunctions(catalog::CatalogSet* catalogSet); - static void registerStringFunctions(catalog::CatalogSet* catalogSet); - static void registerCastFunctions(catalog::CatalogSet* catalogSet); - static void registerListFunctions(catalog::CatalogSet* catalogSet); - static void registerStructFunctions(catalog::CatalogSet* catalogSet); - static void registerMapFunctions(catalog::CatalogSet* catalogSet); - static void registerUnionFunctions(catalog::CatalogSet* catalogSet); - static void registerNodeRelFunctions(catalog::CatalogSet* catalogSet); - static void registerPathFunctions(catalog::CatalogSet* catalogSet); - static void registerRdfFunctions(catalog::CatalogSet* catalogSet); - - // Aggregate functions. - static void registerAggregateFunctions(catalog::CatalogSet* catalogSet); - static void registerCountStar(catalog::CatalogSet* catalogSet); - static void registerCount(catalog::CatalogSet* catalogSet); - static void registerSum(catalog::CatalogSet* catalogSet); - static void registerAvg(catalog::CatalogSet* catalogSet); - static void registerMin(catalog::CatalogSet* catalogSet); - static void registerMax(catalog::CatalogSet* catalogSet); - static void registerCollect(catalog::CatalogSet* catalogSet); - - // Table functions. - static void registerTableFunctions(catalog::CatalogSet* catalogSet); - - // Validations - static void validateNonEmptyCandidateFunctions( - std::vector& candidateFunctions, const std::string& name, - const std::vector& inputTypes, bool isDistinct, - function::function_set& set); - static void validateNonEmptyCandidateFunctions(std::vector& candidateFunctions, - const std::string& name, const std::vector& inputTypes, - function::function_set& set); }; } // namespace function diff --git a/src/include/function/cast/cast_function_bind_data.h b/src/include/function/cast/cast_function_bind_data.h new file mode 100644 index 00000000000..13ff83f57fb --- /dev/null +++ b/src/include/function/cast/cast_function_bind_data.h @@ -0,0 +1,21 @@ +#pragma once + +#include "common/copier_config/csv_reader_config.h" +#include "function/function.h" + +namespace kuzu { +namespace function { + +struct CastFunctionBindData : public FunctionBindData { + // We don't allow configuring delimiters, ... in CAST function. + // For performance purpose, we generate a default option object during binding time. + common::CSVOption option; + // TODO(Mahn): the following field should be removed once we refactor fixed list. + uint64_t numOfEntries; + + explicit CastFunctionBindData(std::unique_ptr dataType) + : FunctionBindData{std::move(dataType)} {} +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/cast/functions/cast_array.h b/src/include/function/cast/functions/cast_array.h new file mode 100644 index 00000000000..d516d45dc87 --- /dev/null +++ b/src/include/function/cast/functions/cast_array.h @@ -0,0 +1,20 @@ +#pragma once + +#include "common/types/types.h" +#include "common/vector/value_vector.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace function { + +struct CastArrayHelper { + static bool checkCompatibleNestedTypes(LogicalTypeID sourceTypeID, LogicalTypeID targetTypeID); + + static bool containsListToArray(const LogicalType* srcType, const LogicalType* dstType); + + static void validateListEntry(ValueVector* inputVector, LogicalType* resultType, uint64_t pos); +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/cast/functions/cast_fixed_list.h b/src/include/function/cast/functions/cast_fixed_list.h deleted file mode 100644 index b313a9209be..00000000000 --- a/src/include/function/cast/functions/cast_fixed_list.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "function/unary_function_executor.h" - -using namespace kuzu::common; - -namespace kuzu { -namespace function { - -struct CastFixedListHelper { - static bool containsListToFixedList(const LogicalType* srcType, const LogicalType* dstType); - - static void validateListEntry(ValueVector* inputVector, LogicalType* resultType, uint64_t pos); -}; - -struct CastFixedList { - template - static void fixedListToStringCastExecFunction( - const std::vector>& params, ValueVector& result, - void* dataPtr); - - template - static void stringtoFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, - void* dataPtr); - - template - static void listToFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, - void* dataPtr); - - template - static void castBetweenFixedListExecFunc( - const std::vector>& params, ValueVector& result, - void* dataPtr); -}; - -template<> -void CastFixedList::fixedListToStringCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::fixedListToStringCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::fixedListToStringCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); - -template<> -void CastFixedList::stringtoFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::stringtoFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::stringtoFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); - -template<> -void CastFixedList::listToFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::listToFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::listToFixedListCastExecFunction( - const std::vector>& params, ValueVector& result, void* dataPtr); - -template<> -void CastFixedList::castBetweenFixedListExecFunc( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::castBetweenFixedListExecFunc( - const std::vector>& params, ValueVector& result, void* dataPtr); -template<> -void CastFixedList::castBetweenFixedListExecFunc( - const std::vector>& params, ValueVector& result, void* dataPtr); - -} // namespace function -} // namespace kuzu diff --git a/src/include/function/cast/functions/cast_from_string_functions.h b/src/include/function/cast/functions/cast_from_string_functions.h index 49ab83099ac..fdc74fb7c86 100644 --- a/src/include/function/cast/functions/cast_from_string_functions.h +++ b/src/include/function/cast/functions/cast_from_string_functions.h @@ -13,14 +13,14 @@ namespace kuzu { namespace function { struct CastString { - static void copyStringToVector( - ValueVector* vector, uint64_t rowToAdd, std::string_view strVal, const CSVOption* option); + static void copyStringToVector(ValueVector* vector, uint64_t vectorPos, std::string_view strVal, + const CSVOption* option); template static inline bool tryCast(const ku_string_t& input, T& result) { // try cast for signed integer types - return trySimpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result); + return trySimpleIntegerCast(reinterpret_cast(input.getData()), + input.len, result); } template @@ -31,9 +31,6 @@ struct CastString { simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::INT64); } - - static void castToFixedList(const ku_string_t& input, ValueVector* resultVector, - uint64_t rowToAdd, const CSVOption* option); }; template<> @@ -45,64 +42,64 @@ inline void CastString::operation(const ku_string_t& input, int128_t& result, template<> inline void CastString::operation(const ku_string_t& input, int32_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::INT32); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, + LogicalTypeID::INT32); } template<> inline void CastString::operation(const ku_string_t& input, int16_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::INT16); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, + LogicalTypeID::INT16); } template<> inline void CastString::operation(const ku_string_t& input, int8_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::INT8); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, + LogicalTypeID::INT8); } template<> inline void CastString::operation(const ku_string_t& input, uint64_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::UINT64); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalTypeID::UINT64); } template<> inline void CastString::operation(const ku_string_t& input, uint32_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::UINT32); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalTypeID::UINT32); } template<> inline void CastString::operation(const ku_string_t& input, uint16_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::UINT16); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalTypeID::UINT16); } template<> inline void CastString::operation(const ku_string_t& input, uint8_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - simpleIntegerCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::UINT8); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalTypeID::UINT8); } template<> inline void CastString::operation(const ku_string_t& input, float& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - doubleCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::FLOAT); + doubleCast(reinterpret_cast(input.getData()), input.len, result, + LogicalTypeID::FLOAT); } template<> inline void CastString::operation(const ku_string_t& input, double& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - doubleCast( - reinterpret_cast(input.getData()), input.len, result, LogicalTypeID::DOUBLE); + doubleCast(reinterpret_cast(input.getData()), input.len, result, + LogicalTypeID::DOUBLE); } template<> @@ -120,29 +117,29 @@ inline void CastString::operation(const ku_string_t& input, timestamp_t& result, template<> inline void CastString::operation(const ku_string_t& input, timestamp_ns_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - TryCastStringToTimestamp::cast( - (const char*)input.getData(), input.len, result, LogicalTypeID::TIMESTAMP_NS); + TryCastStringToTimestamp::cast((const char*)input.getData(), input.len, result, + LogicalTypeID::TIMESTAMP_NS); } template<> inline void CastString::operation(const ku_string_t& input, timestamp_ms_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - TryCastStringToTimestamp::cast( - (const char*)input.getData(), input.len, result, LogicalTypeID::TIMESTAMP_MS); + TryCastStringToTimestamp::cast((const char*)input.getData(), input.len, result, + LogicalTypeID::TIMESTAMP_MS); } template<> inline void CastString::operation(const ku_string_t& input, timestamp_sec_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - TryCastStringToTimestamp::cast( - (const char*)input.getData(), input.len, result, LogicalTypeID::TIMESTAMP_SEC); + TryCastStringToTimestamp::cast((const char*)input.getData(), input.len, result, + LogicalTypeID::TIMESTAMP_SEC); } template<> inline void CastString::operation(const ku_string_t& input, timestamp_tz_t& result, ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, const CSVOption* /*option*/) { - TryCastStringToTimestamp::cast( - (const char*)input.getData(), input.len, result, LogicalTypeID::TIMESTAMP_TZ); + TryCastStringToTimestamp::cast((const char*)input.getData(), input.len, result, + LogicalTypeID::TIMESTAMP_TZ); } template<> diff --git a/src/include/function/cast/functions/cast_functions.h b/src/include/function/cast/functions/cast_functions.h index 4574ae315f1..9ddaf5b26b3 100644 --- a/src/include/function/cast/functions/cast_functions.h +++ b/src/include/function/cast/functions/cast_functions.h @@ -73,8 +73,8 @@ struct CastToDouble { template<> inline void CastToDouble::operation(common::int128_t& input, double& result) { if (!common::Int128_t::tryCast(input, result)) { // LCOV_EXCL_START - throw common::OverflowException{common::stringFormat( - "Value {} is not within DOUBLE range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within DOUBLE range", + common::TypeUtils::toString(input))}; } // LCOV_EXCL_STOP } @@ -91,8 +91,8 @@ struct CastToFloat { template<> inline void CastToFloat::operation(common::int128_t& input, float& result) { if (!common::Int128_t::tryCast(input, result)) { // LCOV_EXCL_START - throw common::OverflowException{common::stringFormat( - "Value {} is not within FLOAT range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within FLOAT range", + common::TypeUtils::toString(input))}; }; // LCOV_EXCL_STOP } @@ -116,8 +116,8 @@ struct CastToInt64 { template<> inline void CastToInt64::operation(common::int128_t& input, int64_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within INT64 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within INT64 range", + common::TypeUtils::toString(input))}; }; } @@ -134,8 +134,8 @@ struct CastToSerial { template<> inline void CastToSerial::operation(common::int128_t& input, int64_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within INT64 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within INT64 range", + common::TypeUtils::toString(input))}; }; } @@ -152,8 +152,8 @@ struct CastToInt32 { template<> inline void CastToInt32::operation(common::int128_t& input, int32_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within INT32 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within INT32 range", + common::TypeUtils::toString(input))}; }; } @@ -170,8 +170,8 @@ struct CastToInt16 { template<> inline void CastToInt16::operation(common::int128_t& input, int16_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within INT16 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within INT16 range", + common::TypeUtils::toString(input))}; }; } @@ -188,8 +188,8 @@ struct CastToInt8 { template<> inline void CastToInt8::operation(common::int128_t& input, int8_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within INT8 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within INT8 range", + common::TypeUtils::toString(input))}; }; } @@ -206,8 +206,8 @@ struct CastToUInt64 { template<> inline void CastToUInt64::operation(common::int128_t& input, uint64_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within UINT64 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within UINT64 range", + common::TypeUtils::toString(input))}; }; } @@ -224,8 +224,8 @@ struct CastToUInt32 { template<> inline void CastToUInt32::operation(common::int128_t& input, uint32_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within UINT32 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within UINT32 range", + common::TypeUtils::toString(input))}; }; } @@ -242,8 +242,8 @@ struct CastToUInt16 { template<> inline void CastToUInt16::operation(common::int128_t& input, uint16_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within UINT16 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within UINT16 range", + common::TypeUtils::toString(input))}; }; } @@ -260,8 +260,8 @@ struct CastToUInt8 { template<> inline void CastToUInt8::operation(common::int128_t& input, uint8_t& result) { if (!common::Int128_t::tryCast(input, result)) { - throw common::OverflowException{common::stringFormat( - "Value {} is not within UINT8 range", common::TypeUtils::toString(input))}; + throw common::OverflowException{common::stringFormat("Value {} is not within UINT8 range", + common::TypeUtils::toString(input))}; }; } @@ -274,79 +274,79 @@ struct CastBetweenTimestamp { }; template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_t& input, common::timestamp_ns_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_t& input, + common::timestamp_ns_t& output) { output.value = common::Timestamp::getEpochNanoSeconds(input); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_t& input, common::timestamp_ms_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_t& input, + common::timestamp_ms_t& output) { output.value = common::Timestamp::getEpochMilliSeconds(input); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_t& input, common::timestamp_sec_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_t& input, + common::timestamp_sec_t& output) { output.value = common::Timestamp::getEpochSeconds(input); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_ms_t& input, common::timestamp_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_ms_t& input, + common::timestamp_t& output) { output = common::Timestamp::fromEpochMilliSeconds(input.value); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_ms_t& input, common::timestamp_ns_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_ms_t& input, + common::timestamp_ns_t& output) { operation(input, output); operation(output, output); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_ms_t& input, common::timestamp_sec_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_ms_t& input, + common::timestamp_sec_t& output) { operation(input, output); operation(output, output); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_ns_t& input, common::timestamp_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_ns_t& input, + common::timestamp_t& output) { output = common::Timestamp::fromEpochNanoSeconds(input.value); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_ns_t& input, common::timestamp_ms_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_ns_t& input, + common::timestamp_ms_t& output) { operation(input, output); operation(output, output); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_ns_t& input, common::timestamp_sec_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_ns_t& input, + common::timestamp_sec_t& output) { operation(input, output); operation(output, output); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_sec_t& input, common::timestamp_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_sec_t& input, + common::timestamp_t& output) { output = common::Timestamp::fromEpochSeconds(input.value); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_sec_t& input, common::timestamp_ns_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_sec_t& input, + common::timestamp_ns_t& output) { operation(input, output); operation(output, output); } template<> -inline void CastBetweenTimestamp::operation( - const common::timestamp_sec_t& input, common::timestamp_ms_t& output) { +inline void CastBetweenTimestamp::operation(const common::timestamp_sec_t& input, + common::timestamp_ms_t& output) { operation(input, output); operation(output, output); } diff --git a/src/include/function/cast/functions/cast_string_non_nested_functions.h b/src/include/function/cast/functions/cast_string_non_nested_functions.h index 020d0c5dbc1..ab75ea89fad 100644 --- a/src/include/function/cast/functions/cast_string_non_nested_functions.h +++ b/src/include/function/cast/functions/cast_string_non_nested_functions.h @@ -188,8 +188,8 @@ inline bool trySimpleIntegerCast(const char* input, uint64_t len, T& result) { } template -inline void simpleIntegerCast( - const char* input, uint64_t len, T& result, LogicalTypeID typeID = LogicalTypeID::ANY) { +inline void simpleIntegerCast(const char* input, uint64_t len, T& result, + LogicalTypeID typeID = LogicalTypeID::ANY) { if (!trySimpleIntegerCast(input, len, result)) { throw ConversionException(stringFormat("Cast failed. Could not convert \"{}\" to {}.", std::string{input, len}, LogicalTypeUtils::toString(typeID))); @@ -217,8 +217,8 @@ inline bool tryDoubleCast(const char* input, uint64_t len, T& result) { } template -inline void doubleCast( - const char* input, uint64_t len, T& result, LogicalTypeID typeID = LogicalTypeID::ANY) { +inline void doubleCast(const char* input, uint64_t len, T& result, + LogicalTypeID typeID = LogicalTypeID::ANY) { if (!tryDoubleCast(input, len, result)) { throw ConversionException(stringFormat("Cast failed. {} is not in {} range.", std::string{input, len}, LogicalTypeUtils::toString(typeID))); @@ -233,27 +233,27 @@ struct TryCastStringToTimestamp { template static void cast(const char* input, uint64_t len, timestamp_t& result, LogicalTypeID typeID) { if (!tryCast(input, len, result)) { - throw ConversionException(Timestamp::getTimestampConversionExceptionMsg( - input, len, LogicalTypeUtils::toString(typeID))); + throw ConversionException(Timestamp::getTimestampConversionExceptionMsg(input, len, + LogicalTypeUtils::toString(typeID))); } } }; template<> -bool TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result); +bool TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result); template<> -bool TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result); +bool TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result); template<> -bool TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result); +bool TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result); template<> -bool inline TryCastStringToTimestamp::tryCast( - const char* input, uint64_t len, timestamp_t& result) { +bool inline TryCastStringToTimestamp::tryCast(const char* input, uint64_t len, + timestamp_t& result) { return Timestamp::tryConvertTimestamp(input, len, result); } diff --git a/src/include/function/cast/functions/numeric_cast.h b/src/include/function/cast/functions/numeric_cast.h index 861fe0724a3..a1fe65a0261 100644 --- a/src/include/function/cast/functions/numeric_cast.h +++ b/src/include/function/cast/functions/numeric_cast.h @@ -74,14 +74,14 @@ inline bool tryCastWithOverflowCheck(float value, int16_t& result) { template<> inline bool tryCastWithOverflowCheck(float value, int32_t& result) { - return tryCastWithOverflowCheckFloat( - value, result, -2147483648.0f, 2147483648.0f); + return tryCastWithOverflowCheckFloat(value, result, -2147483648.0f, + 2147483648.0f); } template<> inline bool tryCastWithOverflowCheck(float value, int64_t& result) { - return tryCastWithOverflowCheckFloat( - value, result, -9223372036854775808.0f, 9223372036854775808.0f); + return tryCastWithOverflowCheckFloat(value, result, -9223372036854775808.0f, + 9223372036854775808.0f); } template<> @@ -101,8 +101,8 @@ inline bool tryCastWithOverflowCheck(float value, uint32_t& result) { template<> inline bool tryCastWithOverflowCheck(float value, uint64_t& result) { - return tryCastWithOverflowCheckFloat( - value, result, 0.0f, 18446744073709551616.0f); + return tryCastWithOverflowCheckFloat(value, result, 0.0f, + 18446744073709551616.0f); } template<> @@ -117,14 +117,14 @@ inline bool tryCastWithOverflowCheck(double value, int16_t& result) { template<> inline bool tryCastWithOverflowCheck(double value, int32_t& result) { - return tryCastWithOverflowCheckFloat( - value, result, -2147483648.0, 2147483648.0); + return tryCastWithOverflowCheckFloat(value, result, -2147483648.0, + 2147483648.0); } template<> inline bool tryCastWithOverflowCheck(double value, int64_t& result) { - return tryCastWithOverflowCheckFloat( - value, result, -9223372036854775808.0, 9223372036854775808.0); + return tryCastWithOverflowCheckFloat(value, result, -9223372036854775808.0, + 9223372036854775808.0); } template<> @@ -144,8 +144,8 @@ inline bool tryCastWithOverflowCheck(double value, uint32_t& result) { template<> inline bool tryCastWithOverflowCheck(double value, uint64_t& result) { - return tryCastWithOverflowCheckFloat( - value, result, 0.0, 18446744073709551615.0); + return tryCastWithOverflowCheckFloat(value, result, 0.0, + 18446744073709551615.0); } template<> diff --git a/src/include/function/cast/vector_cast_functions.h b/src/include/function/cast/vector_cast_functions.h index 97a94f0a959..3ca772935a8 100644 --- a/src/include/function/cast/vector_cast_functions.h +++ b/src/include/function/cast/vector_cast_functions.h @@ -13,8 +13,8 @@ namespace function { struct CastFunction { // This function is only used by expression binder when implicit cast is needed. // The expression binder should consider reusing the existing matchFunction() API. - static bool hasImplicitCast( - const common::LogicalType& srcType, const common::LogicalType& dstType); + static bool hasImplicitCast(const common::LogicalType& srcType, + const common::LogicalType& dstType); template static std::unique_ptr bindCastFunction(const std::string& functionName, @@ -22,84 +22,132 @@ struct CastFunction { }; struct CastToDateFunction { + static constexpr const char* name = "TO_DATE"; + + static constexpr const char* alias = "DATE"; + static function_set getFunctionSet(); }; struct CastToTimestampFunction { + static constexpr const char* name = "TIMESTAMP"; + static function_set getFunctionSet(); }; struct CastToIntervalFunction { + static constexpr const char* name = "TO_INTERVAL"; + + static constexpr const char* alias = "INTERVAL"; + static function_set getFunctionSet(); }; struct CastToStringFunction { + static constexpr const char* name = "TO_STRING"; + + static constexpr const char* alias = "STRING"; + static function_set getFunctionSet(); }; struct CastToBlobFunction { + static constexpr const char* name = "TO_BLOB"; + + static constexpr const char* alias = "BLOB"; + static function_set getFunctionSet(); }; struct CastToUUIDFunction { + static constexpr const char* name = "TO_UUID"; + + static constexpr const char* alias = "UUID"; + static function_set getFunctionSet(); }; struct CastToBoolFunction { + static constexpr const char* name = "TO_BOOL"; + static function_set getFunctionSet(); }; struct CastToDoubleFunction { + static constexpr const char* name = "TO_DOUBLE"; + static function_set getFunctionSet(); }; struct CastToFloatFunction { + static constexpr const char* name = "TO_FLOAT"; + static function_set getFunctionSet(); }; struct CastToSerialFunction { + static constexpr const char* name = "TO_SERIAL"; + static function_set getFunctionSet(); }; struct CastToInt128Function { + static constexpr const char* name = "TO_INT128"; + static function_set getFunctionSet(); }; struct CastToInt64Function { + static constexpr const char* name = "TO_INT64"; + static function_set getFunctionSet(); }; struct CastToInt32Function { + static constexpr const char* name = "TO_INT32"; + static function_set getFunctionSet(); }; struct CastToInt16Function { + static constexpr const char* name = "TO_INT16"; + static function_set getFunctionSet(); }; struct CastToInt8Function { + static constexpr const char* name = "TO_INT8"; + static function_set getFunctionSet(); }; struct CastToUInt64Function { + static constexpr const char* name = "TO_UINT64"; + static function_set getFunctionSet(); }; struct CastToUInt32Function { + static constexpr const char* name = "TO_UINT32"; + static function_set getFunctionSet(); }; struct CastToUInt16Function { + static constexpr const char* name = "TO_UINT16"; + static function_set getFunctionSet(); }; struct CastToUInt8Function { + static constexpr const char* name = "TO_UINT8"; + static function_set getFunctionSet(); }; struct CastAnyFunction { - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); + static constexpr const char* name = "CAST"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/comparison/vector_comparison_functions.h b/src/include/function/comparison/vector_comparison_functions.h index c2538eacb3d..2f7a439a20a 100644 --- a/src/include/function/comparison/vector_comparison_functions.h +++ b/src/include/function/comparison/vector_comparison_functions.h @@ -15,14 +15,14 @@ struct ComparisonFunction { for (auto& comparableType : common::LogicalTypeUtils::getAllValidComparableLogicalTypes()) { functionSet.push_back(getFunction(name, comparableType, comparableType)); } - functionSet.push_back(getFunction( - name, common::LogicalTypeID::VAR_LIST, common::LogicalTypeID::VAR_LIST)); + functionSet.push_back( + getFunction(name, common::LogicalTypeID::LIST, common::LogicalTypeID::LIST)); functionSet.push_back( getFunction(name, common::LogicalTypeID::STRUCT, common::LogicalTypeID::STRUCT)); // We can only check whether two internal ids are equal or not. So INTERNAL_ID is not // part of the comparable logical types. - functionSet.push_back(getFunction( - name, common::LogicalTypeID::INTERNAL_ID, common::LogicalTypeID::INTERNAL_ID)); + functionSet.push_back(getFunction(name, common::LogicalTypeID::INTERNAL_ID, + common::LogicalTypeID::INTERNAL_ID)); return functionSet; } @@ -41,18 +41,18 @@ struct ComparisonFunction { const std::vector>& params, common::SelectionVector& selVector) { KU_ASSERT(params.size() == 2); - return BinaryFunctionExecutor::selectComparison( - *params[0], *params[1], selVector); + return BinaryFunctionExecutor::selectComparison(*params[0], + *params[1], selVector); } template - static inline std::unique_ptr getFunction( - const std::string& name, common::LogicalTypeID leftType, common::LogicalTypeID rightType) { + static std::unique_ptr getFunction(const std::string& name, + common::LogicalTypeID leftType, common::LogicalTypeID rightType) { auto leftPhysical = common::LogicalType::getPhysicalType(leftType); auto rightPhysical = common::LogicalType::getPhysicalType(rightType); - scalar_exec_func execFunc; + scalar_func_exec_t execFunc; getExecFunc(leftPhysical, rightPhysical, execFunc); - scalar_select_func selectFunc; + scalar_func_select_t selectFunc; getSelectFunc(leftPhysical, rightPhysical, selectFunc); return std::make_unique(name, std::vector{leftType, rightType}, common::LogicalTypeID::BOOL, @@ -62,8 +62,8 @@ struct ComparisonFunction { // When comparing two values, we guarantee that they must have the same dataType. So we only // need to switch the physical type to get the corresponding exec function. template - static void getExecFunc( - common::PhysicalTypeID leftType, common::PhysicalTypeID rightType, scalar_exec_func& func) { + static void getExecFunc(common::PhysicalTypeID leftType, common::PhysicalTypeID rightType, + scalar_func_exec_t& func) { switch (leftType) { case common::PhysicalTypeID::INT64: { func = BinaryComparisonExecFunction; @@ -112,7 +112,7 @@ struct ComparisonFunction { func = BinaryComparisonExecFunction; } break; - case common::PhysicalTypeID::VAR_LIST: { + case common::PhysicalTypeID::LIST: { func = BinaryComparisonExecFunction; } break; @@ -130,7 +130,7 @@ struct ComparisonFunction { template static void getSelectFunc(common::PhysicalTypeID leftTypeID, common::PhysicalTypeID rightTypeID, - scalar_select_func& func) { + scalar_func_select_t& func) { KU_ASSERT(leftTypeID == rightTypeID); switch (leftTypeID) { case common::PhysicalTypeID::INT64: { @@ -178,7 +178,7 @@ struct ComparisonFunction { case common::PhysicalTypeID::INTERVAL: { func = BinaryComparisonSelectFunction; } break; - case common::PhysicalTypeID::VAR_LIST: { + case common::PhysicalTypeID::LIST: { func = BinaryComparisonSelectFunction; } break; case common::PhysicalTypeID::STRUCT: { @@ -196,40 +196,50 @@ struct ComparisonFunction { }; struct EqualsFunction { - static inline function_set getFunctionSet() { - return ComparisonFunction::getFunctionSet(common::EQUALS_FUNC_NAME); + static constexpr const char* name = "EQUALS"; + + static function_set getFunctionSet() { + return ComparisonFunction::getFunctionSet(name); } }; struct NotEqualsFunction { - static inline function_set getFunctionSet() { - return ComparisonFunction::getFunctionSet(common::NOT_EQUALS_FUNC_NAME); + static constexpr const char* name = "NOT_EQUALS"; + + static function_set getFunctionSet() { + return ComparisonFunction::getFunctionSet(name); } }; struct GreaterThanFunction { - static inline function_set getFunctionSet() { - return ComparisonFunction::getFunctionSet(common::GREATER_THAN_FUNC_NAME); + static constexpr const char* name = "GREATER_THAN"; + + static function_set getFunctionSet() { + return ComparisonFunction::getFunctionSet(name); } }; struct GreaterThanEqualsFunction { - static inline function_set getFunctionSet() { - return ComparisonFunction::getFunctionSet( - common::GREATER_THAN_EQUALS_FUNC_NAME); + static constexpr const char* name = "GREATER_THAN_EQUALS"; + + static function_set getFunctionSet() { + return ComparisonFunction::getFunctionSet(name); } }; struct LessThanFunction { - static inline function_set getFunctionSet() { - return ComparisonFunction::getFunctionSet(common::LESS_THAN_FUNC_NAME); + static constexpr const char* name = "LESS_THAN"; + + static function_set getFunctionSet() { + return ComparisonFunction::getFunctionSet(name); } }; struct LessThanEqualsFunction { - static inline function_set getFunctionSet() { - return ComparisonFunction::getFunctionSet( - common::LESS_THAN_EQUALS_FUNC_NAME); + static constexpr const char* name = "LESS_THAN_EQUALS"; + + static function_set getFunctionSet() { + return ComparisonFunction::getFunctionSet(name); } }; diff --git a/src/include/function/date/date_functions.h b/src/include/function/date/date_functions.h index 1b5ba3419be..0ab4e2d499f 100644 --- a/src/include/function/date/date_functions.h +++ b/src/include/function/date/date_functions.h @@ -75,31 +75,31 @@ inline void LastDay::operation(common::timestamp_t& input, common::date_t& resul struct DatePart { template - static inline void operation( - LEFT_TYPE& /*partSpecifier*/, RIGHT_TYPE& /*input*/, int64_t& /*result*/) { + static inline void operation(LEFT_TYPE& /*partSpecifier*/, RIGHT_TYPE& /*input*/, + int64_t& /*result*/) { KU_UNREACHABLE; } }; template<> -inline void DatePart::operation( - common::ku_string_t& partSpecifier, common::date_t& input, int64_t& result) { +inline void DatePart::operation(common::ku_string_t& partSpecifier, common::date_t& input, + int64_t& result) { common::DatePartSpecifier specifier; common::Interval::tryGetDatePartSpecifier(partSpecifier.getAsString(), specifier); result = common::Date::getDatePart(specifier, input); } template<> -inline void DatePart::operation( - common::ku_string_t& partSpecifier, common::timestamp_t& input, int64_t& result) { +inline void DatePart::operation(common::ku_string_t& partSpecifier, common::timestamp_t& input, + int64_t& result) { common::DatePartSpecifier specifier; common::Interval::tryGetDatePartSpecifier(partSpecifier.getAsString(), specifier); result = common::Timestamp::getTimestampPart(specifier, input); } template<> -inline void DatePart::operation( - common::ku_string_t& partSpecifier, common::interval_t& input, int64_t& result) { +inline void DatePart::operation(common::ku_string_t& partSpecifier, common::interval_t& input, + int64_t& result) { common::DatePartSpecifier specifier; common::Interval::tryGetDatePartSpecifier(partSpecifier.getAsString(), specifier); result = common::Interval::getIntervalPart(specifier, input); @@ -107,23 +107,23 @@ inline void DatePart::operation( struct DateTrunc { template - static inline void operation( - LEFT_TYPE& /*partSpecifier*/, RIGHT_TYPE& /*input*/, RIGHT_TYPE& /*result*/) { + static inline void operation(LEFT_TYPE& /*partSpecifier*/, RIGHT_TYPE& /*input*/, + RIGHT_TYPE& /*result*/) { KU_UNREACHABLE; } }; template<> -inline void DateTrunc::operation( - common::ku_string_t& partSpecifier, common::date_t& input, common::date_t& result) { +inline void DateTrunc::operation(common::ku_string_t& partSpecifier, common::date_t& input, + common::date_t& result) { common::DatePartSpecifier specifier; common::Interval::tryGetDatePartSpecifier(partSpecifier.getAsString(), specifier); result = common::Date::trunc(specifier, input); } template<> -inline void DateTrunc::operation( - common::ku_string_t& partSpecifier, common::timestamp_t& input, common::timestamp_t& result) { +inline void DateTrunc::operation(common::ku_string_t& partSpecifier, common::timestamp_t& input, + common::timestamp_t& result) { common::DatePartSpecifier specifier; common::Interval::tryGetDatePartSpecifier(partSpecifier.getAsString(), specifier); result = common::Timestamp::trunc(specifier, input); @@ -144,8 +144,8 @@ struct Least { }; struct MakeDate { - static inline void operation( - int64_t& year, int64_t& month, int64_t& day, common::date_t& result) { + static inline void operation(int64_t& year, int64_t& month, int64_t& day, + common::date_t& result) { result = common::Date::fromDate(year, month, day); } }; diff --git a/src/include/function/date/vector_date_functions.h b/src/include/function/date/vector_date_functions.h index d91fd453fff..2c95881e6c6 100644 --- a/src/include/function/date/vector_date_functions.h +++ b/src/include/function/date/vector_date_functions.h @@ -1,39 +1,59 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct DatePartFunction { + static constexpr const char* name = "DATE_PART"; + + static constexpr const char* alias = "DATEPART"; + static function_set getFunctionSet(); }; struct DateTruncFunction { + static constexpr const char* name = "DATE_TRUNC"; + + static constexpr const char* alias = "DATETRUNC"; + static function_set getFunctionSet(); }; struct DayNameFunction { + static constexpr const char* name = "DAYNAME"; + static function_set getFunctionSet(); }; struct GreatestFunction { + static constexpr const char* name = "GREATEST"; + static function_set getFunctionSet(); }; struct LastDayFunction { + static constexpr const char* name = "LAST_DAY"; + static function_set getFunctionSet(); }; struct LeastFunction { + static constexpr const char* name = "LEAST"; + static function_set getFunctionSet(); }; struct MakeDateFunction { + static constexpr const char* name = "MAKE_DATE"; + static function_set getFunctionSet(); }; struct MonthNameFunction { + static constexpr const char* name = "MONTHNAME"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/function.h b/src/include/function/function.h index 97dc56f89e0..ea3f028d0e3 100644 --- a/src/include/function/function.h +++ b/src/include/function/function.h @@ -1,7 +1,6 @@ #pragma once #include "binder/expression/expression.h" -#include "common/copier_config/csv_reader_config.h" namespace kuzu { namespace function { @@ -15,28 +14,30 @@ struct FunctionBindData { virtual ~FunctionBindData() = default; }; -struct CastFunctionBindData : public FunctionBindData { - common::CSVReaderConfig csvConfig; - uint64_t numOfEntries; - - explicit CastFunctionBindData(std::unique_ptr dataType) - : FunctionBindData{std::move(dataType)} {} -}; - struct Function; +using function_set = std::vector>; using scalar_bind_func = std::function( const binder::expression_vector&, Function* definition)>; -enum class FunctionType : uint8_t { SCALAR, AGGREGATE, TABLE }; +enum class FunctionType : uint8_t { + UNKNOWN = 0, + SCALAR = 1, + REWRITE = 2, + AGGREGATE = 3, + TABLE = 4 +}; struct Function { - Function( - FunctionType type, std::string name, std::vector parameterTypeIDs) + Function() : type{FunctionType::UNKNOWN} {}; + Function(FunctionType type, std::string name, + std::vector parameterTypeIDs) : type{type}, name{std::move(name)}, parameterTypeIDs{std::move(parameterTypeIDs)} {} virtual ~Function() = default; - virtual std::string signatureToString() const = 0; + virtual std::string signatureToString() const { + return common::LogicalTypeUtils::toString(parameterTypeIDs); + } virtual std::unique_ptr copy() const = 0; @@ -50,17 +51,16 @@ struct BaseScalarFunction : public Function { BaseScalarFunction(FunctionType type, std::string name, std::vector parameterTypeIDs, common::LogicalTypeID returnTypeID, scalar_bind_func bindFunc) - : Function{type, std::move(name), std::move(parameterTypeIDs)}, - returnTypeID{returnTypeID}, bindFunc{std::move(bindFunc)} {} + : Function{type, std::move(name), std::move(parameterTypeIDs)}, returnTypeID{returnTypeID}, + bindFunc{std::move(bindFunc)} {} - inline std::string signatureToString() const override { - std::string result = common::LogicalTypeUtils::toString(parameterTypeIDs); + std::string signatureToString() const override { + auto result = Function::signatureToString(); result += " -> " + common::LogicalTypeUtils::toString(returnTypeID); return result; } common::LogicalTypeID returnTypeID; - // This function is used to bind parameter/return types for functions with nested dataType. scalar_bind_func bindFunc; }; diff --git a/src/include/function/function_collection.h b/src/include/function/function_collection.h new file mode 100644 index 00000000000..21c337bf62f --- /dev/null +++ b/src/include/function/function_collection.h @@ -0,0 +1,24 @@ +#pragma once + +#include "catalog/catalog_entry/catalog_entry_type.h" +#include "function.h" + +using namespace kuzu::catalog; + +namespace kuzu { +namespace function { + +using get_function_set_fun = std::function; + +struct FunctionCollection { + get_function_set_fun getFunctionSetFunc; + + const char* name; + + CatalogEntryType catalogEntryType; + + static FunctionCollection* getFunctions(); +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/hash/hash_functions.h b/src/include/function/hash/hash_functions.h index 9cfd61f3944..9cd4c4c3f2a 100644 --- a/src/include/function/hash/hash_functions.h +++ b/src/include/function/hash/hash_functions.h @@ -15,12 +15,6 @@ namespace kuzu { namespace function { -template -concept HashableTypes = (std::integral || std::floating_point || - std::is_same_v || - std::is_same_v || - std::is_same_v); - constexpr const uint64_t NULL_HASH = UINT64_MAX; inline common::hash_t murmurhash64(uint64_t x) { @@ -59,81 +53,81 @@ struct Hash { }; struct CombineHash { - static inline void operation( - common::hash_t& left, common::hash_t& right, common::hash_t& result) { + static inline void operation(common::hash_t& left, common::hash_t& right, + common::hash_t& result) { result = combineHashScalar(left, right); } }; template<> -inline void Hash::operation( - const common::internalID_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const common::internalID_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key.offset) ^ murmurhash64(key.tableID); } template<> -inline void Hash::operation( - const bool& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const bool& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const uint8_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const uint8_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const uint16_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const uint16_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const uint32_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const uint32_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const uint64_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const uint64_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const int64_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const int64_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const int32_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const int32_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const int16_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const int16_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const int8_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const int8_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key); } template<> -inline void Hash::operation( - const common::int128_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const common::int128_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = murmurhash64(key.low) ^ murmurhash64(key.high); } template<> -inline void Hash::operation( - const double& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const double& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { // 0 and -0 are not byte-equivalent, but should have the same hash if (key == 0) { result = murmurhash64(0); @@ -143,8 +137,8 @@ inline void Hash::operation( } template<> -inline void Hash::operation( - const float& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const float& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { // 0 and -0 are not byte-equivalent, but should have the same hash if (key == 0) { result = murmurhash64(0); @@ -154,8 +148,8 @@ inline void Hash::operation( } template<> -inline void Hash::operation( - const std::string_view& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const std::string_view& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { common::hash_t hashValue = 0; auto data64 = reinterpret_cast(key.data()); for (size_t i = 0u; i < key.size() / 8; i++) { @@ -171,50 +165,24 @@ inline void Hash::operation( } template<> -inline void Hash::operation( - const std::string& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const std::string& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { Hash::operation(std::string_view(key), result); } template<> -inline void Hash::operation( - const common::ku_string_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const common::ku_string_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { Hash::operation(key.getAsStringView(), result); } template<> -inline void Hash::operation( - const common::interval_t& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { +inline void Hash::operation(const common::interval_t& key, common::hash_t& result, + common::ValueVector* /*keyVector*/) { result = combineHashScalar(murmurhash64(key.months), combineHashScalar(murmurhash64(key.days), murmurhash64(key.micros))); } -template<> -inline void Hash::operation( - const common::list_entry_t& key, common::hash_t& result, common::ValueVector* keyVector) { - auto dataVector = common::ListVector::getDataVector(keyVector); - result = NULL_HASH; - common::hash_t tmpResult; - for (auto i = 0u; i < key.size; i++) { - auto pos = key.offset + i; - if (dataVector->isNull(pos)) { - result = combineHashScalar(result, NULL_HASH); - } else { - common::TypeUtils::visit( - dataVector->dataType.getPhysicalType(), - [&]( - T) { operation(dataVector->getValue(pos), tmpResult, dataVector); }, - [&](common::struct_entry_t) { - // LCOV_EXCL_START - throw common::RuntimeException{"Hash on list of struct is not supported yet."}; - // LCOV_EXCL_STOP - }, - [](auto) { KU_UNREACHABLE; }); - result = combineHashScalar(result, tmpResult); - } - } -} - template<> inline void Hash::operation(const std::unordered_set& key, common::hash_t& result, common::ValueVector* /*keyVector*/) { @@ -226,8 +194,8 @@ inline void Hash::operation(const std::unordered_set& key, common:: struct InternalIDHasher { std::size_t operator()(const common::internalID_t& internalID) const { common::hash_t result; - function::Hash::operation( - internalID, result, nullptr /* keyVector */); + function::Hash::operation(internalID, result, + nullptr /* keyVector */); return result; } }; diff --git a/src/include/function/hash/vector_hash_functions.h b/src/include/function/hash/vector_hash_functions.h index 62c01aae08a..1a73c939da1 100644 --- a/src/include/function/hash/vector_hash_functions.h +++ b/src/include/function/hash/vector_hash_functions.h @@ -21,22 +21,22 @@ struct UnaryHashFunctionExecutor { if (operand.hasNoNullsGuarantee()) { if (operand.state->selVector->isUnfiltered()) { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { - Hash::operation( - operand.getValue(i), resultValues[i], &operand); + Hash::operation(operand.getValue(i), resultValues[i], + &operand); } } else { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { auto pos = operand.state->selVector->selectedPositions[i]; - Hash::operation( - operand.getValue(pos), resultValues[pos], &operand); + Hash::operation(operand.getValue(pos), resultValues[pos], + &operand); } } } else { if (operand.state->selVector->isUnfiltered()) { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { if (!operand.isNull(i)) { - Hash::operation( - operand.getValue(i), resultValues[i], &operand); + Hash::operation(operand.getValue(i), resultValues[i], + &operand); } else { result.setValue(i, NULL_HASH); } @@ -45,8 +45,8 @@ struct UnaryHashFunctionExecutor { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { auto pos = operand.state->selVector->selectedPositions[i]; if (!operand.isNull(pos)) { - Hash::operation( - operand.getValue(pos), resultValues[pos], &operand); + Hash::operation(operand.getValue(pos), resultValues[pos], + &operand); } else { resultValues[pos] = NULL_HASH; } @@ -60,8 +60,8 @@ struct UnaryHashFunctionExecutor { struct VectorHashFunction { static void computeHash(common::ValueVector* operand, common::ValueVector* result); - static void combineHash( - common::ValueVector* left, common::ValueVector* right, common::ValueVector* result); + static void combineHash(common::ValueVector* left, common::ValueVector* right, + common::ValueVector* result); }; } // namespace function diff --git a/src/include/function/interval/vector_interval_functions.h b/src/include/function/interval/vector_interval_functions.h index f107f87f5bf..fdeef159f7e 100644 --- a/src/include/function/interval/vector_interval_functions.h +++ b/src/include/function/interval/vector_interval_functions.h @@ -9,7 +9,7 @@ namespace function { struct IntervalFunction { public: template - static inline function_set getUnaryIntervalFunction(std::string funcName) { + static function_set getUnaryIntervalFunction(std::string funcName) { function_set result; result.push_back(std::make_unique(funcName, std::vector{common::LogicalTypeID::INT64}, @@ -20,52 +20,66 @@ struct IntervalFunction { }; struct ToYearsFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction(common::TO_YEARS_FUNC_NAME); + static constexpr const char* name = "TO_YEARS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToMonthsFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction(common::TO_MONTHS_FUNC_NAME); + static constexpr const char* name = "TO_MONTHS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToDaysFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction(common::TO_DAYS_FUNC_NAME); + static constexpr const char* name = "TO_DAYS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToHoursFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction(common::TO_HOURS_FUNC_NAME); + static constexpr const char* name = "TO_HOURS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToMinutesFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction(common::TO_MINUTES_FUNC_NAME); + static constexpr const char* name = "TO_MINUTES"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToSecondsFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction(common::TO_SECONDS_FUNC_NAME); + static constexpr const char* name = "TO_SECONDS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToMillisecondsFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction( - common::TO_MILLISECONDS_FUNC_NAME); + static constexpr const char* name = "TO_MILLISECONDS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; struct ToMicrosecondsFunction { - static inline function_set getFunctionSet() { - return IntervalFunction::getUnaryIntervalFunction( - common::TO_MICROSECONDS_FUNC_NAME); + static constexpr const char* name = "TO_MICROSECONDS"; + + static function_set getFunctionSet() { + return IntervalFunction::getUnaryIntervalFunction(name); } }; diff --git a/src/include/function/list/functions/base_list_sort_function.h b/src/include/function/list/functions/base_list_sort_function.h index 5d8cf542d38..47684f1e765 100644 --- a/src/include/function/list/functions/base_list_sort_function.h +++ b/src/include/function/list/functions/base_list_sort_function.h @@ -68,8 +68,8 @@ struct BaseListSortOperation { // Add nulls in the end. if (!nullFirst) { - setVectorRangeToNull( - *resultDataVector, result.offset, input.size - nullCount, input.size); + setVectorRangeToNull(*resultDataVector, result.offset, input.size - nullCount, + input.size); } // Determine the starting and ending position of the data to be sorted. @@ -90,8 +90,8 @@ struct BaseListSortOperation { } } - static void setVectorRangeToNull( - common::ValueVector& vector, uint64_t offset, uint64_t startPos, uint64_t endPos) { + static void setVectorRangeToNull(common::ValueVector& vector, uint64_t offset, + uint64_t startPos, uint64_t endPos) { for (auto i = startPos; i < endPos; i++) { vector.setNull(offset + i, true); } diff --git a/src/include/function/list/functions/list_any_value_function.h b/src/include/function/list/functions/list_any_value_function.h index 4970d6c5b49..8adcbb076f8 100644 --- a/src/include/function/list/functions/list_any_value_function.h +++ b/src/include/function/list/functions/list_any_value_function.h @@ -15,8 +15,8 @@ struct ListAnyValue { for (auto i = 0u; i < input.size; i++) { if (!(inputDataVector->isNull(input.offset + i))) { - resultVector.copyFromVectorData( - reinterpret_cast(&result), inputDataVector, inputValues); + resultVector.copyFromVectorData(reinterpret_cast(&result), + inputDataVector, inputValues); break; } inputValues += numBytesPerValue; diff --git a/src/include/function/list/functions/list_distinct_function.h b/src/include/function/list/functions/list_distinct_function.h index b3beff0263a..0a9f9523645 100644 --- a/src/include/function/list/functions/list_distinct_function.h +++ b/src/include/function/list/functions/list_distinct_function.h @@ -28,8 +28,8 @@ struct ListDistinct { auto resultDataVector = common::ListVector::getDataVector(&resultVector); auto numBytesPerValue = inputDataVector->getNumBytesPerValue(); for (auto val : uniqueValues) { - resultDataVector->copyFromVectorData( - resultValues, inputDataVector, reinterpret_cast(&val)); + resultDataVector->copyFromVectorData(resultValues, inputDataVector, + reinterpret_cast(&val)); resultValues += numBytesPerValue; } } diff --git a/src/include/function/list/functions/list_extract_function.h b/src/include/function/list/functions/list_extract_function.h index 46199930672..1a6ef0c6db3 100644 --- a/src/include/function/list/functions/list_extract_function.h +++ b/src/include/function/list/functions/list_extract_function.h @@ -32,13 +32,13 @@ struct ListExtract { if (!resultVector.isNull(resPos)) { auto listValues = common::ListVector::getListValuesWithOffset(&listVector, listEntry, upos - 1); - resultVector.copyFromVectorData( - reinterpret_cast(&result), listDataVector, listValues); + resultVector.copyFromVectorData(reinterpret_cast(&result), listDataVector, + listValues); } } - static inline void operation( - common::ku_string_t& str, int64_t& idx, common::ku_string_t& result) { + static inline void operation(common::ku_string_t& str, int64_t& idx, + common::ku_string_t& result) { if (str.len < idx) { result.set("", 0); } else { diff --git a/src/include/function/list/functions/list_len_function.h b/src/include/function/list/functions/list_len_function.h index 3c6e22d56be..25af99da23d 100644 --- a/src/include/function/list/functions/list_len_function.h +++ b/src/include/function/list/functions/list_len_function.h @@ -25,8 +25,8 @@ inline void ListLen::operation(common::ku_string_t& input, int64_t& result) { int64_t length = 0; // Use grapheme iterator to identify bytes of utf8 char and increment once for each // char. - utf8proc::utf8proc_grapheme_callback( - inputString.c_str(), totalByteLength, [&](size_t /*start*/, size_t /*end*/) { + utf8proc::utf8proc_grapheme_callback(inputString.c_str(), totalByteLength, + [&](size_t /*start*/, size_t /*end*/) { length++; return true; }); diff --git a/src/include/function/list/functions/list_position_function.h b/src/include/function/list/functions/list_position_function.h index 50567a52b35..d47f0558c73 100644 --- a/src/include/function/list/functions/list_position_function.h +++ b/src/include/function/list/functions/list_position_function.h @@ -13,7 +13,7 @@ struct ListPosition { static inline void operation(common::list_entry_t& list, T& element, int64_t& result, common::ValueVector& listVector, common::ValueVector& elementVector, common::ValueVector& /*resultVector*/) { - if (*common::VarListType::getChildType(&listVector.dataType) != elementVector.dataType) { + if (*common::ListType::getChildType(&listVector.dataType) != elementVector.dataType) { result = 0; return; } diff --git a/src/include/function/list/functions/list_range_function.h b/src/include/function/list/functions/list_range_function.h index b7bf9b118a1..6d8be4e96c5 100644 --- a/src/include/function/list/functions/list_range_function.h +++ b/src/include/function/list/functions/list_range_function.h @@ -9,7 +9,7 @@ struct Range { public: // range function: // - include end - // - when start = end: there is only one element in result varlist + // - when start = end: there is only one element in result list // - when end - start are of opposite sign of step, the result will be empty // - default step = 1 template diff --git a/src/include/function/list/functions/list_reverse_sort_function.h b/src/include/function/list/functions/list_reverse_sort_function.h index 704a7785ba2..e0f84011c2a 100644 --- a/src/include/function/list/functions/list_reverse_sort_function.h +++ b/src/include/function/list/functions/list_reverse_sort_function.h @@ -10,8 +10,8 @@ template struct ListReverseSort : BaseListSortOperation { static inline void operation(common::list_entry_t& input, common::list_entry_t& result, common::ValueVector& inputVector, common::ValueVector& resultVector) { - sortValues( - input, result, inputVector, resultVector, false /* ascOrder */, true /* nullFirst */); + sortValues(input, result, inputVector, resultVector, false /* ascOrder */, + true /* nullFirst */); } static inline void operation(common::list_entry_t& input, common::ku_string_t& nullOrder, diff --git a/src/include/function/list/functions/list_sort_function.h b/src/include/function/list/functions/list_sort_function.h index 99b720d3ec6..fe0616d1049 100644 --- a/src/include/function/list/functions/list_sort_function.h +++ b/src/include/function/list/functions/list_sort_function.h @@ -10,8 +10,8 @@ template struct ListSort : BaseListSortOperation { static inline void operation(common::list_entry_t& input, common::list_entry_t& result, common::ValueVector& inputVector, common::ValueVector& resultVector) { - sortValues( - input, result, inputVector, resultVector, true /* ascOrder */, true /* nullFirst */); + sortValues(input, result, inputVector, resultVector, true /* ascOrder */, + true /* nullFirst */); } static inline void operation(common::list_entry_t& input, common::ku_string_t& sortOrder, diff --git a/src/include/function/list/vector_list_functions.h b/src/include/function/list/vector_list_functions.h index f65fa957835..180c745671b 100644 --- a/src/include/function/list/vector_list_functions.h +++ b/src/include/function/list/vector_list_functions.h @@ -1,321 +1,131 @@ #pragma once -#include "common/exception/binder.h" -#include "common/types/int128_t.h" -#include "common/types/interval_t.h" -#include "function/scalar_function.h" +#include "common/vector/value_vector.h" +#include "function/function.h" namespace kuzu { namespace function { -struct ListFunction { - template - static scalar_exec_func getBinaryListExecFuncSwitchRight(const common::LogicalType& rightType) { - scalar_exec_func execFunc; - switch (rightType.getPhysicalType()) { - case common::PhysicalTypeID::BOOL: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT64: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT32: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT16: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT8: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::UINT64: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::UINT32: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::UINT16: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::UINT8: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT128: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::DOUBLE: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::FLOAT: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::STRING: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INTERVAL: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INTERNAL_ID: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::VAR_LIST: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::STRUCT: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - default: { - KU_UNREACHABLE; - } - } - return execFunc; - } - - template - static scalar_exec_func getBinaryListExecFuncSwitchAll(const common::LogicalType& type) { - scalar_exec_func execFunc; - switch (type.getPhysicalType()) { - case common::PhysicalTypeID::INT64: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT32: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT16: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT8: { - execFunc = ScalarFunction::BinaryExecListStructFunction; - } break; - default: { - KU_UNREACHABLE; - } - } - return execFunc; - } - - template - static scalar_exec_func getTernaryListExecFuncSwitchAll(const common::LogicalType& type) { - scalar_exec_func execFunc; - switch (type.getPhysicalType()) { - case common::PhysicalTypeID::INT64: { - execFunc = ScalarFunction::TernaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT32: { - execFunc = ScalarFunction::TernaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT16: { - execFunc = ScalarFunction::TernaryExecListStructFunction; - } break; - case common::PhysicalTypeID::INT8: { - execFunc = ScalarFunction::TernaryExecListStructFunction; - } break; - default: { - KU_UNREACHABLE; - } - } - return execFunc; - } - - template - static std::unique_ptr bindFuncListAggr( - const binder::expression_vector& arguments, Function* function) { - auto scalarFunction = common::ku_dynamic_cast(function); - auto resultType = common::VarListType::getChildType(&arguments[0]->dataType); - switch (resultType->getLogicalTypeID()) { - case common::LogicalTypeID::SERIAL: - case common::LogicalTypeID::INT64: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::INT32: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::INT16: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::INT8: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::UINT64: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::UINT32: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::UINT16: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::UINT8: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::INT128: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::DOUBLE: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - case common::LogicalTypeID::FLOAT: { - scalarFunction->execFunc = - ScalarFunction::UnaryExecNestedTypeFunction; - } break; - default: { - throw common::BinderException( - common::stringFormat("Unsupported inner data type for {}: {}", function->name, - common::LogicalTypeUtils::toString(resultType->getLogicalTypeID()))); - } - } - return std::make_unique(resultType->copy()); - } -}; - struct ListCreationFunction { + static constexpr const char* name = "LIST_CREATION"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); static void execFunc(const std::vector>& parameters, common::ValueVector& result, void* /*dataPtr*/ = nullptr); + static common::LogicalType getChildType(const binder::expression_vector& arguments); }; struct ListRangeFunction { + static constexpr const char* name = "RANGE"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct SizeFunction { + static constexpr const char* name = "SIZE"; + + static constexpr const char* alias = "CARDINALITY"; + static function_set getFunctionSet(); }; struct ListExtractFunction { + static constexpr const char* name = "LIST_EXTRACT"; + + static constexpr const char* alias = "LIST_ELEMENT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListConcatFunction { + static constexpr const char* name = "LIST_CONCAT"; + + static constexpr const char* alias = "LIST_CAT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); + static std::unique_ptr bindFunc(const binder::expression_vector& arguments, + Function* function); }; struct ListAppendFunction { + static constexpr const char* name = "LIST_APPEND"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListPrependFunction { + static constexpr const char* name = "LIST_PREPEND"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListPositionFunction { + static constexpr const char* name = "LIST_POSITION"; + + static constexpr const char* alias = "LIST_INDEXOF"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListContainsFunction { + static constexpr const char* name = "LIST_CONTAINS"; + + static constexpr const char* alias = "LIST_HAS"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListSliceFunction { + static constexpr const char* name = "LIST_SLICE"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListSortFunction { + static constexpr const char* name = "LIST_SORT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); - template - static void getExecFunction(const binder::expression_vector& arguments, scalar_exec_func& func); }; struct ListReverseSortFunction { + static constexpr const char* name = "LIST_REVERSE_SORT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); - template - static void getExecFunction(const binder::expression_vector& arguments, scalar_exec_func& func); }; struct ListSumFunction { + static constexpr const char* name = "LIST_SUM"; + static function_set getFunctionSet(); }; struct ListProductFunction { + static constexpr const char* name = "LIST_PRODUCT"; + static function_set getFunctionSet(); }; struct ListDistinctFunction { + static constexpr const char* name = "LIST_DISTINCT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListUniqueFunction { + static constexpr const char* name = "LIST_UNIQUE"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListAnyValueFunction { + static constexpr const char* name = "LIST_ANY_VALUE"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct ListReverseFunction { + static constexpr const char* name = "LIST_REVERSE"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/map/functions/map_keys_function.h b/src/include/function/map/functions/map_keys_function.h index dd5e9121777..26e59af3512 100644 --- a/src/include/function/map/functions/map_keys_function.h +++ b/src/include/function/map/functions/map_keys_function.h @@ -10,8 +10,8 @@ struct MapKeys : public BaseMapExtract { common::ValueVector& listVector, common::ValueVector& resultVector) { auto mapKeyVector = common::MapVector::getKeyVector(&listVector); auto mapKeyValues = common::MapVector::getMapKeys(&listVector, listEntry); - BaseMapExtract::operation( - resultEntry, resultVector, mapKeyValues, mapKeyVector, listEntry.size); + BaseMapExtract::operation(resultEntry, resultVector, mapKeyValues, mapKeyVector, + listEntry.size); } }; diff --git a/src/include/function/map/functions/map_values_function.h b/src/include/function/map/functions/map_values_function.h index 81efb07b6a6..a4f68a4a39c 100644 --- a/src/include/function/map/functions/map_values_function.h +++ b/src/include/function/map/functions/map_values_function.h @@ -11,8 +11,8 @@ struct MapValues : public BaseMapExtract { common::ValueVector& listVector, common::ValueVector& resultVector) { auto mapValueVector = common::MapVector::getValueVector(&listVector); auto mapValueValues = common::MapVector::getMapValues(&listVector, listEntry); - BaseMapExtract::operation( - resultEntry, resultVector, mapValueValues, mapValueVector, listEntry.size); + BaseMapExtract::operation(resultEntry, resultVector, mapValueValues, mapValueVector, + listEntry.size); } }; diff --git a/src/include/function/map/vector_map_functions.h b/src/include/function/map/vector_map_functions.h index 8448b4e6c36..da996786518 100644 --- a/src/include/function/map/vector_map_functions.h +++ b/src/include/function/map/vector_map_functions.h @@ -1,32 +1,34 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct MapCreationFunctions { + static constexpr const char* name = "MAP"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct MapExtractFunctions { + static constexpr const char* name = "MAP_EXTRACT"; + + static constexpr const char* alias = "ELEMENT_AT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct MapKeysFunctions { + static constexpr const char* name = "MAP_KEYS"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct MapValuesFunctions { + static constexpr const char* name = "MAP_VALUES"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; } // namespace function diff --git a/src/include/function/null/null_function_executor.h b/src/include/function/null/null_function_executor.h index 3a8b5ef9746..ad54389138b 100644 --- a/src/include/function/null/null_function_executor.h +++ b/src/include/function/null/null_function_executor.h @@ -13,13 +13,14 @@ struct NullOperationExecutor { auto resultValues = (uint8_t*)result.getData(); if (operand.state->isFlat()) { auto pos = operand.state->selVector->selectedPositions[0]; - FUNC::operation( - operand.getValue(pos), (bool)operand.isNull(pos), resultValues[pos]); + auto resultPos = result.state->selVector->selectedPositions[0]; + FUNC::operation(operand.getValue(pos), (bool)operand.isNull(pos), + resultValues[resultPos]); } else { if (operand.state->selVector->isUnfiltered()) { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { - FUNC::operation( - operand.getValue(i), (bool)operand.isNull(i), resultValues[i]); + FUNC::operation(operand.getValue(i), (bool)operand.isNull(i), + resultValues[i]); } } else { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { @@ -40,10 +41,10 @@ struct NullOperationExecutor { return resultValue == true; } else { uint64_t numSelectedValues = 0; - auto selectedPositionsBuffer = selVector.getSelectedPositionsBuffer(); + auto buffer = selVector.getMultableBuffer(); for (auto i = 0ul; i < operand.state->selVector->selectedSize; i++) { auto pos = operand.state->selVector->selectedPositions[i]; - selectOnValue(operand, pos, numSelectedValues, selectedPositionsBuffer); + selectOnValue(operand, pos, numSelectedValues, buffer); } selVector.selectedSize = numSelectedValues; return numSelectedValues > 0; @@ -54,8 +55,8 @@ struct NullOperationExecutor { static void selectOnValue(common::ValueVector& operand, uint64_t operandPos, uint64_t& numSelectedValues, common::sel_t* selectedPositionsBuffer) { uint8_t resultValue = 0; - FUNC::operation( - operand.getValue(operandPos), operand.isNull(operandPos), resultValue); + FUNC::operation(operand.getValue(operandPos), operand.isNull(operandPos), + resultValue); selectedPositionsBuffer[numSelectedValues] = operandPos; numSelectedValues += resultValue == true; } diff --git a/src/include/function/null/vector_null_functions.h b/src/include/function/null/vector_null_functions.h index 6e1ec837b78..d54c17f7d1b 100644 --- a/src/include/function/null/vector_null_functions.h +++ b/src/include/function/null/vector_null_functions.h @@ -9,10 +9,10 @@ namespace function { class VectorNullFunction { public: static void bindExecFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_exec_func& func); + const binder::expression_vector& children, scalar_func_exec_t& func); static void bindSelectFunction(common::ExpressionType expressionType, - const binder::expression_vector& children, scalar_select_func& func); + const binder::expression_vector& children, scalar_func_select_t& func); private: template diff --git a/src/include/function/path/path_function_executor.h b/src/include/function/path/path_function_executor.h index 61af150bbd9..d69d34655b1 100644 --- a/src/include/function/path/path_function_executor.h +++ b/src/include/function/path/path_function_executor.h @@ -42,8 +42,8 @@ struct UnaryPathExecutor { execute(*input.state->selVector, *relsVector, internalIDFieldIdx, result); } - static bool selectNodeIDs( - common::ValueVector& input, common::SelectionVector& selectionVector) { + static bool selectNodeIDs(common::ValueVector& input, + common::SelectionVector& selectionVector) { auto nodesFieldIdx = 0; KU_ASSERT(nodesFieldIdx == common::StructType::getFieldIdx(&input.dataType, common::InternalKeyword::NODES)); @@ -66,24 +66,24 @@ struct UnaryPathExecutor { common::ValueVector& listVector, common::struct_field_idx_t fieldIdx, common::ValueVector& result) { auto listDataVector = common::ListVector::getDataVector(&listVector); - KU_ASSERT(fieldIdx == common::StructType::getFieldIdx( - &listDataVector->dataType, common::InternalKeyword::ID)); + KU_ASSERT(fieldIdx == common::StructType::getFieldIdx(&listDataVector->dataType, + common::InternalKeyword::ID)); auto internalIDsVector = common::StructVector::getFieldVector(listDataVector, fieldIdx).get(); std::unordered_set internalIDSet; if (inputSelVector.isUnfiltered()) { for (auto i = 0u; i < inputSelVector.selectedSize; ++i) { auto& listEntry = listVector.getValue(i); - bool isTrail = isAllInternalIDDistinct( - internalIDsVector, listEntry.offset, listEntry.size, internalIDSet); + bool isTrail = isAllInternalIDDistinct(internalIDsVector, listEntry.offset, + listEntry.size, internalIDSet); result.setValue(i, isTrail); } } else { for (auto i = 0u; i < inputSelVector.selectedSize; ++i) { auto pos = inputSelVector.selectedPositions[i]; auto& listEntry = listVector.getValue(pos); - bool isTrail = isAllInternalIDDistinct( - internalIDsVector, listEntry.offset, listEntry.size, internalIDSet); + bool isTrail = isAllInternalIDDistinct(internalIDsVector, listEntry.offset, + listEntry.size, internalIDSet); result.setValue(pos, isTrail); } } @@ -93,18 +93,18 @@ struct UnaryPathExecutor { common::ValueVector& listVector, common::struct_field_idx_t fieldIdx, common::SelectionVector& selectionVector) { auto listDataVector = common::ListVector::getDataVector(&listVector); - KU_ASSERT(fieldIdx == common::StructType::getFieldIdx( - &listDataVector->dataType, common::InternalKeyword::ID)); + KU_ASSERT(fieldIdx == common::StructType::getFieldIdx(&listDataVector->dataType, + common::InternalKeyword::ID)); auto internalIDsVector = common::StructVector::getFieldVector(listDataVector, fieldIdx).get(); std::unordered_set internalIDSet; auto numSelectedValues = 0u; - auto buffer = selectionVector.getSelectedPositionsBuffer(); + auto buffer = selectionVector.getMultableBuffer(); if (inputSelVector.isUnfiltered()) { for (auto i = 0u; i < inputSelVector.selectedSize; ++i) { auto& listEntry = listVector.getValue(i); - bool isTrail = isAllInternalIDDistinct( - internalIDsVector, listEntry.offset, listEntry.size, internalIDSet); + bool isTrail = isAllInternalIDDistinct(internalIDsVector, listEntry.offset, + listEntry.size, internalIDSet); buffer[numSelectedValues] = i; numSelectedValues += isTrail; } @@ -112,8 +112,8 @@ struct UnaryPathExecutor { for (auto i = 0u; i < inputSelVector.selectedSize; ++i) { auto pos = inputSelVector.selectedPositions[i]; auto& listEntry = listVector.getValue(pos); - bool isTrail = isAllInternalIDDistinct( - internalIDsVector, listEntry.offset, listEntry.size, internalIDSet); + bool isTrail = isAllInternalIDDistinct(internalIDsVector, listEntry.offset, + listEntry.size, internalIDSet); buffer[numSelectedValues] = pos; numSelectedValues += isTrail; } diff --git a/src/include/function/path/vector_path_functions.h b/src/include/function/path/vector_path_functions.h index 206d66d075b..051b493d17e 100644 --- a/src/include/function/path/vector_path_functions.h +++ b/src/include/function/path/vector_path_functions.h @@ -1,20 +1,20 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct NodesFunction { + static constexpr const char* name = "NODES"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct RelsFunction { + static constexpr const char* name = "RELS"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); }; struct PropertiesBindData : public FunctionBindData { @@ -25,30 +25,25 @@ struct PropertiesBindData : public FunctionBindData { }; struct PropertiesFunction { + static constexpr const char* name = "PROPERTIES"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); - static void compileFunc(FunctionBindData* bindData, - const std::vector>& parameters, - std::shared_ptr& result); - static void execFunc(const std::vector>& parameters, - common::ValueVector& result, void* /*dataPtr*/ = nullptr); }; struct IsTrailFunction { + static constexpr const char* name = "IS_TRAIL"; + static function_set getFunctionSet(); - static void execFunc(const std::vector>& parameters, - common::ValueVector& result, void* /*dataPtr*/ = nullptr); - static bool selectFunc(const std::vector>& parameters, - common::SelectionVector& selectionVector); }; struct IsACyclicFunction { + static constexpr const char* name = "IS_ACYCLIC"; + static function_set getFunctionSet(); - static void execFunc(const std::vector>& parameters, - common::ValueVector& result, void* /*dataPtr*/ = nullptr); - static bool selectFunc(const std::vector>& parameters, - common::SelectionVector& selectionVector); +}; + +struct LengthFunction { + static constexpr const char* name = "LENGTH"; }; } // namespace function diff --git a/src/include/function/rdf/vector_rdf_functions.h b/src/include/function/rdf/vector_rdf_functions.h index e653292be6d..016cec9c4c4 100644 --- a/src/include/function/rdf/vector_rdf_functions.h +++ b/src/include/function/rdf/vector_rdf_functions.h @@ -1,15 +1,19 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct RDFTypeFunction { + static constexpr const char* name = "TYPE"; + static function_set getFunctionSet(); }; struct ValidatePredicateFunction { + static constexpr const char* name = "VALIDATE_PREDICATE"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/rewrite_function.h b/src/include/function/rewrite_function.h new file mode 100644 index 00000000000..0fc9bb5d9c9 --- /dev/null +++ b/src/include/function/rewrite_function.h @@ -0,0 +1,32 @@ +#pragma once + +#include "function.h" + +namespace kuzu { +namespace binder { +class ExpressionBinder; +} +namespace function { + +// Rewrite function to a different expression, e.g. id(n) -> n._id. +using rewrite_func_rewrite_t = std::function( + const binder::expression_vector&, binder::ExpressionBinder*)>; + +// We write for the following functions +// ID(n) -> n._id +struct RewriteFunction final : public Function { + + RewriteFunction(std::string name, std::vector parameterTypeIDs, + rewrite_func_rewrite_t rewriteFunc) + : Function{FunctionType::REWRITE, name, std::move(parameterTypeIDs)}, + rewriteFunc{rewriteFunc} {} + + std::unique_ptr copy() const override { + return std::make_unique(*this); + } + + rewrite_func_rewrite_t rewriteFunc; +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/scalar_function.h b/src/include/function/scalar_function.h index eb89db0d9f8..48ff546e712 100644 --- a/src/include/function/scalar_function.h +++ b/src/include/function/scalar_function.h @@ -8,43 +8,44 @@ #include "unary_function_executor.h" namespace kuzu { -namespace function { -struct ScalarFunction; +namespace function { -using scalar_compile_func = +// Evaluate function at compile time, e.g. struct_extraction. +using scalar_func_compile_exec_t = std::function>&, std::shared_ptr&)>; -using scalar_exec_func = std::function>&, common::ValueVector&, void*)>; -using scalar_select_func = std::function>&, common::SelectionVector&)>; -using function_set = std::vector>; struct ScalarFunction final : public BaseScalarFunction { ScalarFunction(std::string name, std::vector parameterTypeIDs, - common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, bool isVarLength = false) + common::LogicalTypeID returnTypeID, scalar_func_exec_t execFunc, bool isVarLength = false) : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, std::move(execFunc), nullptr, nullptr, nullptr, isVarLength} {} ScalarFunction(std::string name, std::vector parameterTypeIDs, - common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, - scalar_select_func selectFunc, bool isVarLength = false) + common::LogicalTypeID returnTypeID, scalar_func_exec_t execFunc, + scalar_func_select_t selectFunc, bool isVarLength = false) : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, std::move(execFunc), std::move(selectFunc), nullptr, nullptr, isVarLength} {} ScalarFunction(std::string name, std::vector parameterTypeIDs, - common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, - scalar_select_func selectFunc, scalar_bind_func bindFunc, bool isVarLength = false) + common::LogicalTypeID returnTypeID, scalar_func_exec_t execFunc, + scalar_func_select_t selectFunc, scalar_bind_func bindFunc, bool isVarLength = false) : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, std::move(execFunc), std::move(selectFunc), nullptr, std::move(bindFunc), isVarLength} {} ScalarFunction(std::string name, std::vector parameterTypeIDs, - common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, - scalar_select_func selectFunc, scalar_compile_func compileFunc, scalar_bind_func bindFunc, - bool isVarLength = false) + common::LogicalTypeID returnTypeID, scalar_func_exec_t execFunc, + scalar_func_select_t selectFunc, scalar_func_compile_exec_t compileFunc, + scalar_bind_func bindFunc, bool isVarLength = false) : BaseScalarFunction{FunctionType::SCALAR, std::move(name), std::move(parameterTypeIDs), returnTypeID, std::move(bindFunc)}, execFunc{std::move(execFunc)}, selectFunc(std::move(selectFunc)), @@ -54,8 +55,8 @@ struct ScalarFunction final : public BaseScalarFunction { static void TernaryExecFunction(const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) { KU_ASSERT(params.size() == 3); - TernaryFunctionExecutor::execute( - *params[0], *params[1], *params[2], result); + TernaryFunctionExecutor::execute(*params[0], + *params[1], *params[2], result); } template @@ -71,8 +72,8 @@ struct ScalarFunction final : public BaseScalarFunction { static void BinaryExecFunction(const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) { KU_ASSERT(params.size() == 2); - BinaryFunctionExecutor::execute( - *params[0], *params[1], result); + BinaryFunctionExecutor::execute(*params[0], + *params[1], result); } template @@ -80,8 +81,8 @@ struct ScalarFunction final : public BaseScalarFunction { const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) { KU_ASSERT(params.size() == 2); - BinaryFunctionExecutor::executeString( - *params[0], *params[1], result); + BinaryFunctionExecutor::executeString(*params[0], + *params[1], result); } template @@ -89,8 +90,8 @@ struct ScalarFunction final : public BaseScalarFunction { const std::vector>& params, common::SelectionVector& selVector) { KU_ASSERT(params.size() == 2); - return BinaryFunctionExecutor::select( - *params[0], *params[1], selVector); + return BinaryFunctionExecutor::select(*params[0], *params[1], + selVector); } template(*this); } - scalar_exec_func execFunc; - scalar_select_func selectFunc; - scalar_compile_func compileFunc; + scalar_func_exec_t execFunc; + scalar_func_select_t selectFunc; + scalar_func_compile_exec_t compileFunc; // Currently we only one variable-length function which is list creation. The expectation is // that all parameters must have the same type as parameterTypes[0]. bool isVarLength; diff --git a/src/include/function/schema/vector_label_functions.h b/src/include/function/schema/vector_label_functions.h index 27742d23d27..5152ab1d615 100644 --- a/src/include/function/schema/vector_label_functions.h +++ b/src/include/function/schema/vector_label_functions.h @@ -7,6 +7,8 @@ namespace kuzu { namespace function { struct LabelFunction { + static constexpr const char* name = "LABEL"; + static void execFunction(const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) { KU_ASSERT(params.size() == 2); diff --git a/src/include/function/schema/vector_node_rel_functions.h b/src/include/function/schema/vector_node_rel_functions.h index 7d88a743c41..454ff89843d 100644 --- a/src/include/function/schema/vector_node_rel_functions.h +++ b/src/include/function/schema/vector_node_rel_functions.h @@ -1,18 +1,28 @@ #pragma once -#include "function/scalar_function.h" -#include "offset_functions.h" +#include "function/function.h" namespace kuzu { namespace function { struct OffsetFunction { + static constexpr const char* name = "OFFSET"; + + static function_set getFunctionSet(); +}; + +struct IDFunction { + static constexpr const char* name = "ID"; + static function_set getFunctionSet(); - static void execFunction(const std::vector>& params, - common::ValueVector& result, void* /*dataPtr*/ = nullptr) { - KU_ASSERT(params.size() == 1); - UnaryFunctionExecutor::execute(*params[0], result); - } +}; + +struct StartNodeFunction { + static constexpr const char* name = "START_NODE"; +}; + +struct EndNodeFunction { + static constexpr const char* name = "END_NODE"; }; } // namespace function diff --git a/src/include/function/string/functions/array_extract_function.h b/src/include/function/string/functions/array_extract_function.h index 1e03e984dbb..a0c6f5e1e7c 100644 --- a/src/include/function/string/functions/array_extract_function.h +++ b/src/include/function/string/functions/array_extract_function.h @@ -9,8 +9,8 @@ namespace kuzu { namespace function { struct ArrayExtract { - static inline void operation( - common::ku_string_t& str, int64_t& idx, common::ku_string_t& result) { + static inline void operation(common::ku_string_t& str, int64_t& idx, + common::ku_string_t& result) { if (idx == 0) { result.len = 0; return; @@ -32,8 +32,8 @@ struct ArrayExtract { copySubstr(str, idxPos, 1 /* length */, result, isAscii); } else { int64_t characterCount = 0, startBytePos = 0, endBytePos = 0; - kuzu::utf8proc::utf8proc_grapheme_callback( - stringVal.c_str(), stringVal.size(), [&](int64_t gstart, int64_t /*gend*/) { + kuzu::utf8proc::utf8proc_grapheme_callback(stringVal.c_str(), stringVal.size(), + [&](int64_t gstart, int64_t /*gend*/) { if (characterCount == startPos) { startBytePos = gstart; } else if (characterCount == endPos) { diff --git a/src/include/function/string/functions/base_lower_upper_function.h b/src/include/function/string/functions/base_lower_upper_function.h index a26df11aad2..e5b38af7389 100644 --- a/src/include/function/string/functions/base_lower_upper_function.h +++ b/src/include/function/string/functions/base_lower_upper_function.h @@ -12,6 +12,8 @@ struct BaseLowerUpperFunction { KUZU_API static void operation(common::ku_string_t& input, common::ku_string_t& result, common::ValueVector& resultValueVector, bool isUpper); + static uint64_t convertCharCase(char* result, const char* input, int32_t charPos, bool toUpper); + private: static uint32_t getResultLen(char* inputStr, uint32_t inputLen, bool isUpper); static void convertCase(char* result, uint32_t len, char* input, bool toUpper); diff --git a/src/include/function/string/functions/base_pad_function.h b/src/include/function/string/functions/base_pad_function.h index f8d661faf72..0d6dd2156d2 100644 --- a/src/include/function/string/functions/base_pad_function.h +++ b/src/include/function/string/functions/base_pad_function.h @@ -21,12 +21,12 @@ struct BasePadOperation { } std::string paddedResult; padOperation(src, count, characterToPad, paddedResult); - common::StringVector::addString( - &resultValueVector, result, paddedResult.data(), paddedResult.size()); + common::StringVector::addString(&resultValueVector, result, paddedResult.data(), + paddedResult.size()); } - static std::pair padCountChars( - const uint32_t count, const char* data, const uint32_t size) { + static std::pair padCountChars(const uint32_t count, const char* data, + const uint32_t size) { auto str = reinterpret_cast(data); uint32_t byteCount = 0, charCount = 0; for (; charCount < count && byteCount < size; charCount++) { @@ -47,8 +47,8 @@ struct BasePadOperation { padByteCount = 0; } utf8proc::utf8proc_int32_t codepoint; - auto bytes = utf8proc::utf8proc_iterate( - padData + padByteCount, padSize - padByteCount, &codepoint); + auto bytes = utf8proc::utf8proc_iterate(padData + padByteCount, padSize - padByteCount, + &codepoint); padByteCount += bytes; } result.insert(result.end(), (char*)padData, (char*)(padData + padByteCount)); diff --git a/src/include/function/string/functions/base_regexp_function.h b/src/include/function/string/functions/base_regexp_function.h index b8781e81a0a..8dda8c6747d 100644 --- a/src/include/function/string/functions/base_regexp_function.h +++ b/src/include/function/string/functions/base_regexp_function.h @@ -15,8 +15,8 @@ struct BaseRegexpOperation { return std::regex_replace(pattern, std::regex(R"(\\\\)"), "\\"); } - static inline void copyToKuzuString( - const std::string& value, common::ku_string_t& kuString, common::ValueVector& valueVector) { + static inline void copyToKuzuString(const std::string& value, common::ku_string_t& kuString, + common::ValueVector& valueVector) { common::StringVector::addString(&valueVector, kuString, value.data(), value.length()); } }; diff --git a/src/include/function/string/functions/concat_function.h b/src/include/function/string/functions/concat_function.h deleted file mode 100644 index 337f83fe9d0..00000000000 --- a/src/include/function/string/functions/concat_function.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "common/api.h" -#include "common/types/ku_string.h" -#include "common/vector/value_vector.h" - -namespace kuzu { -namespace function { - -struct Concat { - template - static inline void operation( - A& /*left*/, B& /*right*/, R& /*result*/, common::ValueVector& /*valueVector*/) { - KU_UNREACHABLE; - } - - KUZU_API static void concat(const char* left, uint32_t leftLen, const char* right, - uint32_t rightLen, common::ku_string_t& result, common::ValueVector& resultValueVector); -}; - -template<> -inline void Concat::operation(common::ku_string_t& left, common::ku_string_t& right, - common::ku_string_t& result, common::ValueVector& resultValueVector) { - concat((const char*)left.getData(), left.len, (const char*)right.getData(), right.len, result, - resultValueVector); -} - -template<> -inline void Concat::operation(std::string& left, std::string& right, common::ku_string_t& result, - common::ValueVector& resultValueVector) { - concat(left.c_str(), left.length(), right.c_str(), right.length(), result, resultValueVector); -} - -} // namespace function -} // namespace kuzu diff --git a/src/include/function/string/functions/contains_function.h b/src/include/function/string/functions/contains_function.h index 985cc08d912..bf90ab72697 100644 --- a/src/include/function/string/functions/contains_function.h +++ b/src/include/function/string/functions/contains_function.h @@ -7,8 +7,8 @@ namespace kuzu { namespace function { struct Contains { - static inline void operation( - common::ku_string_t& left, common::ku_string_t& right, uint8_t& result) { + static inline void operation(common::ku_string_t& left, common::ku_string_t& right, + uint8_t& result) { auto lStr = left.getAsString(); auto rStr = right.getAsString(); int64_t pos; diff --git a/src/include/function/string/functions/ends_with_function.h b/src/include/function/string/functions/ends_with_function.h index 4390d99a6e5..07bc8148696 100644 --- a/src/include/function/string/functions/ends_with_function.h +++ b/src/include/function/string/functions/ends_with_function.h @@ -7,8 +7,8 @@ namespace kuzu { namespace function { struct EndsWith { - static inline void operation( - common::ku_string_t& left, common::ku_string_t& right, uint8_t& result) { + static inline void operation(common::ku_string_t& left, common::ku_string_t& right, + uint8_t& result) { int64_t pos = 0; Find::operation(left, right, pos); result = (pos == left.len - right.len + 1); diff --git a/src/include/function/string/functions/find_function.h b/src/include/function/string/functions/find_function.h index b0b3cac4924..a41bcf739f8 100644 --- a/src/include/function/string/functions/find_function.h +++ b/src/include/function/string/functions/find_function.h @@ -9,8 +9,8 @@ namespace function { // https://github.com/duckdb/duckdb/blob/master/src/function/scalar/string/contains.cpp struct Find { - static inline void operation( - common::ku_string_t& left, common::ku_string_t& right, int64_t& result) { + static inline void operation(common::ku_string_t& left, common::ku_string_t& right, + int64_t& result) { if (right.len == 0) { result = 1; } else if (right.len > left.len) { @@ -33,8 +33,8 @@ struct Find { // Returns the position of the first occurrence of needle in the haystack. If haystack doesn't // contain needle, it returns -1. - static int64_t find( - const uint8_t* haystack, uint32_t haystackLen, const uint8_t* needle, uint32_t needleLen); + static int64_t find(const uint8_t* haystack, uint32_t haystackLen, const uint8_t* needle, + uint32_t needleLen); }; } // namespace function diff --git a/src/include/function/string/functions/initcap_function.h b/src/include/function/string/functions/initcap_function.h new file mode 100644 index 00000000000..3d9b443b3fd --- /dev/null +++ b/src/include/function/string/functions/initcap_function.h @@ -0,0 +1,19 @@ +#pragma once + +#include "base_lower_upper_function.h" +#include "lower_function.h" + +namespace kuzu { +namespace function { + +struct Initcap { + static void operation(common::ku_string_t& operand, common::ku_string_t& result, + common::ValueVector& resultVector) { + Lower::operation(operand, result, resultVector); + BaseLowerUpperFunction::convertCharCase(reinterpret_cast(result.getDataUnsafe()), + reinterpret_cast(result.getData()), 0 /* charPos */, true /* toUpper */); + } +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/string/functions/lpad_function.h b/src/include/function/string/functions/lpad_function.h index 193c9ec8a2c..3bcad0d042e 100644 --- a/src/include/function/string/functions/lpad_function.h +++ b/src/include/function/string/functions/lpad_function.h @@ -11,8 +11,8 @@ struct Lpad : BasePadOperation { static inline void operation(common::ku_string_t& src, int64_t count, common::ku_string_t& characterToPad, common::ku_string_t& result, common::ValueVector& resultValueVector) { - BasePadOperation::operation( - src, count, characterToPad, result, resultValueVector, lpadOperation); + BasePadOperation::operation(src, count, characterToPad, result, resultValueVector, + lpadOperation); } static void lpadOperation(common::ku_string_t& src, int64_t count, diff --git a/src/include/function/string/functions/pad_function.h b/src/include/function/string/functions/pad_function.h index 445cf655b80..50d2ed536a8 100644 --- a/src/include/function/string/functions/pad_function.h +++ b/src/include/function/string/functions/pad_function.h @@ -20,8 +20,8 @@ struct PadOperation { } KU_ASSERT(characterToPad.len == 1); padOperation(result, src, characterToPad); - common::StringVector::addString( - &resultValueVector, result, (const char*)result.getData(), count); + common::StringVector::addString(&resultValueVector, result, (const char*)result.getData(), + count); } }; diff --git a/src/include/function/string/functions/regexp_extract_all_function.h b/src/include/function/string/functions/regexp_extract_all_function.h index 603c0a32efa..4c493bd9482 100644 --- a/src/include/function/string/functions/regexp_extract_all_function.h +++ b/src/include/function/string/functions/regexp_extract_all_function.h @@ -19,8 +19,8 @@ struct RegexpExtractAll : BaseRegexpOperation { for (const auto& match : matches) { common::ku_string_t kuString; copyToKuzuString(match, kuString, *resultDataVector); - resultDataVector->copyFromVectorData( - resultValues, resultDataVector, reinterpret_cast(&kuString)); + resultDataVector->copyFromVectorData(resultValues, resultDataVector, + reinterpret_cast(&kuString)); resultValues += numBytesPerValue; } } @@ -31,8 +31,8 @@ struct RegexpExtractAll : BaseRegexpOperation { operation(value, pattern, defaultGroup, result, resultVector); } - static std::vector regexExtractAll( - const std::string& value, const std::string& pattern, std::int64_t& group) { + static std::vector regexExtractAll(const std::string& value, + const std::string& pattern, std::int64_t& group) { RE2 regex(parseCypherPatten(pattern)); auto submatchCount = regex.NumberOfCapturingGroups() + 1; if (group >= submatchCount) { diff --git a/src/include/function/string/functions/regexp_extract_function.h b/src/include/function/string/functions/regexp_extract_function.h index 17d50c374f0..5918a02bb5c 100644 --- a/src/include/function/string/functions/regexp_extract_function.h +++ b/src/include/function/string/functions/regexp_extract_function.h @@ -17,8 +17,8 @@ struct RegexpExtract : BaseRegexpOperation { static inline void operation(common::ku_string_t& value, common::ku_string_t& pattern, common::ku_string_t& result, common::ValueVector& resultValueVector) { int64_t defaultGroup = 0; - regexExtract( - value.getAsString(), pattern.getAsString(), defaultGroup, result, resultValueVector); + regexExtract(value.getAsString(), pattern.getAsString(), defaultGroup, result, + resultValueVector); } static void regexExtract(const std::string& input, const std::string& pattern, diff --git a/src/include/function/string/functions/regexp_full_match_function.h b/src/include/function/string/functions/regexp_full_match_function.h index 70a881c34b9..05ad9496f57 100644 --- a/src/include/function/string/functions/regexp_full_match_function.h +++ b/src/include/function/string/functions/regexp_full_match_function.h @@ -8,8 +8,8 @@ namespace kuzu { namespace function { struct RegexpFullMatch : BaseRegexpOperation { - static inline void operation( - common::ku_string_t& left, common::ku_string_t& right, uint8_t& result) { + static inline void operation(common::ku_string_t& left, common::ku_string_t& right, + uint8_t& result) { result = RE2::FullMatch(left.getAsString(), parseCypherPatten(right.getAsString())); } }; diff --git a/src/include/function/string/functions/regexp_matches_function.h b/src/include/function/string/functions/regexp_matches_function.h index 0489b0a9eb7..df729a68701 100644 --- a/src/include/function/string/functions/regexp_matches_function.h +++ b/src/include/function/string/functions/regexp_matches_function.h @@ -8,8 +8,8 @@ namespace kuzu { namespace function { struct RegexpMatches : BaseRegexpOperation { - static inline void operation( - common::ku_string_t& left, common::ku_string_t& right, uint8_t& result) { + static inline void operation(common::ku_string_t& left, common::ku_string_t& right, + uint8_t& result) { result = RE2::PartialMatch(left.getAsString(), parseCypherPatten(right.getAsString())); } }; diff --git a/src/include/function/string/functions/regexp_replace_function.h b/src/include/function/string/functions/regexp_replace_function.h index 956b86fda1d..cf20b91c5ca 100644 --- a/src/include/function/string/functions/regexp_replace_function.h +++ b/src/include/function/string/functions/regexp_replace_function.h @@ -12,8 +12,8 @@ struct RegexpReplace : BaseRegexpOperation { common::ku_string_t& replacement, common::ku_string_t& result, common::ValueVector& resultValueVector) { std::string resultStr = value.getAsString(); - RE2::Replace( - &resultStr, parseCypherPatten(pattern.getAsString()), replacement.getAsString()); + RE2::Replace(&resultStr, parseCypherPatten(pattern.getAsString()), + replacement.getAsString()); copyToKuzuString(resultStr, result, resultValueVector); } }; diff --git a/src/include/function/string/functions/rpad_function.h b/src/include/function/string/functions/rpad_function.h index 16a79c227c4..841274bff71 100644 --- a/src/include/function/string/functions/rpad_function.h +++ b/src/include/function/string/functions/rpad_function.h @@ -11,8 +11,8 @@ struct Rpad : BasePadOperation { static inline void operation(common::ku_string_t& src, int64_t count, common::ku_string_t& characterToPad, common::ku_string_t& result, common::ValueVector& resultValueVector) { - BasePadOperation::operation( - src, count, characterToPad, result, resultValueVector, rpadOperation); + BasePadOperation::operation(src, count, characterToPad, result, resultValueVector, + rpadOperation); } static void rpadOperation(common::ku_string_t& src, int64_t count, diff --git a/src/include/function/string/functions/starts_with_function.h b/src/include/function/string/functions/starts_with_function.h index e6a51a34df7..bee3237f058 100644 --- a/src/include/function/string/functions/starts_with_function.h +++ b/src/include/function/string/functions/starts_with_function.h @@ -6,8 +6,8 @@ namespace kuzu { namespace function { struct StartsWith { - static inline void operation( - common::ku_string_t& left, common::ku_string_t& right, uint8_t& result) { + static inline void operation(common::ku_string_t& left, common::ku_string_t& right, + uint8_t& result) { auto lStr = left.getAsString(); auto rStr = right.getAsString(); result = lStr.starts_with(rStr); diff --git a/src/include/function/string/functions/substr_function.h b/src/include/function/string/functions/substr_function.h index 6d6ed1d68d6..0c01ca26b7c 100644 --- a/src/include/function/string/functions/substr_function.h +++ b/src/include/function/string/functions/substr_function.h @@ -29,8 +29,8 @@ struct SubStr { copySubstr(src, start, len, result, resultValueVector, true /* isAscii */); } else { int64_t characterCount = 0, startBytePos = 0, endBytePos = 0; - kuzu::utf8proc::utf8proc_grapheme_callback( - srcStr.c_str(), srcStr.size(), [&](int64_t gstart, int64_t /*gend*/) { + kuzu::utf8proc::utf8proc_grapheme_callback(srcStr.c_str(), srcStr.size(), + [&](int64_t gstart, int64_t /*gend*/) { if (characterCount == startPos) { startBytePos = gstart; } else if ((uint64_t)characterCount == endPos) { @@ -55,12 +55,12 @@ struct SubStr { if (isAscii) { // For normal ASCII char case, we get to the proper byte position to copy from by doing // a -1 (since it is guaranteed each char is 1 byte). - common::StringVector::addString( - &resultValueVector, result, (const char*)(src.getData() + start - 1), length); + common::StringVector::addString(&resultValueVector, result, + (const char*)(src.getData() + start - 1), length); } else { // For utf8 char copy, the function gets the exact starting byte position to copy from. - common::StringVector::addString( - &resultValueVector, result, (const char*)(src.getData() + start), length); + common::StringVector::addString(&resultValueVector, result, + (const char*)(src.getData() + start), length); } } }; diff --git a/src/include/function/string/vector_string_functions.h b/src/include/function/string/vector_string_functions.h index 6eb07dc06c8..067793f689e 100644 --- a/src/include/function/string/vector_string_functions.h +++ b/src/include/function/string/vector_string_functions.h @@ -26,108 +26,161 @@ struct VectorStringFunction { }; struct ArrayExtractFunction { + static constexpr const char* name = "ARRAY_EXTRACT"; + static function_set getFunctionSet(); }; struct ConcatFunction : public VectorStringFunction { + static constexpr const char* name = "CONCAT"; + + static void execFunc(const std::vector>& parameters, + common::ValueVector& result, void* /*dataPtr*/); + static function_set getFunctionSet(); }; struct ContainsFunction : public VectorStringFunction { + static constexpr const char* name = "CONTAINS"; + static function_set getFunctionSet(); }; struct EndsWithFunction : public VectorStringFunction { + static constexpr const char* name = "ENDS_WITH"; + + static constexpr const char* alias = "SUFFIX"; + static function_set getFunctionSet(); }; struct LeftFunction : public VectorStringFunction { + static constexpr const char* name = "LEFT"; + static function_set getFunctionSet(); }; struct LowerFunction : public VectorStringFunction { - static inline function_set getFunctionSet() { - return getUnaryStrFunction(common::LOWER_FUNC_NAME); - } + static constexpr const char* name = "LOWER"; + + static constexpr const char* alias = "LCASE"; + + static inline function_set getFunctionSet() { return getUnaryStrFunction(name); } }; struct LpadFunction : public VectorStringFunction { + static constexpr const char* name = "LPAD"; + static function_set getFunctionSet(); }; struct LtrimFunction : public VectorStringFunction { - static inline function_set getFunctionSet() { - return getUnaryStrFunction(common::LTRIM_FUNC_NAME); - } + static constexpr const char* name = "LTRIM"; + + static inline function_set getFunctionSet() { return getUnaryStrFunction(name); } }; struct RepeatFunction : public VectorStringFunction { + static constexpr const char* name = "REPEAT"; + static function_set getFunctionSet(); }; struct ReverseFunction : public VectorStringFunction { - static inline function_set getFunctionSet() { - return getUnaryStrFunction(common::REVERSE_FUNC_NAME); - } + static constexpr const char* name = "REVERSE"; + + static inline function_set getFunctionSet() { return getUnaryStrFunction(name); } }; struct RightFunction : public VectorStringFunction { + static constexpr const char* name = "RIGHT"; + static function_set getFunctionSet(); }; struct RpadFunction : public VectorStringFunction { + static constexpr const char* name = "RPAD"; + static function_set getFunctionSet(); }; struct RtrimFunction : public VectorStringFunction { - static inline function_set getFunctionSet() { - return getUnaryStrFunction(common::RTRIM_FUNC_NAME); - } + static constexpr const char* name = "RTRIM"; + + static inline function_set getFunctionSet() { return getUnaryStrFunction(name); } }; struct StartsWithFunction : public VectorStringFunction { + static constexpr const char* name = "STARTS_WITH"; + + static constexpr const char* alias = "PREFIX"; + static function_set getFunctionSet(); }; struct SubStrFunction : public VectorStringFunction { + static constexpr const char* name = "SUBSTR"; + + static constexpr const char* alias = "SUBSTRING"; + static function_set getFunctionSet(); }; struct TrimFunction : public VectorStringFunction { - static inline function_set getFunctionSet() { - return getUnaryStrFunction(common::TRIM_FUNC_NAME); - } + static constexpr const char* name = "TRIM"; + + static inline function_set getFunctionSet() { return getUnaryStrFunction(name); } }; struct UpperFunction : public VectorStringFunction { - static inline function_set getFunctionSet() { - return getUnaryStrFunction(common::UPPER_FUNC_NAME); - } + static constexpr const char* name = "UPPER"; + + static constexpr const char* alias = "UCASE"; + + static inline function_set getFunctionSet() { return getUnaryStrFunction(name); } }; struct RegexpFullMatchFunction : public VectorStringFunction { + static constexpr const char* name = "REGEXP_FULL_MATCH"; + static function_set getFunctionSet(); }; struct RegexpMatchesFunction : public VectorStringFunction { + static constexpr const char* name = "REGEXP_MATCHES"; + static function_set getFunctionSet(); }; struct RegexpReplaceFunction : public VectorStringFunction { + static constexpr const char* name = "REGEXP_REPLACE"; + static function_set getFunctionSet(); }; struct RegexpExtractFunction : public VectorStringFunction { + static constexpr const char* name = "REGEXP_EXTRACT"; + static function_set getFunctionSet(); }; struct RegexpExtractAllFunction : public VectorStringFunction { + static constexpr const char* name = "REGEXP_EXTRACT_ALL"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); + static std::unique_ptr bindFunc(const binder::expression_vector& arguments, + Function* function); }; struct LevenshteinFunction : public VectorStringFunction { + static constexpr const char* name = "LEVENSHTEIN"; + + static function_set getFunctionSet(); +}; + +struct InitcapFunction : public VectorStringFunction { + static constexpr const char* name = "INITCAP"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/struct/vector_struct_functions.h b/src/include/function/struct/vector_struct_functions.h index 0dd0f17f064..a0493b0a07a 100644 --- a/src/include/function/struct/vector_struct_functions.h +++ b/src/include/function/struct/vector_struct_functions.h @@ -1,38 +1,38 @@ #pragma once #include "common/vector/value_vector.h" -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct StructPackFunctions { + static constexpr const char* name = "STRUCT_PACK"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); static void execFunc(const std::vector>& parameters, common::ValueVector& result, void* /*dataPtr*/ = nullptr); static void compileFunc(FunctionBindData* bindData, const std::vector>& parameters, std::shared_ptr& result); - static void copyParameterValueToStructFieldVector(const common::ValueVector* parameter, - common::ValueVector* structField, common::DataChunkState* structVectorState); }; struct StructExtractBindData : public FunctionBindData { common::vector_idx_t childIdx; - StructExtractBindData( - std::unique_ptr dataType, common::vector_idx_t childIdx) + StructExtractBindData(std::unique_ptr dataType, + common::vector_idx_t childIdx) : FunctionBindData{std::move(dataType)}, childIdx{childIdx} {} }; struct StructExtractFunctions { + static constexpr const char* name = "STRUCT_EXTRACT"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); + static std::unique_ptr bindFunc(const binder::expression_vector& arguments, + Function* function); static void compileFunc(FunctionBindData* bindData, const std::vector>& parameters, std::shared_ptr& result); diff --git a/src/include/function/table/bind_data.h b/src/include/function/table/bind_data.h index 73116a26f72..28cdab7fa38 100644 --- a/src/include/function/table/bind_data.h +++ b/src/include/function/table/bind_data.h @@ -16,8 +16,8 @@ struct TableFuncBindData { std::vector columnNames; TableFuncBindData() = default; - TableFuncBindData( - std::vector columnTypes, std::vector columnNames) + TableFuncBindData(std::vector columnTypes, + std::vector columnNames) : columnTypes{std::move(columnTypes)}, columnNames{std::move(columnNames)} {} TableFuncBindData(const TableFuncBindData& other) : columnTypes{other.columnTypes}, columnNames{other.columnNames} {} diff --git a/src/include/function/table/bind_input.h b/src/include/function/table/bind_input.h index 85c75ce6348..db25100d470 100644 --- a/src/include/function/table/bind_input.h +++ b/src/include/function/table/bind_input.h @@ -16,8 +16,11 @@ struct TableFuncBindInput { std::vector inputs; TableFuncBindInput() = default; - DELETE_COPY_DEFAULT_MOVE(TableFuncBindInput); + EXPLICIT_COPY_DEFAULT_MOVE(TableFuncBindInput); virtual ~TableFuncBindInput() = default; + +protected: + TableFuncBindInput(const TableFuncBindInput& other) : inputs{other.inputs} {} }; struct ScanTableFuncBindInput final : public TableFuncBindInput { @@ -30,11 +33,18 @@ struct ScanTableFuncBindInput final : public TableFuncBindInput { ScanTableFuncBindInput(common::ReaderConfig config, std::vector expectedColumnNames, std::vector expectedColumnTypes, main::ClientContext* context) - : TableFuncBindInput{}, config{std::move(config)}, expectedColumnNames{std::move( - expectedColumnNames)}, + : TableFuncBindInput{}, config{std::move(config)}, + expectedColumnNames{std::move(expectedColumnNames)}, expectedColumnTypes{std::move(expectedColumnTypes)}, context{context} { inputs.push_back(common::Value::createValue(this->config.filePaths[0])); } + EXPLICIT_COPY_DEFAULT_MOVE(ScanTableFuncBindInput); + +private: + ScanTableFuncBindInput(const ScanTableFuncBindInput& other) + : TableFuncBindInput{other}, config{other.config.copy()}, + expectedColumnNames{other.expectedColumnNames}, + expectedColumnTypes{other.expectedColumnTypes}, context{other.context} {} }; } // namespace function diff --git a/src/include/function/table/call_functions.h b/src/include/function/table/call_functions.h index a28ac47037d..fd769698219 100644 --- a/src/include/function/table/call_functions.h +++ b/src/include/function/table/call_functions.h @@ -1,6 +1,6 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/bind_data.h" #include "function/table_functions.h" @@ -36,8 +36,8 @@ struct CallTableFuncBindData : public TableFuncBindData { CallTableFuncBindData(std::vector columnTypes, std::vector returnColumnNames, common::offset_t maxOffset) - : TableFuncBindData{std::move(columnTypes), std::move(returnColumnNames)}, maxOffset{ - maxOffset} {} + : TableFuncBindData{std::move(columnTypes), std::move(returnColumnNames)}, + maxOffset{maxOffset} {} inline std::unique_ptr copy() const override { return std::make_unique(columnTypes, columnNames, maxOffset); @@ -46,31 +46,43 @@ struct CallTableFuncBindData : public TableFuncBindData { struct CallFunction { static std::unique_ptr initSharedState(TableFunctionInitInput& input); - static std::unique_ptr initEmptyLocalState( - TableFunctionInitInput& input, TableFuncSharedState* state, storage::MemoryManager* mm); + static std::unique_ptr initEmptyLocalState(TableFunctionInitInput& input, + TableFuncSharedState* state, storage::MemoryManager* mm); }; struct CurrentSettingFunction : public CallFunction { + static constexpr const char* name = "CURRENT_SETTING"; + static function_set getFunctionSet(); }; struct DBVersionFunction : public CallFunction { + static constexpr const char* name = "DB_VERSION"; + static function_set getFunctionSet(); }; struct ShowTablesFunction : public CallFunction { + static constexpr const char* name = "SHOW_TABLES"; + static function_set getFunctionSet(); }; struct TableInfoFunction : public CallFunction { + static constexpr const char* name = "TABLE_INFO"; + static function_set getFunctionSet(); }; struct ShowConnectionFunction final : public CallFunction { + static constexpr const char* name = "SHOW_CONNECTION"; + static function_set getFunctionSet(); }; struct StorageInfoFunction final : public CallFunction { + static constexpr const char* name = "STORAGE_INFO"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/table/scan_functions.h b/src/include/function/table/scan_functions.h index 253037dbea8..05a61f0de8c 100644 --- a/src/include/function/table/scan_functions.h +++ b/src/include/function/table/scan_functions.h @@ -30,10 +30,11 @@ struct ScanSharedState : public BaseScanSharedState { struct ScanFileSharedState : public ScanSharedState { main::ClientContext* context; + uint64_t totalSize; - ScanFileSharedState( - common::ReaderConfig readerConfig, uint64_t numRows, main::ClientContext* context) - : ScanSharedState{std::move(readerConfig), numRows}, context{context} {} + ScanFileSharedState(common::ReaderConfig readerConfig, uint64_t numRows, + main::ClientContext* context) + : ScanSharedState{std::move(readerConfig), numRows}, context{context}, totalSize{0} {} }; } // namespace function diff --git a/src/include/function/table/scan_replacement.h b/src/include/function/table/scan_replacement.h new file mode 100644 index 00000000000..075a7731822 --- /dev/null +++ b/src/include/function/table/scan_replacement.h @@ -0,0 +1,23 @@ +#pragma once + +#include "function/table/bind_input.h" +#include "function/table_functions.h" + +namespace kuzu { +namespace function { + +struct ScanReplacementData { + TableFunction func; + TableFuncBindInput bindInput; +}; + +using scan_replace_func_t = std::function(const std::string&)>; + +struct ScanReplacement { + explicit ScanReplacement(scan_replace_func_t replaceFunc) : replaceFunc{replaceFunc} {} + + scan_replace_func_t replaceFunc; +}; + +} // namespace function +} // namespace kuzu diff --git a/src/include/function/table_functions.h b/src/include/function/table_functions.h index 5d0723b72ac..c8a78ef8129 100644 --- a/src/include/function/table_functions.h +++ b/src/include/function/table_functions.h @@ -4,18 +4,9 @@ #include "function.h" namespace kuzu { -namespace catalog { -class Catalog; -} // namespace catalog -namespace common { -class ValueVector; -} namespace main { class ClientContext; } -namespace storage { -class StorageManager; -} namespace function { @@ -64,28 +55,39 @@ struct TableFunctionInitInput { virtual ~TableFunctionInitInput() = default; }; -typedef std::unique_ptr (*table_func_bind_t)( - main::ClientContext* context, TableFuncBindInput* input); -typedef common::offset_t (*table_func_t)(TableFuncInput& input, TableFuncOutput& output); -typedef std::unique_ptr (*table_func_init_shared_t)( - TableFunctionInitInput& input); -typedef std::unique_ptr (*table_func_init_local_t)( - TableFunctionInitInput& input, TableFuncSharedState* state, storage::MemoryManager* mm); -typedef bool (*table_func_can_parallel_t)(); - -struct TableFunction : public Function { +using table_func_bind_t = std::function(main::ClientContext*, + function::TableFuncBindInput*)>; +using table_func_t = std::function; +using table_func_init_shared_t = + std::function(TableFunctionInitInput&)>; +using table_func_init_local_t = std::function( + TableFunctionInitInput&, TableFuncSharedState*, storage::MemoryManager*)>; +using table_func_can_parallel_t = std::function; +using table_func_progress_t = std::function; + +struct TableFunction final : public Function { table_func_t tableFunc; table_func_bind_t bindFunc; table_func_init_shared_t initSharedStateFunc; table_func_init_local_t initLocalStateFunc; table_func_can_parallel_t canParallelFunc = [] { return true; }; + table_func_progress_t progressFunc = [](TableFuncSharedState* /*sharedState*/) { return 0.0; }; + TableFunction() + : Function{}, tableFunc{nullptr}, bindFunc{nullptr}, initSharedStateFunc{nullptr}, + initLocalStateFunc{nullptr} {}; TableFunction(std::string name, table_func_t tableFunc, table_func_bind_t bindFunc, table_func_init_shared_t initSharedFunc, table_func_init_local_t initLocalFunc, std::vector inputTypes) : Function{FunctionType::TABLE, std::move(name), std::move(inputTypes)}, tableFunc{tableFunc}, bindFunc{bindFunc}, initSharedStateFunc{initSharedFunc}, initLocalStateFunc{initLocalFunc} {} + TableFunction(std::string name, table_func_t tableFunc, table_func_bind_t bindFunc, + table_func_init_shared_t initSharedFunc, table_func_init_local_t initLocalFunc, + table_func_progress_t progressFunc, std::vector inputTypes) + : Function{FunctionType::TABLE, std::move(name), std::move(inputTypes)}, + tableFunc{tableFunc}, bindFunc{bindFunc}, initSharedStateFunc{initSharedFunc}, + initLocalStateFunc{initLocalFunc}, progressFunc{progressFunc} {} inline std::string signatureToString() const override { return common::LogicalTypeUtils::toString(parameterTypeIDs); diff --git a/src/include/function/ternary_function_executor.h b/src/include/function/ternary_function_executor.h index a3ad99297b5..1d0ae1c9e63 100644 --- a/src/include/function/ternary_function_executor.h +++ b/src/include/function/ternary_function_executor.h @@ -60,8 +60,8 @@ struct TernaryFunctionExecutor { auto resPos = result.state->selVector->selectedPositions[0]; result.setNull(resPos, a.isNull(aPos) || b.isNull(bPos) || c.isNull(cPos)); if (!result.isNull(resPos)) { - executeOnValue( - a, b, c, result, aPos, bPos, cPos, resPos, dataPtr); + executeOnValue(a, b, c, result, + aPos, bPos, cPos, resPos, dataPtr); } } @@ -76,14 +76,14 @@ struct TernaryFunctionExecutor { } else if (c.hasNoNullsGuarantee()) { if (c.state->selVector->isUnfiltered()) { for (auto i = 0u; i < c.state->selVector->selectedSize; ++i) { - executeOnValue( - a, b, c, result, aPos, bPos, i, i, dataPtr); + executeOnValue(a, b, c, + result, aPos, bPos, i, i, dataPtr); } } else { for (auto i = 0u; i < c.state->selVector->selectedSize; ++i) { auto pos = c.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, aPos, bPos, pos, pos, dataPtr); + executeOnValue(a, b, c, + result, aPos, bPos, pos, pos, dataPtr); } } } else { @@ -91,8 +91,8 @@ struct TernaryFunctionExecutor { for (auto i = 0u; i < c.state->selVector->selectedSize; ++i) { result.setNull(i, c.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, aPos, bPos, i, i, dataPtr); + executeOnValue(a, b, + c, result, aPos, bPos, i, i, dataPtr); } } } else { @@ -100,8 +100,8 @@ struct TernaryFunctionExecutor { auto pos = c.state->selVector->selectedPositions[i]; result.setNull(pos, c.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, aPos, bPos, pos, pos, dataPtr); + executeOnValue(a, b, + c, result, aPos, bPos, pos, pos, dataPtr); } } } @@ -119,14 +119,14 @@ struct TernaryFunctionExecutor { } else if (b.hasNoNullsGuarantee() && c.hasNoNullsGuarantee()) { if (b.state->selVector->isUnfiltered()) { for (auto i = 0u; i < b.state->selVector->selectedSize; ++i) { - executeOnValue( - a, b, c, result, aPos, i, i, i, dataPtr); + executeOnValue(a, b, c, + result, aPos, i, i, i, dataPtr); } } else { for (auto i = 0u; i < b.state->selVector->selectedSize; ++i) { auto pos = b.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, aPos, pos, pos, pos, dataPtr); + executeOnValue(a, b, c, + result, aPos, pos, pos, pos, dataPtr); } } } else { @@ -134,8 +134,8 @@ struct TernaryFunctionExecutor { for (auto i = 0u; i < b.state->selVector->selectedSize; ++i) { result.setNull(i, b.isNull(i) || c.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, aPos, i, i, i, dataPtr); + executeOnValue(a, b, + c, result, aPos, i, i, i, dataPtr); } } } else { @@ -143,8 +143,8 @@ struct TernaryFunctionExecutor { auto pos = b.state->selVector->selectedPositions[i]; result.setNull(pos, b.isNull(pos) || c.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, aPos, pos, pos, pos, dataPtr); + executeOnValue(a, b, + c, result, aPos, pos, pos, pos, dataPtr); } } } @@ -162,14 +162,14 @@ struct TernaryFunctionExecutor { } else if (b.hasNoNullsGuarantee()) { if (b.state->selVector->isUnfiltered()) { for (auto i = 0u; i < b.state->selVector->selectedSize; ++i) { - executeOnValue( - a, b, c, result, aPos, i, cPos, i, dataPtr); + executeOnValue(a, b, c, + result, aPos, i, cPos, i, dataPtr); } } else { for (auto i = 0u; i < b.state->selVector->selectedSize; ++i) { auto pos = b.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, aPos, pos, cPos, pos, dataPtr); + executeOnValue(a, b, c, + result, aPos, pos, cPos, pos, dataPtr); } } } else { @@ -177,8 +177,8 @@ struct TernaryFunctionExecutor { for (auto i = 0u; i < b.state->selVector->selectedSize; ++i) { result.setNull(i, b.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, aPos, i, cPos, i, dataPtr); + executeOnValue(a, b, + c, result, aPos, i, cPos, i, dataPtr); } } } else { @@ -186,8 +186,8 @@ struct TernaryFunctionExecutor { auto pos = b.state->selVector->selectedPositions[i]; result.setNull(pos, b.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, aPos, pos, cPos, pos, dataPtr); + executeOnValue(a, b, + c, result, aPos, pos, cPos, pos, dataPtr); } } } @@ -202,14 +202,14 @@ struct TernaryFunctionExecutor { if (a.hasNoNullsGuarantee() && b.hasNoNullsGuarantee() && c.hasNoNullsGuarantee()) { if (a.state->selVector->isUnfiltered()) { for (uint64_t i = 0; i < a.state->selVector->selectedSize; i++) { - executeOnValue( - a, b, c, result, i, i, i, i, dataPtr); + executeOnValue(a, b, c, + result, i, i, i, i, dataPtr); } } else { for (uint64_t i = 0; i < a.state->selVector->selectedSize; i++) { auto pos = a.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, pos, pos, pos, pos, dataPtr); + executeOnValue(a, b, c, + result, pos, pos, pos, pos, dataPtr); } } } else { @@ -217,8 +217,8 @@ struct TernaryFunctionExecutor { for (uint64_t i = 0; i < a.state->selVector->selectedSize; i++) { result.setNull(i, a.isNull(i) || b.isNull(i) || c.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, i, i, i, i, dataPtr); + executeOnValue(a, b, + c, result, i, i, i, i, dataPtr); } } } else { @@ -226,8 +226,8 @@ struct TernaryFunctionExecutor { auto pos = a.state->selVector->selectedPositions[i]; result.setNull(pos, a.isNull(pos) || b.isNull(pos) || c.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, pos, pos, pos, pos, dataPtr); + executeOnValue(a, b, + c, result, pos, pos, pos, pos, dataPtr); } } } @@ -245,14 +245,14 @@ struct TernaryFunctionExecutor { } else if (a.hasNoNullsGuarantee()) { if (a.state->selVector->isUnfiltered()) { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { - executeOnValue( - a, b, c, result, i, bPos, cPos, i, dataPtr); + executeOnValue(a, b, c, + result, i, bPos, cPos, i, dataPtr); } } else { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { auto pos = a.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, pos, bPos, cPos, pos, dataPtr); + executeOnValue(a, b, c, + result, pos, bPos, cPos, pos, dataPtr); } } } else { @@ -260,8 +260,8 @@ struct TernaryFunctionExecutor { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { result.setNull(i, a.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, i, bPos, cPos, i, dataPtr); + executeOnValue(a, b, + c, result, i, bPos, cPos, i, dataPtr); } } } else { @@ -269,8 +269,8 @@ struct TernaryFunctionExecutor { auto pos = a.state->selVector->selectedPositions[i]; result.setNull(pos, a.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, pos, bPos, cPos, pos, dataPtr); + executeOnValue(a, b, + c, result, pos, bPos, cPos, pos, dataPtr); } } } @@ -288,14 +288,14 @@ struct TernaryFunctionExecutor { } else if (a.hasNoNullsGuarantee() && c.hasNoNullsGuarantee()) { if (a.state->selVector->isUnfiltered()) { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { - executeOnValue( - a, b, c, result, i, bPos, i, i, dataPtr); + executeOnValue(a, b, c, + result, i, bPos, i, i, dataPtr); } } else { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { auto pos = a.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, pos, bPos, pos, pos, dataPtr); + executeOnValue(a, b, c, + result, pos, bPos, pos, pos, dataPtr); } } } else { @@ -303,8 +303,8 @@ struct TernaryFunctionExecutor { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { result.setNull(i, a.isNull(i) || c.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, i, bPos, i, i, dataPtr); + executeOnValue(a, b, + c, result, i, bPos, i, i, dataPtr); } } } else { @@ -312,8 +312,8 @@ struct TernaryFunctionExecutor { auto pos = b.state->selVector->selectedPositions[i]; result.setNull(pos, a.isNull(pos) || c.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, pos, bPos, pos, pos, dataPtr); + executeOnValue(a, b, + c, result, pos, bPos, pos, pos, dataPtr); } } } @@ -331,14 +331,14 @@ struct TernaryFunctionExecutor { } else if (a.hasNoNullsGuarantee() && b.hasNoNullsGuarantee()) { if (a.state->selVector->isUnfiltered()) { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { - executeOnValue( - a, b, c, result, i, i, cPos, i, dataPtr); + executeOnValue(a, b, c, + result, i, i, cPos, i, dataPtr); } } else { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { auto pos = a.state->selVector->selectedPositions[i]; - executeOnValue( - a, b, c, result, pos, pos, cPos, pos, dataPtr); + executeOnValue(a, b, c, + result, pos, pos, cPos, pos, dataPtr); } } } else { @@ -346,8 +346,8 @@ struct TernaryFunctionExecutor { for (auto i = 0u; i < a.state->selVector->selectedSize; ++i) { result.setNull(i, a.isNull(i) || b.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - a, b, c, result, i, i, cPos, i, dataPtr); + executeOnValue(a, b, + c, result, i, i, cPos, i, dataPtr); } } } else { @@ -355,8 +355,8 @@ struct TernaryFunctionExecutor { auto pos = a.state->selVector->selectedPositions[i]; result.setNull(pos, a.isNull(pos) || b.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - a, b, c, result, pos, pos, cPos, pos, dataPtr); + executeOnValue(a, b, + c, result, pos, pos, cPos, pos, dataPtr); } } } @@ -369,29 +369,29 @@ struct TernaryFunctionExecutor { common::ValueVector& c, common::ValueVector& result, void* dataPtr) { result.resetAuxiliaryBuffer(); if (a.state->isFlat() && b.state->isFlat() && c.state->isFlat()) { - executeAllFlat( - a, b, c, result, dataPtr); + executeAllFlat(a, b, c, result, + dataPtr); } else if (a.state->isFlat() && b.state->isFlat() && !c.state->isFlat()) { - executeFlatFlatUnflat( - a, b, c, result, dataPtr); + executeFlatFlatUnflat(a, b, c, + result, dataPtr); } else if (a.state->isFlat() && !b.state->isFlat() && !c.state->isFlat()) { - executeFlatUnflatUnflat( - a, b, c, result, dataPtr); + executeFlatUnflatUnflat(a, b, c, + result, dataPtr); } else if (a.state->isFlat() && !b.state->isFlat() && c.state->isFlat()) { - executeFlatUnflatFlat( - a, b, c, result, dataPtr); + executeFlatUnflatFlat(a, b, c, + result, dataPtr); } else if (!a.state->isFlat() && !b.state->isFlat() && !c.state->isFlat()) { - executeAllUnFlat( - a, b, c, result, dataPtr); + executeAllUnFlat(a, b, c, result, + dataPtr); } else if (!a.state->isFlat() && !b.state->isFlat() && c.state->isFlat()) { - executeUnflatUnFlatFlat( - a, b, c, result, dataPtr); + executeUnflatUnFlatFlat(a, b, c, + result, dataPtr); } else if (!a.state->isFlat() && b.state->isFlat() && c.state->isFlat()) { - executeUnflatFlatFlat( - a, b, c, result, dataPtr); + executeUnflatFlatFlat(a, b, c, + result, dataPtr); } else if (!a.state->isFlat() && b.state->isFlat() && !c.state->isFlat()) { - executeUnflatFlatUnflat( - a, b, c, result, dataPtr); + executeUnflatFlatUnflat(a, b, c, + result, dataPtr); } else { KU_ASSERT(false); } @@ -400,29 +400,29 @@ struct TernaryFunctionExecutor { template static void execute(common::ValueVector& a, common::ValueVector& b, common::ValueVector& c, common::ValueVector& result) { - executeSwitch( - a, b, c, result, nullptr /* dataPtr */); + executeSwitch(a, b, c, + result, nullptr /* dataPtr */); } template static void executeString(common::ValueVector& a, common::ValueVector& b, common::ValueVector& c, common::ValueVector& result) { - executeSwitch( - a, b, c, result, nullptr /* dataPtr */); + executeSwitch(a, b, + c, result, nullptr /* dataPtr */); } template static void executeListStruct(common::ValueVector& a, common::ValueVector& b, common::ValueVector& c, common::ValueVector& result) { - executeSwitch( - a, b, c, result, nullptr /* dataPtr */); + executeSwitch(a, b, + c, result, nullptr /* dataPtr */); } template static void executeUDF(common::ValueVector& a, common::ValueVector& b, common::ValueVector& c, common::ValueVector& result, void* dataPtr) { - executeSwitch( - a, b, c, result, dataPtr); + executeSwitch(a, b, c, + result, dataPtr); } }; diff --git a/src/include/function/timestamp/vector_timestamp_functions.h b/src/include/function/timestamp/vector_timestamp_functions.h index 9efd4ba90a3..40732003084 100644 --- a/src/include/function/timestamp/vector_timestamp_functions.h +++ b/src/include/function/timestamp/vector_timestamp_functions.h @@ -1,19 +1,25 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct CenturyFunction { + static constexpr const char* name = "CENTURY"; + static function_set getFunctionSet(); }; struct EpochMsFunction { + static constexpr const char* name = "EPOCH_MS"; + static function_set getFunctionSet(); }; struct ToTimestampFunction { + static constexpr const char* name = "TO_TIMESTAMP"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/udf_function.h b/src/include/function/udf_function.h index 72d4bcd6b2a..f1762582ad3 100644 --- a/src/include/function/udf_function.h +++ b/src/include/function/udf_function.h @@ -20,8 +20,8 @@ struct UnaryUDFExecutor { struct BinaryUDFExecutor { template - static inline void operation( - LEFT_TYPE& left, RIGHT_TYPE& right, RESULT_TYPE& result, void* udfFunc) { + static inline void operation(LEFT_TYPE& left, RIGHT_TYPE& right, RESULT_TYPE& result, + void* udfFunc) { typedef RESULT_TYPE (*binary_udf_func)(LEFT_TYPE, RIGHT_TYPE); auto binaryUDFFunc = (binary_udf_func)udfFunc; result = binaryUDFFunc(left, right); @@ -30,8 +30,8 @@ struct BinaryUDFExecutor { struct TernaryUDFExecutor { template - static inline void operation( - A_TYPE& a, B_TYPE& b, C_TYPE& c, RESULT_TYPE& result, void* udfFunc) { + static inline void operation(A_TYPE& a, B_TYPE& b, C_TYPE& c, RESULT_TYPE& result, + void* udfFunc) { typedef RESULT_TYPE (*ternary_udf_func)(A_TYPE, B_TYPE, C_TYPE); auto ternaryUDFFunc = (ternary_udf_func)udfFunc; result = ternaryUDFFunc(a, b, c); @@ -80,13 +80,13 @@ struct UDF { } template - static function::scalar_exec_func createUnaryExecFunc(RESULT_TYPE (*/*udfFunc*/)(Args...), + static function::scalar_func_exec_t createUnaryExecFunc(RESULT_TYPE (* /*udfFunc*/)(Args...), const std::vector& /*parameterTypes*/) { KU_UNREACHABLE; } template - static function::scalar_exec_func createUnaryExecFunc(RESULT_TYPE (*udfFunc)(OPERAND_TYPE), + static function::scalar_func_exec_t createUnaryExecFunc(RESULT_TYPE (*udfFunc)(OPERAND_TYPE), const std::vector& parameterTypes) { if (parameterTypes.size() != 1) { throw common::CatalogException{ @@ -94,7 +94,7 @@ struct UDF { std::to_string(parameterTypes.size()) + "."}; } validateType(parameterTypes[0]); - function::scalar_exec_func execFunc = + function::scalar_func_exec_t execFunc = [=](const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) -> void { KU_ASSERT(params.size() == 1); @@ -105,13 +105,13 @@ struct UDF { } template - static function::scalar_exec_func createBinaryExecFunc(RESULT_TYPE (*/*udfFunc*/)(Args...), + static function::scalar_func_exec_t createBinaryExecFunc(RESULT_TYPE (* /*udfFunc*/)(Args...), const std::vector& /*parameterTypes*/) { KU_UNREACHABLE; } template - static function::scalar_exec_func createBinaryExecFunc( + static function::scalar_func_exec_t createBinaryExecFunc( RESULT_TYPE (*udfFunc)(LEFT_TYPE, RIGHT_TYPE), const std::vector& parameterTypes) { if (parameterTypes.size() != 2) { @@ -121,7 +121,7 @@ struct UDF { } validateType(parameterTypes[0]); validateType(parameterTypes[1]); - function::scalar_exec_func execFunc = + function::scalar_func_exec_t execFunc = [=](const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) -> void { KU_ASSERT(params.size() == 2); @@ -132,13 +132,13 @@ struct UDF { } template - static function::scalar_exec_func createTernaryExecFunc(RESULT_TYPE (*/*udfFunc*/)(Args...), + static function::scalar_func_exec_t createTernaryExecFunc(RESULT_TYPE (* /*udfFunc*/)(Args...), const std::vector& /*parameterTypes*/) { KU_UNREACHABLE; } template - static function::scalar_exec_func createTernaryExecFunc( + static function::scalar_func_exec_t createTernaryExecFunc( RESULT_TYPE (*udfFunc)(A_TYPE, B_TYPE, C_TYPE), std::vector parameterTypes) { if (parameterTypes.size() != 3) { @@ -149,7 +149,7 @@ struct UDF { validateType(parameterTypes[0]); validateType(parameterTypes[1]); validateType(parameterTypes[2]); - function::scalar_exec_func execFunc = + function::scalar_func_exec_t execFunc = [=](const std::vector>& params, common::ValueVector& result, void* /*dataPtr*/ = nullptr) -> void { KU_ASSERT(params.size() == 3); @@ -160,8 +160,8 @@ struct UDF { } template - static scalar_exec_func getScalarExecFunc( - TR (*udfFunc)(Args...), std::vector parameterTypes) { + static scalar_func_exec_t getScalarExecFunc(TR (*udfFunc)(Args...), + std::vector parameterTypes) { constexpr auto numArgs = sizeof...(Args); switch (numArgs) { case 1: @@ -222,31 +222,31 @@ struct UDF { KU_UNREACHABLE; } validateType(returnType); - scalar_exec_func scalarExecFunc = getScalarExecFunc(udfFunc, parameterTypes); - definitions.push_back(std::make_unique( - std::move(name), std::move(parameterTypes), returnType, std::move(scalarExecFunc))); + scalar_func_exec_t scalarExecFunc = getScalarExecFunc(udfFunc, parameterTypes); + definitions.push_back(std::make_unique(std::move(name), + std::move(parameterTypes), returnType, std::move(scalarExecFunc))); return definitions; } template static function_set getFunction(std::string name, TR (*udfFunc)(Args...)) { - return getFunction( - std::move(name), udfFunc, getParameterTypes(), getParameterType()); + return getFunction(std::move(name), udfFunc, getParameterTypes(), + getParameterType()); } template - static function_set getVectorizedFunction(std::string name, scalar_exec_func execFunc) { + static function_set getVectorizedFunction(std::string name, scalar_func_exec_t execFunc) { function_set definitions; definitions.push_back(std::make_unique(std::move(name), getParameterTypes(), getParameterType(), std::move(execFunc))); return definitions; } - static function_set getVectorizedFunction(std::string name, scalar_exec_func execFunc, + static function_set getVectorizedFunction(std::string name, scalar_func_exec_t execFunc, std::vector parameterTypes, common::LogicalTypeID returnType) { function_set definitions; - definitions.push_back(std::make_unique( - std::move(name), std::move(parameterTypes), returnType, std::move(execFunc))); + definitions.push_back(std::make_unique(std::move(name), + std::move(parameterTypes), returnType, std::move(execFunc))); return definitions; } }; diff --git a/src/include/function/unary_function_executor.h b/src/include/function/unary_function_executor.h index 7ec14a0bfe3..ba1b3230656 100644 --- a/src/include/function/unary_function_executor.h +++ b/src/include/function/unary_function_executor.h @@ -1,7 +1,7 @@ #pragma once #include "common/vector/value_vector.h" -#include "function/function.h" +#include "function/cast/cast_function_bind_data.h" namespace kuzu { namespace function { @@ -41,7 +41,7 @@ struct UnaryCastStringFunctionWrapper { auto resultVector_ = (common::ValueVector*)resultVector; FUNC::operation(inputVector_.getValue(inputPos), resultVector_->getValue(resultPos), resultVector_, inputPos, - &reinterpret_cast(dataPtr)->csvConfig.option); + &reinterpret_cast(dataPtr)->option); } }; @@ -90,35 +90,16 @@ struct UnaryUDFFunctionWrapper { } }; -struct CastFixedListToListFunctionExecutor { - template - static void executeSwitch( - common::ValueVector& operand, common::ValueVector& result, void* dataPtr) { - auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; - auto numValuesPerList = common::FixedListType::getNumValuesInList(&operand.dataType); - - for (auto i = 0u; i < numOfEntries; i++) { - if (!operand.isNull(i)) { - for (auto j = 0u; j < numValuesPerList; j++) { - OP_WRAPPER::template operation( - (void*)(&operand), i * numValuesPerList + j, (void*)(&result), - i * numValuesPerList + j, nullptr); - } - } - } - } -}; - struct CastChildFunctionExecutor { template - static void executeSwitch( - common::ValueVector& operand, common::ValueVector& result, void* dataPtr) { + static void executeSwitch(common::ValueVector& operand, common::ValueVector& result, + void* dataPtr) { auto numOfEntries = reinterpret_cast(dataPtr)->numOfEntries; for (auto i = 0u; i < numOfEntries; i++) { result.setNull(i, operand.isNull(i)); if (!result.isNull(i)) { - OP_WRAPPER::template operation( - (void*)(&operand), i, (void*)(&result), i, dataPtr); + OP_WRAPPER::template operation((void*)(&operand), + i, (void*)(&result), i, dataPtr); } } } @@ -128,34 +109,34 @@ struct UnaryFunctionExecutor { template static void executeOnValue(common::ValueVector& inputVector, uint64_t inputPos, common::ValueVector& resultVector, uint64_t resultPos, void* dataPtr) { - OP_WRAPPER::template operation( - (void*)&inputVector, inputPos, (void*)&resultVector, resultPos, dataPtr); + OP_WRAPPER::template operation((void*)&inputVector, + inputPos, (void*)&resultVector, resultPos, dataPtr); } template - static void executeSwitch( - common::ValueVector& operand, common::ValueVector& result, void* dataPtr) { + static void executeSwitch(common::ValueVector& operand, common::ValueVector& result, + void* dataPtr) { result.resetAuxiliaryBuffer(); if (operand.state->isFlat()) { auto inputPos = operand.state->selVector->selectedPositions[0]; auto resultPos = result.state->selVector->selectedPositions[0]; result.setNull(resultPos, operand.isNull(inputPos)); if (!result.isNull(resultPos)) { - executeOnValue( - operand, inputPos, result, resultPos, dataPtr); + executeOnValue(operand, inputPos, + result, resultPos, dataPtr); } } else { if (operand.hasNoNullsGuarantee()) { if (operand.state->selVector->isUnfiltered()) { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { - executeOnValue( - operand, i, result, i, dataPtr); + executeOnValue(operand, i, + result, i, dataPtr); } } else { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { auto pos = operand.state->selVector->selectedPositions[i]; - executeOnValue( - operand, pos, result, pos, dataPtr); + executeOnValue(operand, pos, + result, pos, dataPtr); } } } else { @@ -163,8 +144,8 @@ struct UnaryFunctionExecutor { for (auto i = 0u; i < operand.state->selVector->selectedSize; i++) { result.setNull(i, operand.isNull(i)); if (!result.isNull(i)) { - executeOnValue( - operand, i, result, i, dataPtr); + executeOnValue(operand, i, + result, i, dataPtr); } } } else { @@ -172,8 +153,8 @@ struct UnaryFunctionExecutor { auto pos = operand.state->selVector->selectedPositions[i]; result.setNull(pos, operand.isNull(pos)); if (!result.isNull(pos)) { - executeOnValue( - operand, pos, result, pos, dataPtr); + executeOnValue(operand, + pos, result, pos, dataPtr); } } } @@ -183,15 +164,15 @@ struct UnaryFunctionExecutor { template static void execute(common::ValueVector& operand, common::ValueVector& result) { - executeSwitch( - operand, result, nullptr /* dataPtr */); + executeSwitch(operand, result, + nullptr /* dataPtr */); } template - static void executeUDF( - common::ValueVector& operand, common::ValueVector& result, void* dataPtr) { - executeSwitch( - operand, result, dataPtr); + static void executeUDF(common::ValueVector& operand, common::ValueVector& result, + void* dataPtr) { + executeSwitch(operand, result, + dataPtr); } }; diff --git a/src/include/function/union/vector_union_functions.h b/src/include/function/union/vector_union_functions.h index c9447bd0a72..ac1fb6c7c86 100644 --- a/src/include/function/union/vector_union_functions.h +++ b/src/include/function/union/vector_union_functions.h @@ -1,26 +1,25 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct UnionValueFunction { + static constexpr const char* name = "UNION_VALUE"; + static function_set getFunctionSet(); - static std::unique_ptr bindFunc( - const binder::expression_vector& arguments, Function* function); - static void execFunc(const std::vector>& parameters, - common::ValueVector& result, void* /*dataPtr*/ = nullptr); - static void compileFunc(FunctionBindData* bindData, - const std::vector>& parameters, - std::shared_ptr& result); }; struct UnionTagFunction { + static constexpr const char* name = "UNION_TAG"; + static function_set getFunctionSet(); }; struct UnionExtractFunction { + static constexpr const char* name = "UNION_EXTRACT"; + static function_set getFunctionSet(); }; diff --git a/src/include/function/uuid/vector_uuid_functions.h b/src/include/function/uuid/vector_uuid_functions.h index a587aaa3a4e..5cd7587dfc8 100644 --- a/src/include/function/uuid/vector_uuid_functions.h +++ b/src/include/function/uuid/vector_uuid_functions.h @@ -1,11 +1,13 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" namespace kuzu { namespace function { struct GenRandomUUIDFunction { + static constexpr const char* name = "GEN_RANDOM_UUID"; + static function_set getFunctionSet(); }; diff --git a/src/include/main/attached_database.h b/src/include/main/attached_database.h new file mode 100644 index 00000000000..811536e5aa2 --- /dev/null +++ b/src/include/main/attached_database.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "catalog/catalog_content.h" + +namespace kuzu { +namespace main { + +class AttachedDatabase { +public: + AttachedDatabase(std::string dbName, std::unique_ptr catalogContent) + : dbName{std::move(dbName)}, catalogContent{std::move(catalogContent)} {} + + std::string getDBName() { return dbName; } + + catalog::CatalogContent* getCatalogContent() { return catalogContent.get(); } + +private: + std::string dbName; + std::unique_ptr catalogContent; +}; + +} // namespace main +} // namespace kuzu diff --git a/src/include/main/client_config.h b/src/include/main/client_config.h new file mode 100644 index 00000000000..774ba916a92 --- /dev/null +++ b/src/include/main/client_config.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +namespace kuzu { +namespace main { + +struct ClientConfig { + // System home directory. + std::string homeDirectory; + // File search path. + std::string fileSearchPath; + // If using semi mask in join. + bool enableSemiMask; + // Number of threads for execution. + uint64_t numThreads; + // Timeout (milliseconds) + uint64_t timeoutInMS; + // variable length maximum depth + uint32_t varLengthMaxDepth; + // If using progress bar + bool enableProgressBar; + // time before displaying progress bar + uint64_t showProgressAfter; + // If multi copy is enabled + bool enableMultiCopy; +}; + +struct ClientConfigDefault { + // 0 means timeout is disabled by default. + static constexpr uint64_t TIMEOUT_IN_MS = 0; + static constexpr uint32_t VAR_LENGTH_MAX_DEPTH = 30; + static constexpr bool ENABLE_SEMI_MASK = true; + static constexpr bool ENABLE_PROGRESS_BAR = true; + static constexpr uint64_t SHOW_PROGRESS_AFTER = 1000; + static constexpr bool ENABLE_MULTI_COPY = false; +}; + +} // namespace main +} // namespace kuzu diff --git a/src/include/main/client_context.h b/src/include/main/client_context.h index 032350a949e..7dc6d40a1c6 100644 --- a/src/include/main/client_context.h +++ b/src/include/main/client_context.h @@ -2,13 +2,15 @@ #include #include -#include #include #include +#include "client_config.h" +#include "common/task_system/progress_bar.h" #include "common/timer.h" #include "common/types/value/value.h" -#include "function/scalar_function.h" +#include "function/function.h" +#include "function/table/scan_replacement.h" #include "main/kuzu_fwd.h" #include "parser/statement.h" #include "prepared_statement.h" @@ -26,6 +28,10 @@ namespace common { class RandomEngine; } +namespace extension { +struct ExtensionOptions; +} + namespace main { class Database; @@ -37,8 +43,6 @@ struct ActiveQuery { void reset(); }; -using replace_func_t = std::function(common::Value*)>; - /** * @brief Contain client side configuration. We make profiler associated per query, so profiler is * not maintained in client context. @@ -47,88 +51,83 @@ class ClientContext { friend class Connection; friend class binder::Binder; friend class binder::ExpressionBinder; - friend class testing::TinySnbDDLTest; - friend class testing::TinySnbCopyCSVTransactionTest; - friend struct ThreadsSetting; - friend struct TimeoutSetting; - friend struct VarLengthExtendMaxDepthSetting; - friend struct EnableSemiMaskSetting; - friend struct HomeDirectorySetting; - friend struct FileSearchPathSetting; public: explicit ClientContext(Database* database); - inline void interrupt() { activeQuery.interrupted = true; } - - bool isInterrupted() const { return activeQuery.interrupted; } - - inline bool isTimeOutEnabled() const { return timeoutInMS != 0; } - - inline uint64_t getTimeoutRemainingInMS() { - KU_ASSERT(isTimeOutEnabled()); - auto elapsed = activeQuery.timer.getElapsedTimeInMS(); - return elapsed >= timeoutInMS ? 0 : timeoutInMS - elapsed; - } - - inline bool isEnableSemiMask() const { return enableSemiMask; } - - void startTimingIfEnabled(); - + // Client config + const ClientConfig* getClientConfig() const { return &config; } + ClientConfig* getClientConfigUnsafe() { return &config; } KUZU_API common::Value getCurrentSetting(const std::string& optionName); + // Timer and timeout + void interrupt() { activeQuery.interrupted = true; } + bool interrupted() const { return activeQuery.interrupted; } + bool hasTimeout() const { return config.timeoutInMS != 0; } + void setQueryTimeOut(uint64_t timeoutInMS); + uint64_t getQueryTimeOut() const; + void startTimer(); + uint64_t getTimeoutRemainingInMS() const; + void resetActiveQuery() { activeQuery.reset(); } + + // Parallelism + void setMaxNumThreadForExec(uint64_t numThreads); + uint64_t getMaxNumThreadForExec() const; + // Transaction. transaction::Transaction* getTx() const; KUZU_API transaction::TransactionContext* getTransactionContext() const; - inline bool hasReplaceFunc() { return replaceFunc != nullptr; } - inline void setReplaceFunc(replace_func_t func) { replaceFunc = func; } + // Progress bar + common::ProgressBar* getProgressBar() const; + // Replace function. + void addScanReplace(function::ScanReplacement scanReplacement); + std::unique_ptr tryReplace(const std::string& objectName) const; + // Extension KUZU_API void setExtensionOption(std::string name, common::Value value); - - common::RandomEngine* getRandomEngine() { return randomEngine.get(); } - - common::VirtualFileSystem* getVFSUnsafe() const; - + extension::ExtensionOptions* getExtensionOptions() const; std::string getExtensionDir() const; - KUZU_API Database* getDatabase() const { return database; } - storage::StorageManager* getStorageManager(); - storage::MemoryManager* getMemoryManager(); - catalog::Catalog* getCatalog(); - + // Environment. KUZU_API std::string getEnvVariable(const std::string& name); - std::unique_ptr prepare(std::string_view query); - - void setQueryTimeOut(uint64_t timeoutInMS); - - uint64_t getQueryTimeOut(); - - void setMaxNumThreadForExec(uint64_t numThreads); - - uint64_t getMaxNumThreadForExec(); + // Database component getters. + KUZU_API Database* getDatabase() const { return database; } + storage::StorageManager* getStorageManager() const; + KUZU_API storage::MemoryManager* getMemoryManager(); + catalog::Catalog* getCatalog() const; + common::VirtualFileSystem* getVFSUnsafe() const; + common::RandomEngine* getRandomEngine(); + // Query. + std::unique_ptr prepare(std::string_view query); KUZU_API std::unique_ptr executeWithParams(PreparedStatement* preparedStatement, std::unordered_map> inputParams); - std::unique_ptr query(std::string_view queryStatement); - void runQuery(std::string query); -private: - inline void resetActiveQuery() { activeQuery.reset(); } + // TODO(Jiamin): should remove after supporting ddl in manual tx + std::unique_ptr prepareTest(std::string_view query); + // only use for test framework + std::vector> parseQuery(std::string_view query); - std::unique_ptr query( - std::string_view query, std::string_view encodedJoin, bool enumerateAllPlans = true); +private: + std::unique_ptr query(std::string_view query, std::string_view encodedJoin, + bool enumerateAllPlans = true); std::unique_ptr queryResultWithError(std::string_view errMsg); std::unique_ptr preparedStatementWithError(std::string_view errMsg); - std::vector> parseQuery(std::string_view query); - - std::unique_ptr prepareNoLock(parser::Statement* parsedStatement, - bool enumerateAllPlans = false, std::string_view joinOrder = std::string_view()); + // when we do prepare, we will start a transaction for the query + // when we execute after prepare in a same context, we set requireNewTx to false and will not + // commit the transaction in prepare when we only prepare a query statement, we set requireNewTx + // to true and will commit the transaction in prepare + std::unique_ptr prepareNoLock( + std::shared_ptr parsedStatement, bool enumerateAllPlans = false, + std::string_view joinOrder = std::string_view(), bool requireNewTx = true, + std::optional>> inputParams = + std::nullopt); template std::unique_ptr executeWithParams(PreparedStatement* preparedStatement, @@ -144,7 +143,7 @@ class ClientContext { const std::unordered_map>& inputParams); std::unique_ptr executeAndAutoCommitIfNecessaryNoLock( - PreparedStatement* preparedStatement, uint32_t planIdx = 0u); + PreparedStatement* preparedStatement, uint32_t planIdx = 0u, bool requiredNexTx = true); void addScalarFunction(std::string name, function::function_set definitions); @@ -152,18 +151,22 @@ class ClientContext { void commitUDFTrx(bool isAutoCommitTrx); - uint64_t numThreadsForExecution; + // Client side configurable settings. + ClientConfig config; + // Current query. ActiveQuery activeQuery; - uint64_t timeoutInMS; - uint32_t varLengthExtendMaxDepth; + // Transaction context. std::unique_ptr transactionContext; - bool enableSemiMask; - replace_func_t replaceFunc; + // Replace external object as pointer Value; + std::vector scanReplacements; + // Extension configurable settings. std::unordered_map extensionOptionValues; + // Random generator for UUID. std::unique_ptr randomEngine; - std::string homeDirectory; - std::string fileSearchPath; + // Attached database. Database* database; + // Progress bar for queries + std::unique_ptr progressBar; std::mutex mtx; }; diff --git a/src/include/main/connection.h b/src/include/main/connection.h index 38c3c601154..af059781d7f 100644 --- a/src/include/main/connection.h +++ b/src/include/main/connection.h @@ -40,6 +40,10 @@ class Connection { */ KUZU_API uint64_t getMaxNumThreadForExec(); + void setProgressBarPrinting(bool enable) { + clientContext->progressBar->toggleProgressBarPrinting(enable); + } + /** * @brief Executes the given query and returns the result. * @param query The query to execute. @@ -60,8 +64,8 @@ class Connection { * @return the result of the query. */ template - inline std::unique_ptr execute( - PreparedStatement* preparedStatement, std::pair... args) { + inline std::unique_ptr execute(PreparedStatement* preparedStatement, + std::pair... args) { std::unordered_map> inputParameters; return executeWithParams(preparedStatement, std::move(inputParameters), args...); } @@ -95,8 +99,8 @@ class Connection { void createScalarFunction(std::string name, TR (*udfFunc)(Args...)) { auto autoTrx = startUDFAutoTrx(clientContext->getTransactionContext()); auto nameCopy = std::string(name); - addScalarFunction( - std::move(nameCopy), function::UDF::getFunction(std::move(name), udfFunc)); + addScalarFunction(std::move(nameCopy), + function::UDF::getFunction(std::move(name), udfFunc)); commitUDFTrx(autoTrx); } @@ -105,14 +109,14 @@ class Connection { common::LogicalTypeID returnType, TR (*udfFunc)(Args...)) { auto autoTrx = startUDFAutoTrx(clientContext->getTransactionContext()); auto nameCopy = std::string(name); - addScalarFunction( - std::move(nameCopy), function::UDF::getFunction(std::move(name), udfFunc, - std::move(parameterTypes), returnType)); + addScalarFunction(std::move(nameCopy), + function::UDF::getFunction(std::move(name), udfFunc, + std::move(parameterTypes), returnType)); commitUDFTrx(autoTrx); } template - void createVectorizedFunction(std::string name, function::scalar_exec_func scalarFunc) { + void createVectorizedFunction(std::string name, function::scalar_func_exec_t scalarFunc) { auto autoTrx = startUDFAutoTrx(clientContext->getTransactionContext()); auto nameCopy = std::string(name); addScalarFunction(std::move(nameCopy), function::UDF::getVectorizedFunction( @@ -122,33 +126,28 @@ class Connection { void createVectorizedFunction(std::string name, std::vector parameterTypes, common::LogicalTypeID returnType, - function::scalar_exec_func scalarFunc) { + function::scalar_func_exec_t scalarFunc) { auto autoTrx = startUDFAutoTrx(clientContext->getTransactionContext()); auto nameCopy = std::string(name); - addScalarFunction( - std::move(nameCopy), function::UDF::getVectorizedFunction(std::move(name), - std::move(scalarFunc), std::move(parameterTypes), returnType)); + addScalarFunction(std::move(nameCopy), + function::UDF::getVectorizedFunction(std::move(name), std::move(scalarFunc), + std::move(parameterTypes), returnType)); commitUDFTrx(autoTrx); } - inline void setReplaceFunc(replace_func_t replaceFunc) { - clientContext->setReplaceFunc(std::move(replaceFunc)); - } - - inline ClientContext* getClientContext() { return clientContext.get(); }; + ClientContext* getClientContext() { return clientContext.get(); }; private: - std::unique_ptr query( - std::string_view query, std::string_view encodedJoin, bool enumerateAllPlans = true); + std::unique_ptr query(std::string_view query, std::string_view encodedJoin, + bool enumerateAllPlans = true); std::unique_ptr queryResultWithError(std::string_view errMsg); std::unique_ptr preparedStatementWithError(std::string_view errMsg); - std::vector> parseQuery(std::string_view query); - - std::unique_ptr prepareNoLock(parser::Statement* parsedStatement, - bool enumerateAllPlans = false, std::string_view joinOrder = std::string_view()); + std::unique_ptr prepareNoLock( + std::shared_ptr parsedStatement, bool enumerateAllPlans = false, + std::string_view joinOrder = std::string_view()); template std::unique_ptr executeWithParams(PreparedStatement* preparedStatement, diff --git a/src/include/main/database.h b/src/include/main/database.h index 455b0a09700..2af50812ce6 100644 --- a/src/include/main/database.h +++ b/src/include/main/database.h @@ -5,6 +5,7 @@ #include #include "common/api.h" +#include "common/case_insensitive_map.h" #include "kuzu_fwd.h" namespace kuzu { @@ -13,6 +14,10 @@ class FileSystem; enum class LogicalTypeID : uint8_t; } // namespace common +namespace catalog { +class CatalogEntry; +} // namespace catalog + namespace function { struct Function; } // namespace function @@ -22,8 +27,13 @@ struct ExtensionUtils; struct ExtensionOptions; } // namespace extension +namespace storage { +class StorageExtension; +} // namespace storage + namespace main { struct ExtensionOption; +class DatabaseManager; /** * @brief Stores runtime configuration for creating or opening a Database @@ -75,8 +85,8 @@ class Database { * @param databasePath Database path. * @param systemConfig System configurations (buffer pool size and max num threads). */ - KUZU_API explicit Database( - std::string_view databasePath, SystemConfig systemConfig = SystemConfig()); + KUZU_API explicit Database(std::string_view databasePath, + SystemConfig systemConfig = SystemConfig()); /** * @brief Destructs the database object. */ @@ -91,16 +101,24 @@ class Database { // TODO(Ziyi): Instead of exposing a dedicated API for adding a new function, we should consider // add function through the extension module. - void addBuiltInFunction( - std::string name, std::vector> functionSet); + void addBuiltInFunction(std::string name, + std::vector> functionSet); KUZU_API void registerFileSystem(std::unique_ptr fs); - KUZU_API void addExtensionOption( - std::string name, common::LogicalTypeID type, common::Value defaultValue); + KUZU_API void registerStorageExtension(std::string name, + std::unique_ptr storageExtension); + + KUZU_API void addExtensionOption(std::string name, common::LogicalTypeID type, + common::Value defaultValue); ExtensionOption* getExtensionOption(std::string name); + common::case_insensitive_map_t>& + getStorageExtensions(); + + DatabaseManager* getDatabaseManagerUnsafe() const; + private: void openLockFile(); void initDBDirAndCoreFilesIfNecessary(); @@ -131,6 +149,8 @@ class Database { std::shared_ptr logger; std::unique_ptr lockFile; std::unique_ptr extensionOptions; + std::unique_ptr databaseManager; + common::case_insensitive_map_t> storageExtensions; }; } // namespace main diff --git a/src/include/main/database_manager.h b/src/include/main/database_manager.h new file mode 100644 index 00000000000..35be0a6738b --- /dev/null +++ b/src/include/main/database_manager.h @@ -0,0 +1,19 @@ +#pragma once + +#include "attached_database.h" + +namespace kuzu { +namespace main { + +class DatabaseManager { +public: + void registerAttachedDatabase(std::unique_ptr attachedDatabase); + AttachedDatabase* getAttachedDatabase(const std::string& name); + void detachDatabase(const std::string& databaseName); + +private: + std::vector> attachedDatabases; +}; + +} // namespace main +} // namespace kuzu diff --git a/src/include/main/db_config.h b/src/include/main/db_config.h index 06c64003de9..a660b9adcbe 100644 --- a/src/include/main/db_config.h +++ b/src/include/main/db_config.h @@ -36,10 +36,10 @@ struct ConfigurationOption : public Option { struct ExtensionOption : public Option { common::Value defaultValue; - ExtensionOption( - std::string name, common::LogicalTypeID parameterType, common::Value defaultValue) - : Option{std::move(name), parameterType, OptionType::EXTENSION}, defaultValue{std::move( - defaultValue)} {} + ExtensionOption(std::string name, common::LogicalTypeID parameterType, + common::Value defaultValue) + : Option{std::move(name), parameterType, OptionType::EXTENSION}, + defaultValue{std::move(defaultValue)} {} }; class DBConfig { diff --git a/src/include/main/plan_printer.h b/src/include/main/plan_printer.h index c4eb119009c..292d248b625 100644 --- a/src/include/main/plan_printer.h +++ b/src/include/main/plan_printer.h @@ -13,8 +13,8 @@ namespace main { class OpProfileBox { public: - OpProfileBox( - std::string opName, const std::string& paramsName, std::vector attributes); + OpProfileBox(std::string opName, const std::string& paramsName, + std::vector attributes); inline std::string getOpName() const { return opName; } @@ -41,8 +41,8 @@ class OpProfileTree { std::ostringstream printPlanToOstream() const; private: - static void calculateNumRowsAndColsForOp( - processor::PhysicalOperator* op, uint32_t& numRows, uint32_t& numCols); + static void calculateNumRowsAndColsForOp(processor::PhysicalOperator* op, uint32_t& numRows, + uint32_t& numCols); uint32_t fillOpProfileBoxes(processor::PhysicalOperator* op, uint32_t rowIdx, uint32_t colIdx, uint32_t& maxFieldWidth, common::Profiler& profiler); @@ -64,8 +64,8 @@ class OpProfileTree { (void)colIdx; } - void insertOpProfileBox( - uint32_t rowIdx, uint32_t colIdx, std::unique_ptr opProfileBox); + void insertOpProfileBox(uint32_t rowIdx, uint32_t colIdx, + std::unique_ptr opProfileBox); OpProfileBox* getOpProfileBox(uint32_t rowIdx, uint32_t colIdx) const; @@ -102,8 +102,8 @@ class PlanPrinter { static inline std::string getOperatorParams(processor::PhysicalOperator* physicalOperator); private: - nlohmann::json toJson( - processor::PhysicalOperator* physicalOperator, common::Profiler& profiler); + nlohmann::json toJson(processor::PhysicalOperator* physicalOperator, + common::Profiler& profiler); private: processor::PhysicalPlan* physicalPlan; diff --git a/src/include/main/prepared_statement.h b/src/include/main/prepared_statement.h index 22d4c9f952e..20ad0974b39 100644 --- a/src/include/main/prepared_statement.h +++ b/src/include/main/prepared_statement.h @@ -7,6 +7,7 @@ #include "common/api.h" #include "kuzu_fwd.h" +#include "parser/statement.h" #include "query_summary.h" namespace kuzu { @@ -62,6 +63,7 @@ class PreparedStatement { std::unordered_map> parameterMap; std::unique_ptr statementResult; std::vector> logicalPlans; + std::shared_ptr parsedStatement; }; } // namespace main diff --git a/src/include/main/query_result.h b/src/include/main/query_result.h index e52d957861f..afd5bebf08c 100644 --- a/src/include/main/query_result.h +++ b/src/include/main/query_result.h @@ -15,16 +15,16 @@ namespace main { struct DataTypeInfo { public: DataTypeInfo(common::LogicalTypeID typeID, std::string name) - : typeID{typeID}, name{std::move(name)}, numValuesPerList{0} {} + : typeID{typeID}, name{std::move(name)}, fixedNumValues{0} {} common::LogicalTypeID typeID; std::string name; std::vector> childrenTypesInfo; - // Used by fixedList only. - uint64_t numValuesPerList; + // Used by array only. + uint64_t fixedNumValues; - static std::unique_ptr getInfoForDataType( - const common::LogicalType& type, const std::string& name); + static std::unique_ptr getInfoForDataType(const common::LogicalType& type, + const std::string& name); }; /** @@ -38,6 +38,8 @@ class QueryResult { QueryResult* currentResult; public: + QueryResultIterator() = default; + explicit QueryResultIterator(QueryResult* startResult) : currentResult(startResult) {} void operator++() { @@ -46,9 +48,9 @@ class QueryResult { } } - bool isEnd() { return currentResult == nullptr; } + bool isEnd() const { return currentResult == nullptr; } - QueryResult* getCurrentResult() { return currentResult; } + QueryResult* getCurrentResult() const { return currentResult; } }; public: @@ -97,15 +99,22 @@ class QueryResult { * @return whether there are more tuples to read. */ KUZU_API bool hasNext() const; - std::unique_ptr nextQueryResult; + /** + * @return whether there are more query results to read. + */ + KUZU_API bool hasNextQueryResult() const; + /** + * @return get next query result to read (for multiple query statements). + */ + KUZU_API QueryResult* getNextQueryResult(); - std::string toSingleQueryString(); + std::unique_ptr nextQueryResult; /** * @return next flat tuple in the query result. */ KUZU_API std::shared_ptr getNext(); /** - * @return string of query result. + * @return string of first query result. */ KUZU_API std::string toString(); @@ -158,6 +167,9 @@ class QueryResult { // execution statistics std::unique_ptr querySummary; + + // query iterator + QueryResultIterator queryResultIterator; }; } // namespace main diff --git a/src/include/main/settings.h b/src/include/main/settings.h index 3e3b6a0a32c..41f25c83bf9 100644 --- a/src/include/main/settings.h +++ b/src/include/main/settings.h @@ -11,10 +11,10 @@ struct ThreadsSetting { static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::INT64; static void setContext(ClientContext* context, const common::Value& parameter) { KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::INT64); - context->numThreadsForExecution = parameter.getValue(); + context->getClientConfigUnsafe()->numThreads = parameter.getValue(); } static common::Value getSetting(ClientContext* context) { - return common::Value(context->numThreadsForExecution); + return common::Value(context->getClientConfig()->numThreads); } }; @@ -23,11 +23,36 @@ struct TimeoutSetting { static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::INT64; static void setContext(ClientContext* context, const common::Value& parameter) { KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::INT64); - context->timeoutInMS = parameter.getValue(); - context->startTimingIfEnabled(); + context->getClientConfigUnsafe()->timeoutInMS = parameter.getValue(); } static common::Value getSetting(ClientContext* context) { - return common::Value(context->timeoutInMS); + return common::Value(context->getClientConfig()->timeoutInMS); + } +}; + +struct ProgressBarSetting { + static constexpr const char* name = "progress_bar"; + static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::BOOL; + static void setContext(ClientContext* context, const common::Value& parameter) { + KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::BOOL); + context->getClientConfigUnsafe()->enableProgressBar = parameter.getValue(); + context->getProgressBar()->toggleProgressBarPrinting(parameter.getValue()); + } + static common::Value getSetting(ClientContext* context) { + return common::Value(context->getClientConfig()->enableProgressBar); + } +}; + +struct ProgressBarTimerSetting { + static constexpr const char* name = "progress_bar_time"; + static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::INT64; + static void setContext(ClientContext* context, const common::Value& parameter) { + KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::INT64); + context->getClientConfigUnsafe()->showProgressAfter = parameter.getValue(); + context->getProgressBar()->setShowProgressAfter(parameter.getValue()); + } + static common::Value getSetting(ClientContext* context) { + return common::Value(context->getClientConfig()->showProgressAfter); } }; @@ -36,10 +61,10 @@ struct VarLengthExtendMaxDepthSetting { static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::INT64; static void setContext(ClientContext* context, const common::Value& parameter) { KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::INT64); - context->varLengthExtendMaxDepth = parameter.getValue(); + context->getClientConfigUnsafe()->varLengthMaxDepth = parameter.getValue(); } static common::Value getSetting(ClientContext* context) { - return common::Value(context->varLengthExtendMaxDepth); + return common::Value(context->getClientConfig()->varLengthMaxDepth); } }; @@ -48,10 +73,10 @@ struct EnableSemiMaskSetting { static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::BOOL; static void setContext(ClientContext* context, const common::Value& parameter) { KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::BOOL); - context->enableSemiMask = parameter.getValue(); + context->getClientConfigUnsafe()->enableSemiMask = parameter.getValue(); } static common::Value getSetting(ClientContext* context) { - return common::Value(context->enableSemiMask); + return common::Value(context->getClientConfig()->enableSemiMask); } }; @@ -60,10 +85,10 @@ struct HomeDirectorySetting { static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::STRING; static void setContext(ClientContext* context, const common::Value& parameter) { KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::STRING); - context->homeDirectory = parameter.getValue(); + context->getClientConfigUnsafe()->homeDirectory = parameter.getValue(); } static common::Value getSetting(ClientContext* context) { - return common::Value::createValue(context->homeDirectory); + return common::Value::createValue(context->getClientConfig()->homeDirectory); } }; @@ -72,10 +97,22 @@ struct FileSearchPathSetting { static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::STRING; static void setContext(ClientContext* context, const common::Value& parameter) { KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::STRING); - context->fileSearchPath = parameter.getValue(); + context->getClientConfigUnsafe()->fileSearchPath = parameter.getValue(); + } + static common::Value getSetting(ClientContext* context) { + return common::Value::createValue(context->getClientConfig()->fileSearchPath); + } +}; + +struct EnableMultiCopySetting { + static constexpr const char* name = "enable_multi_copy"; + static constexpr const common::LogicalTypeID inputType = common::LogicalTypeID::BOOL; + static void setContext(ClientContext* context, const common::Value& parameter) { + KU_ASSERT(parameter.getDataType()->getLogicalTypeID() == common::LogicalTypeID::BOOL); + context->getClientConfigUnsafe()->enableMultiCopy = parameter.getValue(); } static common::Value getSetting(ClientContext* context) { - return common::Value::createValue(context->fileSearchPath); + return common::Value(context->getClientConfig()->enableMultiCopy); } }; diff --git a/src/include/optimizer/factorization_rewriter.h b/src/include/optimizer/factorization_rewriter.h index afdbf05d639..95c978b2ef4 100644 --- a/src/include/optimizer/factorization_rewriter.h +++ b/src/include/optimizer/factorization_rewriter.h @@ -6,7 +6,7 @@ namespace kuzu { namespace optimizer { -class FactorizationRewriter : public LogicalOperatorVisitor { +class FactorizationRewriter final : public LogicalOperatorVisitor { public: void rewrite(planner::LogicalPlan* plan); @@ -19,6 +19,7 @@ class FactorizationRewriter : public LogicalOperatorVisitor { void visitIntersect(planner::LogicalOperator* op) override; void visitProjection(planner::LogicalOperator* op) override; void visitAccumulate(planner::LogicalOperator* op) override; + void visitMarkAccumulate(planner::LogicalOperator*) override; void visitAggregate(planner::LogicalOperator* op) override; void visitOrderBy(planner::LogicalOperator* op) override; void visitLimit(planner::LogicalOperator* op) override; diff --git a/src/include/optimizer/logical_operator_visitor.h b/src/include/optimizer/logical_operator_visitor.h index ed19ca34daa..69c72a5a72d 100644 --- a/src/include/optimizer/logical_operator_visitor.h +++ b/src/include/optimizer/logical_operator_visitor.h @@ -105,6 +105,12 @@ class LogicalOperatorVisitor { return op; } + virtual void visitMarkAccumulate(planner::LogicalOperator* /*op*/) {} + virtual std::shared_ptr visitMarkAccumulateReplace( + std::shared_ptr op) { + return op; + } + virtual void visitDistinct(planner::LogicalOperator* /*op*/) {} virtual std::shared_ptr visitDistinctReplace( std::shared_ptr op) { @@ -170,6 +176,12 @@ class LogicalOperatorVisitor { std::shared_ptr op) { return op; } + + virtual void visitCopyFrom(planner::LogicalOperator* /*op*/) {} + virtual std::shared_ptr visitCopyFromReplace( + std::shared_ptr op) { + return op; + } }; } // namespace optimizer diff --git a/src/include/optimizer/projection_push_down_optimizer.h b/src/include/optimizer/projection_push_down_optimizer.h index c6f2ddb703d..6f9fceb55aa 100644 --- a/src/include/optimizer/projection_push_down_optimizer.h +++ b/src/include/optimizer/projection_push_down_optimizer.h @@ -38,13 +38,14 @@ class ProjectionPushDownOptimizer : public LogicalOperatorVisitor { void visitDeleteNode(planner::LogicalOperator* op) override; void visitDeleteRel(planner::LogicalOperator* op) override; void visitMerge(planner::LogicalOperator* op) override; + void visitCopyFrom(planner::LogicalOperator* op) override; void collectExpressionsInUse(std::shared_ptr expression); binder::expression_vector pruneExpressions(const binder::expression_vector& expressions); - void preAppendProjection( - planner::LogicalOperator* op, uint32_t childIdx, binder::expression_vector expressions); + void preAppendProjection(planner::LogicalOperator* op, uint32_t childIdx, + binder::expression_vector expressions); private: binder::expression_set propertiesInUse; diff --git a/src/include/parser/antlr_parser/kuzu_cypher_parser.h b/src/include/parser/antlr_parser/kuzu_cypher_parser.h index 8ec369457b6..d3a8cedc185 100644 --- a/src/include/parser/antlr_parser/kuzu_cypher_parser.h +++ b/src/include/parser/antlr_parser/kuzu_cypher_parser.h @@ -16,8 +16,8 @@ class KuzuCypherParser : public CypherParser { void notifyQueryNotConcludeWithReturn(antlr4::Token* startToken) override; - void notifyNodePatternWithoutParentheses( - std::string nodeName, antlr4::Token* startToken) override; + void notifyNodePatternWithoutParentheses(std::string nodeName, + antlr4::Token* startToken) override; void notifyInvalidNotEqualOperator(antlr4::Token* startToken) override; diff --git a/src/include/parser/antlr_parser/parser_error_strategy.h b/src/include/parser/antlr_parser/parser_error_strategy.h index 7b6dc630eaa..0980073b5a3 100644 --- a/src/include/parser/antlr_parser/parser_error_strategy.h +++ b/src/include/parser/antlr_parser/parser_error_strategy.h @@ -8,8 +8,8 @@ namespace parser { class ParserErrorStrategy : public antlr4::DefaultErrorStrategy { protected: - void reportNoViableAlternative( - antlr4::Parser* recognizer, const antlr4::NoViableAltException& e) override; + void reportNoViableAlternative(antlr4::Parser* recognizer, + const antlr4::NoViableAltException& e) override; }; } // namespace parser diff --git a/src/include/parser/attach_database.h b/src/include/parser/attach_database.h new file mode 100644 index 00000000000..975c16dbb60 --- /dev/null +++ b/src/include/parser/attach_database.h @@ -0,0 +1,21 @@ +#pragma once + +#include "parsed_data/attach_info.h" +#include "parser/statement.h" + +namespace kuzu { +namespace parser { + +class AttachDatabase final : public Statement { +public: + explicit AttachDatabase(AttachInfo attachInfo) + : Statement{common::StatementType::ATTACH_DATABASE}, attachInfo{std::move(attachInfo)} {} + + AttachInfo getAttachInfo() const { return attachInfo; } + +private: + AttachInfo attachInfo; +}; + +} // namespace parser +} // namespace kuzu diff --git a/src/include/parser/comment_on.h b/src/include/parser/comment_on.h index 092cff669c6..c64451cd4f5 100644 --- a/src/include/parser/comment_on.h +++ b/src/include/parser/comment_on.h @@ -10,8 +10,8 @@ namespace parser { class CommentOn : public Statement { public: explicit CommentOn(std::string table, std::string comment) - : Statement{common::StatementType::COMMENT_ON}, table{std::move(table)}, comment{std::move( - comment)} {} + : Statement{common::StatementType::COMMENT_ON}, table{std::move(table)}, + comment{std::move(comment)} {} inline std::string getTable() const { return table; } diff --git a/src/include/parser/copy.h b/src/include/parser/copy.h index e481039570c..82c8ff1ac28 100644 --- a/src/include/parser/copy.h +++ b/src/include/parser/copy.h @@ -3,6 +3,7 @@ #include #include "parser/expression/parsed_expression.h" +#include "parser/scan_source.h" #include "parser/statement.h" namespace kuzu { @@ -21,14 +22,14 @@ class Copy : public Statement { class CopyFrom : public Copy { public: - CopyFrom(std::vector filePaths, std::string tableName) - : Copy{common::StatementType::COPY_FROM}, byColumn_{false}, filePaths{std::move(filePaths)}, + CopyFrom(std::unique_ptr source, std::string tableName) + : Copy{common::StatementType::COPY_FROM}, byColumn_{false}, source{std::move(source)}, tableName{std::move(tableName)} {} inline void setByColumn() { byColumn_ = true; } inline bool byColumn() const { return byColumn_; } - inline std::vector getFilePaths() const { return filePaths; } + inline BaseScanSource* getSource() const { return source.get(); } inline std::string getTableName() const { return tableName; } @@ -37,7 +38,7 @@ class CopyFrom : public Copy { private: bool byColumn_; - std::vector filePaths; + std::unique_ptr source; std::string tableName; std::vector columnNames; }; @@ -45,8 +46,8 @@ class CopyFrom : public Copy { class CopyTo : public Copy { public: CopyTo(std::string filePath, std::unique_ptr statement) - : Copy{common::StatementType::COPY_TO}, filePath{std::move(filePath)}, statement{std::move( - statement)} {} + : Copy{common::StatementType::COPY_TO}, filePath{std::move(filePath)}, + statement{std::move(statement)} {} inline std::string getFilePath() const { return filePath; } inline const Statement* getStatement() const { return statement.get(); } diff --git a/src/include/parser/ddl/alter_info.h b/src/include/parser/ddl/alter_info.h index 26d04c81a0d..490747c908b 100644 --- a/src/include/parser/ddl/alter_info.h +++ b/src/include/parser/ddl/alter_info.h @@ -18,8 +18,8 @@ struct AlterInfo { std::string tableName; std::unique_ptr extraInfo; - AlterInfo( - common::AlterType type, std::string tableName, std::unique_ptr extraInfo) + AlterInfo(common::AlterType type, std::string tableName, + std::unique_ptr extraInfo) : type{type}, tableName{std::move(tableName)}, extraInfo{std::move(extraInfo)} {} DELETE_COPY_DEFAULT_MOVE(AlterInfo); }; diff --git a/src/include/parser/ddl/create_table_info.h b/src/include/parser/ddl/create_table_info.h index 7cac23c1132..bef38ea4c0c 100644 --- a/src/include/parser/ddl/create_table_info.h +++ b/src/include/parser/ddl/create_table_info.h @@ -37,8 +37,8 @@ struct ExtraCreateRelTableInfo : public ExtraCreateTableInfo { std::string srcTableName; std::string dstTableName; - ExtraCreateRelTableInfo( - std::string relMultiplicity, std::string srcTableName, std::string dstTableName) + ExtraCreateRelTableInfo(std::string relMultiplicity, std::string srcTableName, + std::string dstTableName) : relMultiplicity{std::move(relMultiplicity)}, srcTableName{std::move(srcTableName)}, dstTableName{std::move(dstTableName)} {} }; @@ -49,8 +49,8 @@ struct ExtraCreateRelTableGroupInfo : public ExtraCreateTableInfo { ExtraCreateRelTableGroupInfo(std::string relMultiplicity, std::vector> srcDstTablePairs) - : relMultiplicity{std::move(relMultiplicity)}, srcDstTablePairs{ - std::move(srcDstTablePairs)} {} + : relMultiplicity{std::move(relMultiplicity)}, + srcDstTablePairs{std::move(srcDstTablePairs)} {} }; } // namespace parser diff --git a/src/include/parser/detach_database.h b/src/include/parser/detach_database.h new file mode 100644 index 00000000000..5a9b4f6bbef --- /dev/null +++ b/src/include/parser/detach_database.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include "parser/statement.h" + +namespace kuzu { +namespace parser { + +class DetachDatabase final : public Statement { +public: + explicit DetachDatabase(std::string dbName) + : Statement{common::StatementType::DETACH_DATABASE}, dbName{std::move(dbName)} {} + + std::string getDBName() const { return dbName; } + +private: + std::string dbName; +}; + +} // namespace parser +} // namespace kuzu diff --git a/src/include/parser/expression/parsed_case_expression.h b/src/include/parser/expression/parsed_case_expression.h index 0cd4b74a171..e9f709036fb 100644 --- a/src/include/parser/expression/parsed_case_expression.h +++ b/src/include/parser/expression/parsed_case_expression.h @@ -15,8 +15,8 @@ struct ParsedCaseAlternative { std::unique_ptr thenExpression) : whenExpression{std::move(whenExpression)}, thenExpression{std::move(thenExpression)} {} ParsedCaseAlternative(const ParsedCaseAlternative& other) - : whenExpression{other.whenExpression->copy()}, thenExpression{ - other.thenExpression->copy()} {} + : whenExpression{other.whenExpression->copy()}, + thenExpression{other.thenExpression->copy()} {} DEFAULT_BOTH_MOVE(ParsedCaseAlternative); void serialize(common::Serializer& serializer) const; @@ -47,10 +47,9 @@ class ParsedCaseExpression final : public ParsedExpression { ParsedCaseExpression(std::unique_ptr caseExpression, std::vector caseAlternatives, std::unique_ptr elseExpression) - : ParsedExpression{common::ExpressionType::CASE_ELSE}, caseExpression{std::move( - caseExpression)}, - caseAlternatives{std::move(caseAlternatives)}, elseExpression{std::move(elseExpression)} { - } + : ParsedExpression{common::ExpressionType::CASE_ELSE}, + caseExpression{std::move(caseExpression)}, caseAlternatives{std::move(caseAlternatives)}, + elseExpression{std::move(elseExpression)} {} inline void setCaseExpression(std::unique_ptr expression) { caseExpression = std::move(expression); diff --git a/src/include/parser/expression/parsed_expression.h b/src/include/parser/expression/parsed_expression.h index a8a3257adbe..2033910f010 100644 --- a/src/include/parser/expression/parsed_expression.h +++ b/src/include/parser/expression/parsed_expression.h @@ -29,8 +29,8 @@ class ParsedExpression { friend class ParsedExpressionChildrenVisitor; public: - ParsedExpression( - common::ExpressionType type, std::unique_ptr child, std::string rawName); + ParsedExpression(common::ExpressionType type, std::unique_ptr child, + std::string rawName); ParsedExpression(common::ExpressionType type, std::unique_ptr left, std::unique_ptr right, std::string rawName); @@ -42,8 +42,8 @@ class ParsedExpression { ParsedExpression(common::ExpressionType type, std::string alias, std::string rawName, parsed_expr_vector children) - : type{type}, alias{std::move(alias)}, rawName{std::move(rawName)}, children{std::move( - children)} {} + : type{type}, alias{std::move(alias)}, rawName{std::move(rawName)}, + children{std::move(children)} {} DELETE_COPY_DEFAULT_MOVE(ParsedExpression); virtual ~ParsedExpression() = default; diff --git a/src/include/parser/expression/parsed_function_expression.h b/src/include/parser/expression/parsed_function_expression.h index 1c9e7951c44..dc1021d4e75 100644 --- a/src/include/parser/expression/parsed_function_expression.h +++ b/src/include/parser/expression/parsed_function_expression.h @@ -1,5 +1,6 @@ #pragma once +#include "common/string_utils.h" #include "parsed_expression.h" namespace kuzu { @@ -34,7 +35,10 @@ class ParsedFunctionExpression : public ParsedExpression { inline bool getIsDistinct() const { return isDistinct; } - inline std::string getFunctionName() const { return functionName; } + std::string getFunctionName() const { return functionName; } + std::string getNormalizedFunctionName() const { + return common::StringUtils::getUpper(functionName); + } // A function might have more than 2 parameters. inline void addChild(std::unique_ptr child) { @@ -45,8 +49,8 @@ class ParsedFunctionExpression : public ParsedExpression { common::Deserializer& deserializer); inline std::unique_ptr copy() const override { - return std::make_unique( - alias, rawName, copyChildren(), functionName, isDistinct); + return std::make_unique(alias, rawName, copyChildren(), + functionName, isDistinct); } private: diff --git a/src/include/parser/expression/parsed_literal_expression.h b/src/include/parser/expression/parsed_literal_expression.h index bfe14d82080..90e73dc4eec 100644 --- a/src/include/parser/expression/parsed_literal_expression.h +++ b/src/include/parser/expression/parsed_literal_expression.h @@ -9,11 +9,11 @@ namespace parser { class ParsedLiteralExpression : public ParsedExpression { public: ParsedLiteralExpression(common::Value value, std::string raw) - : ParsedExpression{common::ExpressionType::LITERAL, std::move(raw)}, value{std::move( - value)} {} + : ParsedExpression{common::ExpressionType::LITERAL, std::move(raw)}, + value{std::move(value)} {} - ParsedLiteralExpression( - std::string alias, std::string rawName, parsed_expr_vector children, common::Value value) + ParsedLiteralExpression(std::string alias, std::string rawName, parsed_expr_vector children, + common::Value value) : ParsedExpression{common::ExpressionType::LITERAL, std::move(alias), std::move(rawName), std::move(children)}, value{std::move(value)} {} diff --git a/src/include/parser/expression/parsed_property_expression.h b/src/include/parser/expression/parsed_property_expression.h index c89e21c520f..55f218994d3 100644 --- a/src/include/parser/expression/parsed_property_expression.h +++ b/src/include/parser/expression/parsed_property_expression.h @@ -9,8 +9,8 @@ namespace parser { class ParsedPropertyExpression : public ParsedExpression { public: - ParsedPropertyExpression( - std::string propertyName, std::unique_ptr child, std::string raw) + ParsedPropertyExpression(std::string propertyName, std::unique_ptr child, + std::string raw) : ParsedExpression{common::ExpressionType::PROPERTY, std::move(child), std::move(raw)}, propertyName{std::move(propertyName)} {} @@ -21,8 +21,8 @@ class ParsedPropertyExpression : public ParsedExpression { propertyName{std::move(propertyName)} {} explicit ParsedPropertyExpression(std::string propertyName) - : ParsedExpression{common::ExpressionType::PROPERTY}, propertyName{ - std::move(propertyName)} {} + : ParsedExpression{common::ExpressionType::PROPERTY}, + propertyName{std::move(propertyName)} {} inline std::string getPropertyName() const { return propertyName; } inline bool isStar() const { return propertyName == common::InternalKeyword::STAR; } @@ -31,8 +31,8 @@ class ParsedPropertyExpression : public ParsedExpression { common::Deserializer& deserializer); inline std::unique_ptr copy() const override { - return std::make_unique( - alias, rawName, copyChildren(), propertyName); + return std::make_unique(alias, rawName, copyChildren(), + propertyName); } private: diff --git a/src/include/parser/expression/parsed_variable_expression.h b/src/include/parser/expression/parsed_variable_expression.h index 40618c0adc6..4ee7545b831 100644 --- a/src/include/parser/expression/parsed_variable_expression.h +++ b/src/include/parser/expression/parsed_variable_expression.h @@ -20,8 +20,8 @@ class ParsedVariableExpression : public ParsedExpression { variableName{std::move(variableName)} {} explicit ParsedVariableExpression(std::string variableName) - : ParsedExpression{common::ExpressionType::VARIABLE}, variableName{ - std::move(variableName)} {} + : ParsedExpression{common::ExpressionType::VARIABLE}, + variableName{std::move(variableName)} {} inline std::string getVariableName() const { return variableName; } @@ -29,8 +29,8 @@ class ParsedVariableExpression : public ParsedExpression { common::Deserializer& deserializer); inline std::unique_ptr copy() const override { - return std::make_unique( - alias, rawName, copyChildren(), variableName); + return std::make_unique(alias, rawName, copyChildren(), + variableName); } private: diff --git a/src/include/parser/parsed_data/attach_info.h b/src/include/parser/parsed_data/attach_info.h new file mode 100644 index 00000000000..71dbb9c54fc --- /dev/null +++ b/src/include/parser/parsed_data/attach_info.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace kuzu { +namespace parser { + +struct AttachInfo { + std::string dbPath, dbAlias, dbType; +}; + +} // namespace parser +} // namespace kuzu diff --git a/src/include/parser/parsed_statement_visitor.h b/src/include/parser/parsed_statement_visitor.h index 76769561aee..73673d1609a 100644 --- a/src/include/parser/parsed_statement_visitor.h +++ b/src/include/parser/parsed_statement_visitor.h @@ -50,6 +50,8 @@ class StatementVisitor { virtual void visitExtension(const Statement& /*statement*/) {} virtual void visitExportDatabase(const Statement& /*statement*/) {} virtual void visitImportDatabase(const Statement& /*statement*/) {} + virtual void visitAttachDatabase(const Statement& /*statement*/) {} + virtual void visitDetachDatabase(const Statement& /*statement*/) {} // LCOV_EXCL_STOP }; diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h index 5ca9ef9ba8b..a6bed351df1 100644 --- a/src/include/parser/parser.h +++ b/src/include/parser/parser.h @@ -12,7 +12,7 @@ namespace parser { class Parser { public: - static std::vector> parseQuery(std::string_view query); + static std::vector> parseQuery(std::string_view query); }; } // namespace parser diff --git a/src/include/parser/query/graph_pattern/rel_pattern.h b/src/include/parser/query/graph_pattern/rel_pattern.h index 424580f7bbb..e45dc21a851 100644 --- a/src/include/parser/query/graph_pattern/rel_pattern.h +++ b/src/include/parser/query/graph_pattern/rel_pattern.h @@ -29,8 +29,8 @@ class RelPattern : public NodePattern { ArrowDirection arrowDirection, std::vector propertyKeyValPairs, RecursiveRelPatternInfo recursiveInfo) : NodePattern{std::move(name), std::move(tableNames), std::move(propertyKeyValPairs)}, - relType{relType}, arrowDirection{arrowDirection}, recursiveInfo{ - std::move(recursiveInfo)} {} + relType{relType}, arrowDirection{arrowDirection}, + recursiveInfo{std::move(recursiveInfo)} {} DELETE_COPY_DEFAULT_MOVE(RelPattern); inline common::QueryRelType getRelType() const { return relType; } diff --git a/src/include/parser/query/reading_clause/in_query_call_clause.h b/src/include/parser/query/reading_clause/in_query_call_clause.h index 2534f7f5300..309da657251 100644 --- a/src/include/parser/query/reading_clause/in_query_call_clause.h +++ b/src/include/parser/query/reading_clause/in_query_call_clause.h @@ -9,8 +9,8 @@ namespace parser { class InQueryCallClause final : public ReadingClause { public: explicit InQueryCallClause(std::unique_ptr functionExpression) - : ReadingClause{common::ClauseType::IN_QUERY_CALL}, functionExpression{ - std::move(functionExpression)} {} + : ReadingClause{common::ClauseType::IN_QUERY_CALL}, + functionExpression{std::move(functionExpression)} {} inline const ParsedExpression* getFunctionExpression() const { return functionExpression.get(); diff --git a/src/include/parser/query/reading_clause/load_from.h b/src/include/parser/query/reading_clause/load_from.h index 0674167f12b..386116186b5 100644 --- a/src/include/parser/query/reading_clause/load_from.h +++ b/src/include/parser/query/reading_clause/load_from.h @@ -1,6 +1,7 @@ #pragma once #include "parser/expression/parsed_expression.h" +#include "parser/scan_source.h" #include "reading_clause.h" namespace kuzu { @@ -8,17 +9,10 @@ namespace parser { class LoadFrom : public ReadingClause { public: - LoadFrom() : ReadingClause{common::ClauseType::LOAD_FROM} {} + explicit LoadFrom(std::unique_ptr source) + : ReadingClause{common::ClauseType::LOAD_FROM}, source{std::move(source)} {} - inline bool hasObjectName() const { return !objectName.empty(); } - inline std::string getObjectname() const { return objectName; } - inline void setObjectName(const std::string& name) { objectName = name; } - - inline bool hasFilePaths() const { return !filePaths.empty(); } - inline std::vector getFilePaths() const { return filePaths; } - inline void setFilePaths(std::vector filePaths_) { - filePaths = std::move(filePaths_); - } + inline BaseScanSource* getSource() const { return source.get(); } inline void setParingOptions(parsing_option_t options) { parsingOptions = std::move(options); } inline const parsing_option_t& getParsingOptionsRef() const { return parsingOptions; } @@ -39,8 +33,7 @@ class LoadFrom : public ReadingClause { inline const ParsedExpression* getWherePredicate() const { return wherePredicate.get(); } private: - std::string objectName; - std::vector filePaths; + std::unique_ptr source; std::vector> columnNameDataTypes; parsing_option_t parsingOptions; std::unique_ptr wherePredicate; diff --git a/src/include/parser/query/reading_clause/match_clause.h b/src/include/parser/query/reading_clause/match_clause.h index 05f3975524d..5a7eb9f31b3 100644 --- a/src/include/parser/query/reading_clause/match_clause.h +++ b/src/include/parser/query/reading_clause/match_clause.h @@ -9,8 +9,8 @@ namespace parser { class MatchClause : public ReadingClause { public: - MatchClause( - std::vector patternElements, common::MatchClauseType matchClauseType) + MatchClause(std::vector patternElements, + common::MatchClauseType matchClauseType) : ReadingClause{common::ClauseType::MATCH}, patternElements{std::move(patternElements)}, matchClauseType{matchClauseType} {} diff --git a/src/include/parser/query/reading_clause/unwind_clause.h b/src/include/parser/query/reading_clause/unwind_clause.h index c3554cc94cb..70de26ecf33 100644 --- a/src/include/parser/query/reading_clause/unwind_clause.h +++ b/src/include/parser/query/reading_clause/unwind_clause.h @@ -8,13 +8,13 @@ namespace parser { class UnwindClause : public ReadingClause { public: - explicit UnwindClause(std::unique_ptr expression, std::string listAlias) - : ReadingClause{common::ClauseType::UNWIND}, - expression{std::move(expression)}, alias{std::move(listAlias)} {} + UnwindClause(std::unique_ptr expression, std::string listAlias) + : ReadingClause{common::ClauseType::UNWIND}, expression{std::move(expression)}, + alias{std::move(listAlias)} {} - inline const ParsedExpression* getExpression() const { return expression.get(); } + const ParsedExpression* getExpression() const { return expression.get(); } - inline std::string getAlias() const { return alias; } + std::string getAlias() const { return alias; } private: std::unique_ptr expression; diff --git a/src/include/parser/query/return_with_clause/projection_body.h b/src/include/parser/query/return_with_clause/projection_body.h index 697557f89b3..6729e3d17b4 100644 --- a/src/include/parser/query/return_with_clause/projection_body.h +++ b/src/include/parser/query/return_with_clause/projection_body.h @@ -8,8 +8,8 @@ namespace parser { class ProjectionBody { public: - ProjectionBody( - bool isDistinct, std::vector> projectionExpressions) + ProjectionBody(bool isDistinct, + std::vector> projectionExpressions) : isDistinct{isDistinct}, projectionExpressions{std::move(projectionExpressions)} {} DELETE_COPY_DEFAULT_MOVE(ProjectionBody); @@ -19,8 +19,8 @@ class ProjectionBody { return projectionExpressions; } - inline void setOrderByExpressions( - std::vector> expressions, std::vector sortOrders) { + inline void setOrderByExpressions(std::vector> expressions, + std::vector sortOrders) { orderByExpressions = std::move(expressions); isAscOrders = std::move(sortOrders); } diff --git a/src/include/parser/query/updating_clause/insert_clause.h b/src/include/parser/query/updating_clause/insert_clause.h index ea836013a5c..715b7a777e2 100644 --- a/src/include/parser/query/updating_clause/insert_clause.h +++ b/src/include/parser/query/updating_clause/insert_clause.h @@ -9,8 +9,8 @@ namespace parser { class InsertClause final : public UpdatingClause { public: explicit InsertClause(std::vector patternElements) - : UpdatingClause{common::ClauseType::INSERT}, patternElements{ - std::move(patternElements)} {}; + : UpdatingClause{common::ClauseType::INSERT}, + patternElements{std::move(patternElements)} {}; inline const std::vector& getPatternElementsRef() const { return patternElements; diff --git a/src/include/parser/scan_source.h b/src/include/parser/scan_source.h new file mode 100644 index 00000000000..c5345116c2e --- /dev/null +++ b/src/include/parser/scan_source.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +#include "common/copy_constructors.h" +#include "common/enums/scan_source_type.h" +#include "parser/statement.h" + +namespace kuzu { +namespace parser { + +struct BaseScanSource { + common::ScanSourceType type; + + explicit BaseScanSource(common::ScanSourceType type) : type{type} {} + virtual ~BaseScanSource() = default; + DELETE_COPY_AND_MOVE(BaseScanSource); +}; + +struct FileScanSource : public BaseScanSource { + std::vector filePaths; + + explicit FileScanSource(std::vector paths) + : BaseScanSource{common::ScanSourceType::FILE}, filePaths{std::move(paths)} {} +}; + +struct ObjectScanSource : public BaseScanSource { + std::string objectName; + + explicit ObjectScanSource(std::string objectName) + : BaseScanSource{common::ScanSourceType::OBJECT}, objectName{std::move(objectName)} {} +}; + +struct QueryScanSource : public BaseScanSource { + std::unique_ptr statement; + + explicit QueryScanSource(std::unique_ptr statement) + : BaseScanSource{common::ScanSourceType::QUERY}, statement{std::move(statement)} {} +}; + +} // namespace parser +} // namespace kuzu diff --git a/src/include/parser/statement.h b/src/include/parser/statement.h index 3cb56749f57..45e3d1bb633 100644 --- a/src/include/parser/statement.h +++ b/src/include/parser/statement.h @@ -13,6 +13,15 @@ class Statement { inline common::StatementType getStatementType() const { return statementType; } + inline bool requireTx() { + switch (statementType) { + case common::StatementType::TRANSACTION: + return false; + default: + return true; + } + } + private: common::StatementType statementType; }; diff --git a/src/include/parser/transformer.h b/src/include/parser/transformer.h index ccd3a40029b..392af7a358f 100644 --- a/src/include/parser/transformer.h +++ b/src/include/parser/transformer.h @@ -25,12 +25,13 @@ class NodePattern; class PatternElementChain; class RelPattern; struct ParsedCaseAlternative; +struct BaseScanSource; class Transformer { public: explicit Transformer(CypherParser::Ku_StatementsContext& root) : root{root} {} - std::vector> transform(); + std::vector> transform(); private: std::unique_ptr transformStatement(CypherParser::OC_StatementContext& ctx); @@ -50,6 +51,7 @@ class Transformer { std::vector transformColumnNames(CypherParser::KU_ColumnNamesContext& ctx); std::vector transformFilePaths( const std::vector& stringLiteral); + std::unique_ptr transformScanSource(CypherParser::KU_ScanSourceContext& ctx); parsing_option_t transformParsingOptions(CypherParser::KU_ParsingOptionsContext& ctx); std::unique_ptr transformExportDatabase(CypherParser::KU_ExportDatabaseContext& ctx); @@ -217,6 +219,10 @@ class Transformer { // Transform comment on. std::unique_ptr transformCommentOn(CypherParser::KU_CommentOnContext& ctx); + // Transform attach/detach database. + std::unique_ptr transformAttachDatabase(CypherParser::KU_AttachDatabaseContext& ctx); + std::unique_ptr transformDetachDatabase(CypherParser::KU_DetachDatabaseContext& ctx); + private: CypherParser::Ku_StatementsContext& root; }; diff --git a/src/include/planner/join_order/cardinality_estimator.h b/src/include/planner/join_order/cardinality_estimator.h index 97f1a7b6ce8..01b388ed852 100644 --- a/src/include/planner/join_order/cardinality_estimator.h +++ b/src/include/planner/join_order/cardinality_estimator.h @@ -17,9 +17,9 @@ class CardinalityEstimator { DELETE_COPY_DEFAULT_MOVE(CardinalityEstimator); // TODO(Xiyang): revisit this init at some point. Maybe we should init while enumerating. - void initNodeIDDom(const binder::QueryGraph& queryGraph); - void addNodeIDDom( - const binder::Expression& nodeID, const std::vector& tableIDs); + void initNodeIDDom(const binder::QueryGraph& queryGraph, transaction::Transaction* transaction); + void addNodeIDDom(const binder::Expression& nodeID, + const std::vector& tableIDs, transaction::Transaction* transaction); uint64_t estimateScanNode(LogicalOperator* op); uint64_t estimateHashJoin(const binder::expression_vector& joinKeys, @@ -30,8 +30,8 @@ class CardinalityEstimator { uint64_t estimateFlatten(const LogicalPlan& childPlan, f_group_pos groupPosToFlatten); uint64_t estimateFilter(const LogicalPlan& childPlan, const binder::Expression& predicate); - double getExtensionRate( - const binder::RelExpression& rel, const binder::NodeExpression& boundNode); + double getExtensionRate(const binder::RelExpression& rel, + const binder::NodeExpression& boundNode, transaction::Transaction* transaction); private: inline uint64_t atLeastOne(uint64_t x) { return x == 0 ? 1 : x; } @@ -40,9 +40,11 @@ class CardinalityEstimator { KU_ASSERT(nodeIDName2dom.contains(nodeIDName)); return nodeIDName2dom.at(nodeIDName); } - uint64_t getNumNodes(const std::vector& tableIDs); + uint64_t getNumNodes(const std::vector& tableIDs, + transaction::Transaction* transaction); - uint64_t getNumRels(const std::vector& tableIDs); + uint64_t getNumRels(const std::vector& tableIDs, + transaction::Transaction* transaction); private: const storage::NodesStoreStatsAndDeletedIDs* nodesStatistics; diff --git a/src/include/planner/join_order/cost_model.h b/src/include/planner/join_order/cost_model.h index afc1e4bb61f..94e6ba19492 100644 --- a/src/include/planner/join_order/cost_model.h +++ b/src/include/planner/join_order/cost_model.h @@ -8,14 +8,14 @@ namespace planner { class CostModel { public: static uint64_t computeExtendCost(const LogicalPlan& childPlan); - static uint64_t computeRecursiveExtendCost( - uint8_t upperBound, double extensionRate, const LogicalPlan& childPlan); + static uint64_t computeRecursiveExtendCost(uint8_t upperBound, double extensionRate, + const LogicalPlan& childPlan); static uint64_t computeHashJoinCost(const binder::expression_vector& joinNodeIDs, const LogicalPlan& probe, const LogicalPlan& build); static uint64_t computeMarkJoinCost(const binder::expression_vector& joinNodeIDs, const LogicalPlan& probe, const LogicalPlan& build); - static uint64_t computeIntersectCost( - const LogicalPlan& probePlan, const std::vector>& buildPlans); + static uint64_t computeIntersectCost(const LogicalPlan& probePlan, + const std::vector>& buildPlans); }; } // namespace planner diff --git a/src/include/planner/join_order/join_order_util.h b/src/include/planner/join_order/join_order_util.h index 52cde7f159f..47a715da090 100644 --- a/src/include/planner/join_order/join_order_util.h +++ b/src/include/planner/join_order/join_order_util.h @@ -8,8 +8,8 @@ namespace planner { struct JoinOrderUtil { // Although we do not flatten join key in Build operator computation. We still need to perform // cardinality and cost estimation based on their flat cardinality. - static uint64_t getJoinKeysFlatCardinality( - const binder::expression_vector& joinNodeIDs, const LogicalPlan& buildPlan); + static uint64_t getJoinKeysFlatCardinality(const binder::expression_vector& joinNodeIDs, + const LogicalPlan& buildPlan); }; } // namespace planner diff --git a/src/include/planner/join_order_enumerator_context.h b/src/include/planner/join_order_enumerator_context.h index af77ac05c91..3f4ddccb4c0 100644 --- a/src/include/planner/join_order_enumerator_context.h +++ b/src/include/planner/join_order_enumerator_context.h @@ -18,8 +18,8 @@ class JoinOrderEnumeratorContext { public: JoinOrderEnumeratorContext() : currentLevel{0}, maxLevel{0}, subPlansTable{std::make_unique()}, - queryGraph{nullptr}, subqueryType{SubqueryType::NONE}, correlatedExpressionsCardinality{ - 1} {} + queryGraph{nullptr}, subqueryType{SubqueryType::NONE}, + correlatedExpressionsCardinality{1} {} DELETE_COPY_DEFAULT_MOVE(JoinOrderEnumeratorContext); void init(const binder::QueryGraph* queryGraph, const binder::expression_vector& predicates); @@ -33,8 +33,8 @@ class JoinOrderEnumeratorContext { const binder::SubqueryGraph& subqueryGraph) const { return subPlansTable->getSubgraphPlans(subqueryGraph); } - inline void addPlan( - const binder::SubqueryGraph& subqueryGraph, std::unique_ptr plan) { + inline void addPlan(const binder::SubqueryGraph& subqueryGraph, + std::unique_ptr plan) { subPlansTable->addPlan(subqueryGraph, std::move(plan)); } diff --git a/src/include/planner/operator/extend/extend_direction.h b/src/include/planner/operator/extend/extend_direction.h index 079727f9547..0541cef3889 100644 --- a/src/include/planner/operator/extend/extend_direction.h +++ b/src/include/planner/operator/extend/extend_direction.h @@ -11,8 +11,8 @@ namespace planner { enum class ExtendDirection : uint8_t { FWD = 0, BWD = 1, BOTH = 2 }; struct ExtendDirectionUtils { - static inline ExtendDirection getExtendDirection( - const binder::RelExpression& relExpression, const binder::NodeExpression& boundNode) { + static inline ExtendDirection getExtendDirection(const binder::RelExpression& relExpression, + const binder::NodeExpression& boundNode) { if (relExpression.getDirectionType() == binder::RelDirectionType::BOTH) { return ExtendDirection::BOTH; } diff --git a/src/include/planner/operator/extend/logical_extend.h b/src/include/planner/operator/extend/logical_extend.h index ab8aa0eca73..5400d839ded 100644 --- a/src/include/planner/operator/extend/logical_extend.h +++ b/src/include/planner/operator/extend/logical_extend.h @@ -23,8 +23,8 @@ class LogicalExtend : public BaseLogicalExtend { inline binder::expression_vector getProperties() const { return properties; } inline std::unique_ptr copy() override { - return make_unique( - boundNode, nbrNode, rel, direction, properties, hasAtMostOneNbr, children[0]->copy()); + return make_unique(boundNode, nbrNode, rel, direction, properties, + hasAtMostOneNbr, children[0]->copy()); } private: diff --git a/src/include/planner/operator/factorization/sink_util.h b/src/include/planner/operator/factorization/sink_util.h index 20d3c7b1eec..a9e2d96fe1a 100644 --- a/src/include/planner/operator/factorization/sink_util.h +++ b/src/include/planner/operator/factorization/sink_util.h @@ -18,8 +18,8 @@ class SinkOperatorUtil { static std::unordered_map getUnFlatPayloadsPerGroup( const Schema& schema, const binder::expression_vector& payloads); - static binder::expression_vector getFlatPayloads( - const Schema& schema, const binder::expression_vector& payloads); + static binder::expression_vector getFlatPayloads(const Schema& schema, + const binder::expression_vector& payloads); static uint32_t appendPayloadsToNewGroup(Schema& schema, binder::expression_vector& payloads); }; diff --git a/src/include/planner/operator/logical_accumulate.h b/src/include/planner/operator/logical_accumulate.h index 8a8e546f9bd..3ed55bfc0af 100644 --- a/src/include/planner/operator/logical_accumulate.h +++ b/src/include/planner/operator/logical_accumulate.h @@ -6,33 +6,38 @@ namespace kuzu { namespace planner { -class LogicalAccumulate : public LogicalOperator { +class LogicalAccumulate final : public LogicalOperator { public: - LogicalAccumulate(common::AccumulateType accumulateType, - binder::expression_vector expressionsToFlatten, std::shared_ptr child) + LogicalAccumulate(common::AccumulateType accumulateType, binder::expression_vector flatExprs, + std::shared_ptr offset, std::shared_ptr child) : LogicalOperator{LogicalOperatorType::ACCUMULATE, std::move(child)}, - accumulateType{accumulateType}, expressionsToFlatten{std::move(expressionsToFlatten)} {} + accumulateType{accumulateType}, flatExprs{std::move(flatExprs)}, + offset{std::move(offset)} {} - void computeFactorizedSchema() final; - void computeFlatSchema() final; + void computeFactorizedSchema() override; + void computeFlatSchema() override; f_group_pos_set getGroupPositionsToFlatten() const; - inline std::string getExpressionsForPrinting() const final { return std::string{}; } + std::string getExpressionsForPrinting() const override { return {}; } - inline common::AccumulateType getAccumulateType() const { return accumulateType; } - inline binder::expression_vector getExpressionsToAccumulate() const { + common::AccumulateType getAccumulateType() const { return accumulateType; } + binder::expression_vector getPayloads() const { return children[0]->getSchema()->getExpressionsInScope(); } + std::shared_ptr getOffset() const { return offset; } - inline std::unique_ptr copy() final { - return make_unique( - accumulateType, expressionsToFlatten, children[0]->copy()); + std::unique_ptr copy() override { + return make_unique(accumulateType, flatExprs, offset, + children[0]->copy()); } private: common::AccumulateType accumulateType; - binder::expression_vector expressionsToFlatten; + binder::expression_vector flatExprs; + // Accumulate may be used as a source operator for COPY pipeline. In such case, row offset needs + // to be provided in order to generate internal ID. + std::shared_ptr offset; }; } // namespace planner diff --git a/src/include/planner/operator/logical_aggregate.h b/src/include/planner/operator/logical_aggregate.h index 105616385f7..a5e4e700c2f 100644 --- a/src/include/planner/operator/logical_aggregate.h +++ b/src/include/planner/operator/logical_aggregate.h @@ -10,14 +10,14 @@ class LogicalAggregate : public LogicalOperator { LogicalAggregate(binder::expression_vector keyExpressions, binder::expression_vector aggregateExpressions, std::shared_ptr child) : LogicalOperator{LogicalOperatorType::AGGREGATE, std::move(child)}, - keyExpressions{std::move(keyExpressions)}, aggregateExpressions{ - std::move(aggregateExpressions)} {} + keyExpressions{std::move(keyExpressions)}, + aggregateExpressions{std::move(aggregateExpressions)} {} LogicalAggregate(binder::expression_vector keyExpressions, binder::expression_vector dependentKeyExpressions, binder::expression_vector aggregateExpressions, std::shared_ptr child) : LogicalOperator{LogicalOperatorType::AGGREGATE, std::move(child)}, - keyExpressions{std::move(keyExpressions)}, dependentKeyExpressions{std::move( - dependentKeyExpressions)}, + keyExpressions{std::move(keyExpressions)}, + dependentKeyExpressions{std::move(dependentKeyExpressions)}, aggregateExpressions{std::move(aggregateExpressions)} {} void computeFactorizedSchema() override; @@ -50,8 +50,8 @@ class LogicalAggregate : public LogicalOperator { } inline std::unique_ptr copy() override { - return make_unique( - keyExpressions, dependentKeyExpressions, aggregateExpressions, children[0]->copy()); + return make_unique(keyExpressions, dependentKeyExpressions, + aggregateExpressions, children[0]->copy()); } private: diff --git a/src/include/planner/operator/logical_attach_database.h b/src/include/planner/operator/logical_attach_database.h new file mode 100644 index 00000000000..971c8da1d51 --- /dev/null +++ b/src/include/planner/operator/logical_attach_database.h @@ -0,0 +1,31 @@ +#pragma once + +#include "parser/parsed_data/attach_info.h" +#include "planner/operator/logical_operator.h" + +namespace kuzu { +namespace planner { + +class LogicalAttachDatabase final : public LogicalOperator { +public: + explicit LogicalAttachDatabase(parser::AttachInfo attachInfo) + : LogicalOperator{LogicalOperatorType::ATTACH_DATABASE}, attachInfo{std::move(attachInfo)} { + } + + parser::AttachInfo getAttachInfo() const { return attachInfo; } + + std::string getExpressionsForPrinting() const override { return attachInfo.dbPath; } + + void computeFactorizedSchema() override { createEmptySchema(); } + void computeFlatSchema() override { createEmptySchema(); } + + std::unique_ptr copy() override { + return std::make_unique(attachInfo); + } + +private: + parser::AttachInfo attachInfo; +}; + +} // namespace planner +} // namespace kuzu diff --git a/src/include/planner/operator/logical_create_macro.h b/src/include/planner/operator/logical_create_macro.h index 72a663710cf..7b123047aa2 100644 --- a/src/include/planner/operator/logical_create_macro.h +++ b/src/include/planner/operator/logical_create_macro.h @@ -10,9 +10,9 @@ class LogicalCreateMacro : public LogicalOperator { public: LogicalCreateMacro(std::shared_ptr outputExpression, std::string macroName, std::unique_ptr macro) - : LogicalOperator{LogicalOperatorType::CREATE_MACRO}, outputExpression{std::move( - outputExpression)}, - macroName{std::move(macroName)}, macro{std::move(macro)} {} + : LogicalOperator{LogicalOperatorType::CREATE_MACRO}, + outputExpression{std::move(outputExpression)}, macroName{std::move(macroName)}, + macro{std::move(macro)} {} void computeFactorizedSchema() override; void computeFlatSchema() override; diff --git a/src/include/planner/operator/logical_cross_product.h b/src/include/planner/operator/logical_cross_product.h index 9825b272ff0..d25557646eb 100644 --- a/src/include/planner/operator/logical_cross_product.h +++ b/src/include/planner/operator/logical_cross_product.h @@ -22,8 +22,8 @@ class LogicalCrossProduct : public LogicalOperator { inline common::AccumulateType getAccumulateType() const { return accumulateType; } inline std::unique_ptr copy() override { - return make_unique( - accumulateType, children[0]->copy(), children[1]->copy()); + return make_unique(accumulateType, children[0]->copy(), + children[1]->copy()); } private: diff --git a/src/include/planner/operator/logical_detach_database.h b/src/include/planner/operator/logical_detach_database.h new file mode 100644 index 00000000000..feaa712b4e5 --- /dev/null +++ b/src/include/planner/operator/logical_detach_database.h @@ -0,0 +1,29 @@ +#pragma once + +#include "planner/operator/logical_operator.h" + +namespace kuzu { +namespace planner { + +class LogicalDetachDatabase final : public LogicalOperator { +public: + explicit LogicalDetachDatabase(std::string dbName) + : LogicalOperator{LogicalOperatorType::DETACH_DATABASE}, dbName{std::move(dbName)} {} + + std::string getDBName() const { return dbName; } + + std::string getExpressionsForPrinting() const override { return dbName; } + + void computeFactorizedSchema() override { createEmptySchema(); } + void computeFlatSchema() override { createEmptySchema(); } + + std::unique_ptr copy() override { + return std::make_unique(dbName); + } + +private: + std::string dbName; +}; + +} // namespace planner +} // namespace kuzu diff --git a/src/include/planner/operator/logical_distinct.h b/src/include/planner/operator/logical_distinct.h index c635c14447f..bc58ed489c5 100644 --- a/src/include/planner/operator/logical_distinct.h +++ b/src/include/planner/operator/logical_distinct.h @@ -1,56 +1,43 @@ #pragma once #include "planner/operator/logical_operator.h" -#include "planner/operator/schema.h" namespace kuzu { namespace planner { class LogicalDistinct : public LogicalOperator { public: - LogicalDistinct( - binder::expression_vector keyExpressions, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::DISTINCT, std::move(child)}, - keyExpressions{std::move(keyExpressions)} {} - LogicalDistinct(binder::expression_vector keyExpressions, - binder::expression_vector dependentKeyExpressions, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::DISTINCT, std::move(child)}, - keyExpressions{std::move(keyExpressions)}, dependentKeyExpressions{ - std::move(dependentKeyExpressions)} {} + LogicalDistinct(binder::expression_vector keys, std::shared_ptr child) + : LogicalDistinct{LogicalOperatorType::DISTINCT, keys, binder::expression_vector{}, + std::move(child)} {} + LogicalDistinct(LogicalOperatorType type, binder::expression_vector keys, + binder::expression_vector payloads, std::shared_ptr child) + : LogicalOperator{type, std::move(child)}, keys{std::move(keys)}, + payloads{std::move(payloads)} {} void computeFactorizedSchema() override; void computeFlatSchema() override; - f_group_pos_set getGroupsPosToFlatten(); + virtual f_group_pos_set getGroupsPosToFlatten(); std::string getExpressionsForPrinting() const override; - inline binder::expression_vector getKeyExpressions() const { return keyExpressions; } - inline void setKeyExpressions(binder::expression_vector expressions) { - keyExpressions = std::move(expressions); - } - inline binder::expression_vector getDependentKeyExpressions() const { - return dependentKeyExpressions; - } - inline void setDependentKeyExpressions(binder::expression_vector expressions) { - dependentKeyExpressions = std::move(expressions); - } - inline binder::expression_vector getAllDistinctExpressions() const { - binder::expression_vector result; - result.insert(result.end(), keyExpressions.begin(), keyExpressions.end()); - result.insert(result.end(), dependentKeyExpressions.begin(), dependentKeyExpressions.end()); - return result; - } + binder::expression_vector getKeys() const { return keys; } + void setKeys(binder::expression_vector expressions) { keys = std::move(expressions); } + binder::expression_vector getPayloads() const { return payloads; } + void setPayloads(binder::expression_vector expressions) { payloads = std::move(expressions); } std::unique_ptr copy() override { - return make_unique( - keyExpressions, dependentKeyExpressions, children[0]->copy()); + return make_unique(operatorType, keys, payloads, children[0]->copy()); } -private: - binder::expression_vector keyExpressions; - // See logical_aggregate.h for details. - binder::expression_vector dependentKeyExpressions; +protected: + binder::expression_vector getKeysAndPayloads() const; + +protected: + binder::expression_vector keys; + // Payloads meaning additional keys that are functional dependent on the keys above. + binder::expression_vector payloads; }; } // namespace planner diff --git a/src/include/planner/operator/logical_explain.h b/src/include/planner/operator/logical_explain.h index f1cc2c53740..83e2e1d8ebd 100644 --- a/src/include/planner/operator/logical_explain.h +++ b/src/include/planner/operator/logical_explain.h @@ -34,8 +34,8 @@ class LogicalExplain : public LogicalOperator { } inline std::unique_ptr copy() override { - return std::make_unique( - children[0], outputExpression, explainType, outputExpressionsToExplain); + return std::make_unique(children[0], outputExpression, explainType, + outputExpressionsToExplain); } private: diff --git a/src/include/planner/operator/logical_filter.h b/src/include/planner/operator/logical_filter.h index 335f671edb4..1487ac8dd2c 100644 --- a/src/include/planner/operator/logical_filter.h +++ b/src/include/planner/operator/logical_filter.h @@ -8,10 +8,10 @@ namespace planner { class LogicalFilter : public LogicalOperator { public: - LogicalFilter( - std::shared_ptr expression, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::FILTER, std::move(child)}, expression{std::move( - expression)} {} + LogicalFilter(std::shared_ptr expression, + std::shared_ptr child) + : LogicalOperator{LogicalOperatorType::FILTER, std::move(child)}, + expression{std::move(expression)} {} inline void computeFactorizedSchema() override { copyChildSchema(0); } inline void computeFlatSchema() override { copyChildSchema(0); } diff --git a/src/include/planner/operator/logical_hash_join.h b/src/include/planner/operator/logical_hash_join.h index f9018045afa..e1e49028989 100644 --- a/src/include/planner/operator/logical_hash_join.h +++ b/src/include/planner/operator/logical_hash_join.h @@ -70,8 +70,8 @@ class LogicalHashJoin : public LogicalOperator { inline JoinSubPlanSolveOrder getJoinSubPlanSolveOrder() const { return order; } inline std::unique_ptr copy() override { - return make_unique( - joinConditions, joinType, mark, children[0]->copy(), children[1]->copy()); + return make_unique(joinConditions, joinType, mark, children[0]->copy(), + children[1]->copy()); } // Flat probe side key group in either of the following two cases: diff --git a/src/include/planner/operator/logical_in_query_call.h b/src/include/planner/operator/logical_in_query_call.h index e26c87e3f79..f77f0c245eb 100644 --- a/src/include/planner/operator/logical_in_query_call.h +++ b/src/include/planner/operator/logical_in_query_call.h @@ -9,7 +9,7 @@ namespace planner { class LogicalInQueryCall : public LogicalOperator { public: - LogicalInQueryCall(function::TableFunction* tableFunc, + LogicalInQueryCall(function::TableFunction tableFunc, std::unique_ptr bindData, binder::expression_vector outputExpressions, std::shared_ptr rowIDExpression) @@ -17,7 +17,7 @@ class LogicalInQueryCall : public LogicalOperator { bindData{std::move(bindData)}, outputExpressions{std::move(outputExpressions)}, rowIDExpression{std::move(rowIDExpression)} {} - inline function::TableFunction* getTableFunc() const { return tableFunc; } + inline function::TableFunction getTableFunc() const { return tableFunc; } inline function::TableFuncBindData* getBindData() const { return bindData.get(); } @@ -32,12 +32,12 @@ class LogicalInQueryCall : public LogicalOperator { inline std::string getExpressionsForPrinting() const override { return "CALL TABLE FUNC"; } std::unique_ptr copy() override { - return std::make_unique( - tableFunc, bindData->copy(), outputExpressions, rowIDExpression); + return std::make_unique(tableFunc, bindData->copy(), outputExpressions, + rowIDExpression); } private: - function::TableFunction* tableFunc; + function::TableFunction tableFunc; std::unique_ptr bindData; binder::expression_vector outputExpressions; std::shared_ptr rowIDExpression; diff --git a/src/include/planner/operator/logical_intersect.h b/src/include/planner/operator/logical_intersect.h index 3ec8e73f01b..6770cae9e9a 100644 --- a/src/include/planner/operator/logical_intersect.h +++ b/src/include/planner/operator/logical_intersect.h @@ -12,8 +12,8 @@ class LogicalIntersect : public LogicalOperator { binder::expression_vector keyNodeIDs, std::shared_ptr probeChild, std::vector> buildChildren) : LogicalOperator{LogicalOperatorType::INTERSECT, std::move(probeChild)}, - intersectNodeID{std::move(intersectNodeID)}, - keyNodeIDs{std::move(keyNodeIDs)}, sip{SidewaysInfoPassing::NONE} { + intersectNodeID{std::move(intersectNodeID)}, keyNodeIDs{std::move(keyNodeIDs)}, + sip{SidewaysInfoPassing::NONE} { for (auto& child : buildChildren) { children.push_back(std::move(child)); } diff --git a/src/include/planner/operator/logical_mark_accmulate.h b/src/include/planner/operator/logical_mark_accmulate.h new file mode 100644 index 00000000000..697cb942977 --- /dev/null +++ b/src/include/planner/operator/logical_mark_accmulate.h @@ -0,0 +1,35 @@ +#pragma once + +#include "planner/operator/logical_operator.h" + +namespace kuzu { +namespace planner { + +class LogicalMarkAccumulate final : public LogicalOperator { +public: + LogicalMarkAccumulate(binder::expression_vector keys, std::shared_ptr mark, + std::shared_ptr child) + : LogicalOperator{LogicalOperatorType::MARK_ACCUMULATE, std::move(child)}, + keys{std::move(keys)}, mark{std::move(mark)} {} + + void computeFactorizedSchema() override; + void computeFlatSchema() override; + + f_group_pos_set getGroupsPosToFlatten() const; + + std::string getExpressionsForPrinting() const override { return {}; } + binder::expression_vector getKeys() const { return keys; } + binder::expression_vector getPayloads() const; + std::shared_ptr getMark() const { return mark; } + + std::unique_ptr copy() override { + return std::make_unique(keys, mark, children[0]->copy()); + } + +private: + binder::expression_vector keys; + std::shared_ptr mark; +}; + +} // namespace planner +} // namespace kuzu diff --git a/src/include/planner/operator/logical_operator.h b/src/include/planner/operator/logical_operator.h index c6c1749c503..a9118b8471f 100644 --- a/src/include/planner/operator/logical_operator.h +++ b/src/include/planner/operator/logical_operator.h @@ -9,6 +9,8 @@ enum class LogicalOperatorType : uint8_t { ACCUMULATE, AGGREGATE, ALTER, + ATTACH_DATABASE, + DETACH_DATABASE, COMMENT_ON, COPY_FROM, COPY_TO, @@ -32,6 +34,7 @@ enum class LogicalOperatorType : uint8_t { INTERSECT, INSERT, LIMIT, + MARK_ACCUMULATE, MERGE, MULTIPLICITY_REDUCER, NODE_LABEL_FILTER, @@ -56,9 +59,9 @@ enum class LogicalOperatorType : uint8_t { IMPORT_DATABASE, }; -class LogicalOperatorUtils { -public: +struct LogicalOperatorUtils { static std::string logicalOperatorTypeToString(LogicalOperatorType type); + static bool isUpdate(LogicalOperatorType type); }; class LogicalOperator; @@ -66,35 +69,33 @@ using logical_op_vector_t = std::vector>; class LogicalOperator { public: - // Leaf operator. explicit LogicalOperator(LogicalOperatorType operatorType) : operatorType{operatorType} {} - // Unary operator. - explicit LogicalOperator( - LogicalOperatorType operatorType, std::shared_ptr child); - // Binary operator. + explicit LogicalOperator(LogicalOperatorType operatorType, + std::shared_ptr child); explicit LogicalOperator(LogicalOperatorType operatorType, std::shared_ptr left, std::shared_ptr right); explicit LogicalOperator(LogicalOperatorType operatorType, const logical_op_vector_t& children); virtual ~LogicalOperator() = default; - inline uint32_t getNumChildren() const { return children.size(); } - - inline std::shared_ptr getChild(uint64_t idx) const { return children[idx]; } - inline std::vector> getChildren() const { return children; } - inline void setChild(uint64_t idx, std::shared_ptr child) { + uint32_t getNumChildren() const { return children.size(); } + std::shared_ptr getChild(uint64_t idx) const { return children[idx]; } + std::vector> getChildren() const { return children; } + void setChild(uint64_t idx, std::shared_ptr child) { children[idx] = std::move(child); } - inline void setChildren(logical_op_vector_t children_) { children = std::move(children_); } - inline LogicalOperatorType getOperatorType() const { return operatorType; } + // Operator type. + LogicalOperatorType getOperatorType() const { return operatorType; } + bool hasUpdateRecursive(); - inline Schema* getSchema() const { return schema.get(); } + // Schema + Schema* getSchema() const { return schema.get(); } virtual void computeFactorizedSchema() = 0; virtual void computeFlatSchema() = 0; + // Printing. virtual std::string getExpressionsForPrinting() const = 0; - // Print the sub-plan rooted at this operator. virtual std::string toString(uint64_t depth = 0) const; @@ -103,8 +104,8 @@ class LogicalOperator { static logical_op_vector_t copy(const logical_op_vector_t& ops); protected: - inline void createEmptySchema() { schema = std::make_unique(); } - inline void copyChildSchema(uint32_t idx) { schema = children[idx]->getSchema()->copy(); } + void createEmptySchema() { schema = std::make_unique(); } + void copyChildSchema(uint32_t idx) { schema = children[idx]->getSchema()->copy(); } protected: LogicalOperatorType operatorType; diff --git a/src/include/planner/operator/logical_order_by.h b/src/include/planner/operator/logical_order_by.h index 9331bc5399c..783ccf8aba8 100644 --- a/src/include/planner/operator/logical_order_by.h +++ b/src/include/planner/operator/logical_order_by.h @@ -10,8 +10,8 @@ class LogicalOrderBy : public LogicalOperator { LogicalOrderBy(binder::expression_vector expressionsToOrderBy, std::vector sortOrders, std::shared_ptr child) : LogicalOperator{LogicalOperatorType::ORDER_BY, std::move(child)}, - expressionsToOrderBy{std::move(expressionsToOrderBy)}, isAscOrders{ - std::move(sortOrders)} {} + expressionsToOrderBy{std::move(expressionsToOrderBy)}, + isAscOrders{std::move(sortOrders)} {} f_group_pos_set getGroupsPosToFlatten(); diff --git a/src/include/planner/operator/logical_partitioner.h b/src/include/planner/operator/logical_partitioner.h index b6dac4b7eb5..4f5c3723224 100644 --- a/src/include/planner/operator/logical_partitioner.h +++ b/src/include/planner/operator/logical_partitioner.h @@ -34,8 +34,8 @@ class LogicalPartitioner : public LogicalOperator { public: LogicalPartitioner(std::vector> infos, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::PARTITIONER, std::move(child)}, infos{std::move( - infos)} {} + : LogicalOperator{LogicalOperatorType::PARTITIONER, std::move(child)}, + infos{std::move(infos)} {} void computeFactorizedSchema() final; void computeFlatSchema() final; @@ -49,8 +49,8 @@ class LogicalPartitioner : public LogicalOperator { } inline std::unique_ptr copy() final { - return make_unique( - LogicalPartitionerInfo::copy(infos), children[0]->copy()); + return make_unique(LogicalPartitionerInfo::copy(infos), + children[0]->copy()); } private: diff --git a/src/include/planner/operator/logical_plan.h b/src/include/planner/operator/logical_plan.h index 8948e01382e..40ae4c15a15 100644 --- a/src/include/planner/operator/logical_plan.h +++ b/src/include/planner/operator/logical_plan.h @@ -1,6 +1,5 @@ #pragma once -#include "logical_explain.h" #include "logical_operator.h" namespace kuzu { @@ -13,28 +12,23 @@ class LogicalPlan { public: LogicalPlan() : estCardinality{1}, cost{0} {} - inline void setLastOperator(std::shared_ptr op) { - lastOperator = std::move(op); - } + void setLastOperator(std::shared_ptr op) { lastOperator = std::move(op); } - inline bool isEmpty() const { return lastOperator == nullptr; } + bool isEmpty() const { return lastOperator == nullptr; } - inline std::shared_ptr getLastOperator() const { return lastOperator; } - inline Schema* getSchema() const { return lastOperator->getSchema(); } + std::shared_ptr getLastOperator() const { return lastOperator; } + Schema* getSchema() const { return lastOperator->getSchema(); } - inline void setCardinality(uint64_t cardinality) { estCardinality = cardinality; } - inline uint64_t getCardinality() const { return estCardinality; } + void setCardinality(uint64_t cardinality) { estCardinality = cardinality; } + uint64_t getCardinality() const { return estCardinality; } - inline void setCost(uint64_t cost_) { cost = cost_; } - inline uint64_t getCost() const { return cost; } + void setCost(uint64_t cost_) { cost = cost_; } + uint64_t getCost() const { return cost; } - inline std::string toString() const { return lastOperator->toString(); } + std::string toString() const { return lastOperator->toString(); } - inline bool isProfile() const { - return lastOperator->getOperatorType() == LogicalOperatorType::EXPLAIN && - reinterpret_cast(lastOperator.get())->getExplainType() == - common::ExplainType::PROFILE; - } + bool isProfile() const; + bool hasUpdate() const; std::unique_ptr shallowCopy() const; diff --git a/src/include/planner/operator/logical_projection.h b/src/include/planner/operator/logical_projection.h index ac0b7428694..1c68cfda921 100644 --- a/src/include/planner/operator/logical_projection.h +++ b/src/include/planner/operator/logical_projection.h @@ -9,10 +9,10 @@ namespace planner { class LogicalProjection : public LogicalOperator { public: - explicit LogicalProjection( - binder::expression_vector expressions, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::PROJECTION, std::move(child)}, expressions{std::move( - expressions)} {} + explicit LogicalProjection(binder::expression_vector expressions, + std::shared_ptr child) + : LogicalOperator{LogicalOperatorType::PROJECTION, std::move(child)}, + expressions{std::move(expressions)} {} void computeFactorizedSchema() override; void computeFlatSchema() override; diff --git a/src/include/planner/operator/logical_union.h b/src/include/planner/operator/logical_union.h index a7269fb7b9e..32e7f5871af 100644 --- a/src/include/planner/operator/logical_union.h +++ b/src/include/planner/operator/logical_union.h @@ -9,8 +9,8 @@ class LogicalUnion : public LogicalOperator { public: LogicalUnion(binder::expression_vector expressions, const std::vector>& children) - : LogicalOperator{LogicalOperatorType::UNION_ALL, children}, expressionsToUnion{ - std::move(expressions)} {} + : LogicalOperator{LogicalOperatorType::UNION_ALL, children}, + expressionsToUnion{std::move(expressions)} {} f_group_pos_set getGroupsPosToFlatten(uint32_t childIdx); diff --git a/src/include/planner/operator/logical_unwind.h b/src/include/planner/operator/logical_unwind.h index 34a9b3d8a5e..ce3387caa6c 100644 --- a/src/include/planner/operator/logical_unwind.h +++ b/src/include/planner/operator/logical_unwind.h @@ -7,32 +7,32 @@ namespace planner { class LogicalUnwind : public LogicalOperator { public: - LogicalUnwind(std::shared_ptr expression, - std::shared_ptr aliasExpression, + LogicalUnwind(std::shared_ptr inExpr, + std::shared_ptr outExpr, std::shared_ptr idExpr, std::shared_ptr childOperator) : LogicalOperator{LogicalOperatorType::UNWIND, std::move(childOperator)}, - expression{std::move(expression)}, aliasExpression{std::move(aliasExpression)} {} + inExpr{std::move(inExpr)}, outExpr{std::move(outExpr)}, idExpr{std::move(idExpr)} {} f_group_pos_set getGroupsPosToFlatten(); void computeFactorizedSchema() override; void computeFlatSchema() override; - inline std::shared_ptr getExpression() { return expression; } + std::shared_ptr getInExpr() const { return inExpr; } + std::shared_ptr getOutExpr() const { return outExpr; } + bool hasIDExpr() const { return idExpr != nullptr; } + std::shared_ptr getIDExpr() const { return idExpr; } - inline std::shared_ptr getAliasExpression() { return aliasExpression; } + std::string getExpressionsForPrinting() const override { return inExpr->toString(); } - inline std::string getExpressionsForPrinting() const override { - return expression->getUniqueName(); - } - - inline std::unique_ptr copy() override { - return make_unique(expression, aliasExpression, children[0]->copy()); + std::unique_ptr copy() override { + return make_unique(inExpr, outExpr, idExpr, children[0]->copy()); } private: - std::shared_ptr expression; - std::shared_ptr aliasExpression; + std::shared_ptr inExpr; + std::shared_ptr outExpr; + std::shared_ptr idExpr; }; } // namespace planner diff --git a/src/include/planner/operator/persistent/logical_copy_to.h b/src/include/planner/operator/persistent/logical_copy_to.h index 4c976a48499..ce0ff8fd79b 100644 --- a/src/include/planner/operator/persistent/logical_copy_to.h +++ b/src/include/planner/operator/persistent/logical_copy_to.h @@ -30,8 +30,8 @@ class LogicalCopyTo : public LogicalOperator { inline const common::CSVOption* getCopyOption() const { return ©ToOption; } inline std::unique_ptr copy() override { - return make_unique( - filePath, fileType, columnNames, columnTypes, copyToOption.copy(), children[0]->copy()); + return make_unique(filePath, fileType, columnNames, columnTypes, + copyToOption.copy(), children[0]->copy()); } private: diff --git a/src/include/planner/operator/persistent/logical_delete.h b/src/include/planner/operator/persistent/logical_delete.h index f2089216977..2bef3bbc64a 100644 --- a/src/include/planner/operator/persistent/logical_delete.h +++ b/src/include/planner/operator/persistent/logical_delete.h @@ -11,8 +11,8 @@ struct LogicalDeleteNodeInfo { std::shared_ptr node; common::DeleteNodeType deleteType; - LogicalDeleteNodeInfo( - std::shared_ptr node, common::DeleteNodeType deleteType) + LogicalDeleteNodeInfo(std::shared_ptr node, + common::DeleteNodeType deleteType) : node{std::move(node)}, deleteType{deleteType} {} inline std::unique_ptr copy() const { @@ -27,8 +27,8 @@ class LogicalDeleteNode : public LogicalOperator { public: LogicalDeleteNode(std::vector> infos, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::DELETE_NODE, std::move(child)}, infos{std::move( - infos)} {} + : LogicalOperator{LogicalOperatorType::DELETE_NODE, std::move(child)}, + infos{std::move(infos)} {} inline void computeFactorizedSchema() final { copyChildSchema(0); } inline void computeFlatSchema() final { copyChildSchema(0); } @@ -47,8 +47,8 @@ class LogicalDeleteNode : public LogicalOperator { f_group_pos_set getGroupsPosToFlatten(); inline std::unique_ptr copy() final { - return std::make_unique( - LogicalDeleteNodeInfo::copy(infos), children[0]->copy()); + return std::make_unique(LogicalDeleteNodeInfo::copy(infos), + children[0]->copy()); } private: @@ -59,8 +59,8 @@ class LogicalDeleteRel : public LogicalOperator { public: LogicalDeleteRel(std::vector> rels, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::DELETE_REL, std::move(child)}, rels{std::move( - rels)} {} + : LogicalOperator{LogicalOperatorType::DELETE_REL, std::move(child)}, + rels{std::move(rels)} {} inline void computeFactorizedSchema() final { copyChildSchema(0); } inline void computeFlatSchema() final { copyChildSchema(0); } diff --git a/src/include/planner/operator/persistent/logical_export_db.h b/src/include/planner/operator/persistent/logical_export_db.h index f2f24189cb3..e77e4a0bbff 100644 --- a/src/include/planner/operator/persistent/logical_export_db.h +++ b/src/include/planner/operator/persistent/logical_export_db.h @@ -9,8 +9,8 @@ namespace planner { class LogicalExportDatabase : public LogicalOperator { public: - explicit LogicalExportDatabase( - common::ReaderConfig boundFileInfo, std::vector> plans) + explicit LogicalExportDatabase(common::ReaderConfig boundFileInfo, + std::vector> plans) : LogicalOperator{LogicalOperatorType::EXPORT_DATABASE, std::move(plans)}, boundFileInfo{std::move(boundFileInfo)} {} diff --git a/src/include/planner/operator/persistent/logical_merge.h b/src/include/planner/operator/persistent/logical_merge.h index 93c4f2d9cb9..213ae51173c 100644 --- a/src/include/planner/operator/persistent/logical_merge.h +++ b/src/include/planner/operator/persistent/logical_merge.h @@ -9,7 +9,8 @@ namespace planner { class LogicalMerge : public LogicalOperator { public: - LogicalMerge(std::shared_ptr mark, + LogicalMerge(std::shared_ptr existenceMark, + std::shared_ptr distinctMark, std::vector insertNodeInfos, std::vector insertRelInfos, std::vector> onCreateSetNodeInfos, @@ -17,54 +18,52 @@ class LogicalMerge : public LogicalOperator { std::vector> onMatchSetNodeInfos, std::vector> onMatchSetRelInfos, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::MERGE, std::move(child)}, mark{std::move(mark)}, + : LogicalOperator{LogicalOperatorType::MERGE, std::move(child)}, + existenceMark{std::move(existenceMark)}, distinctMark{std::move(distinctMark)}, insertNodeInfos{std::move(insertNodeInfos)}, insertRelInfos{std::move(insertRelInfos)}, onCreateSetNodeInfos{std::move(onCreateSetNodeInfos)}, onCreateSetRelInfos(std::move(onCreateSetRelInfos)), - onMatchSetNodeInfos{std::move(onMatchSetNodeInfos)}, onMatchSetRelInfos{ - std::move(onMatchSetRelInfos)} {} + onMatchSetNodeInfos{std::move(onMatchSetNodeInfos)}, + onMatchSetRelInfos{std::move(onMatchSetRelInfos)} {} void computeFactorizedSchema() final; void computeFlatSchema() final; - inline std::string getExpressionsForPrinting() const final { return std::string(""); } + std::string getExpressionsForPrinting() const final { return {}; } f_group_pos_set getGroupsPosToFlatten(); - inline std::shared_ptr getMark() const { return mark; } - inline const std::vector& getInsertNodeInfosRef() const { - return insertNodeInfos; - } - inline const std::vector& getInsertRelInfosRef() const { - return insertRelInfos; - } - inline const std::vector>& - getOnCreateSetNodeInfosRef() const { + std::shared_ptr getExistenceMark() const { return existenceMark; } + bool hasDistinctMark() const { return distinctMark != nullptr; } + std::shared_ptr getDistinctMark() const { return distinctMark; } + + const std::vector& getInsertNodeInfosRef() const { return insertNodeInfos; } + const std::vector& getInsertRelInfosRef() const { return insertRelInfos; } + const std::vector>& getOnCreateSetNodeInfosRef() const { return onCreateSetNodeInfos; } - inline const std::vector>& - getOnCreateSetRelInfosRef() const { + const std::vector>& getOnCreateSetRelInfosRef() const { return onCreateSetRelInfos; } - inline const std::vector>& - getOnMatchSetNodeInfosRef() const { + const std::vector>& getOnMatchSetNodeInfosRef() const { return onMatchSetNodeInfos; } - inline const std::vector>& - getOnMatchSetRelInfosRef() const { + const std::vector>& getOnMatchSetRelInfosRef() const { return onMatchSetRelInfos; } - inline std::unique_ptr copy() final { - return std::make_unique(mark, copyVector(insertNodeInfos), - copyVector(insertRelInfos), LogicalSetPropertyInfo::copy(onCreateSetNodeInfos), + std::unique_ptr copy() final { + return std::make_unique(existenceMark, distinctMark, + copyVector(insertNodeInfos), copyVector(insertRelInfos), + LogicalSetPropertyInfo::copy(onCreateSetNodeInfos), LogicalSetPropertyInfo::copy(onCreateSetRelInfos), LogicalSetPropertyInfo::copy(onMatchSetNodeInfos), LogicalSetPropertyInfo::copy(onMatchSetRelInfos), children[0]->copy()); } private: - std::shared_ptr mark; + std::shared_ptr existenceMark; + std::shared_ptr distinctMark; // Create infos std::vector insertNodeInfos; std::vector insertRelInfos; diff --git a/src/include/planner/operator/persistent/logical_set.h b/src/include/planner/operator/persistent/logical_set.h index 48860a83608..ab2455dd864 100644 --- a/src/include/planner/operator/persistent/logical_set.h +++ b/src/include/planner/operator/persistent/logical_set.h @@ -9,8 +9,8 @@ struct LogicalSetPropertyInfo { std::shared_ptr nodeOrRel; binder::expression_pair setItem; - LogicalSetPropertyInfo( - std::shared_ptr nodeOrRel, binder::expression_pair setItem) + LogicalSetPropertyInfo(std::shared_ptr nodeOrRel, + binder::expression_pair setItem) : nodeOrRel{std::move(nodeOrRel)}, setItem{std::move(setItem)} {} LogicalSetPropertyInfo(const LogicalSetPropertyInfo& other) : nodeOrRel{other.nodeOrRel}, setItem{other.setItem} {} @@ -42,8 +42,8 @@ class LogicalSetNodeProperty : public LogicalOperator { std::string getExpressionsForPrinting() const final; inline std::unique_ptr copy() final { - return std::make_unique( - LogicalSetPropertyInfo::copy(infos), children[0]->copy()); + return std::make_unique(LogicalSetPropertyInfo::copy(infos), + children[0]->copy()); } private: @@ -54,8 +54,8 @@ class LogicalSetRelProperty : public LogicalOperator { public: LogicalSetRelProperty(std::vector> infos, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::SET_REL_PROPERTY, std::move(child)}, infos{std::move( - infos)} {} + : LogicalOperator{LogicalOperatorType::SET_REL_PROPERTY, std::move(child)}, + infos{std::move(infos)} {} inline void computeFactorizedSchema() final { copyChildSchema(0); } inline void computeFlatSchema() final { copyChildSchema(0); } @@ -69,8 +69,8 @@ class LogicalSetRelProperty : public LogicalOperator { std::string getExpressionsForPrinting() const final; inline std::unique_ptr copy() final { - return std::make_unique( - LogicalSetPropertyInfo::copy(infos), children[0]->copy()); + return std::make_unique(LogicalSetPropertyInfo::copy(infos), + children[0]->copy()); } private: diff --git a/src/include/planner/operator/scan/logical_expressions_scan.h b/src/include/planner/operator/scan/logical_expressions_scan.h index 90633964c3e..326ac96ef06 100644 --- a/src/include/planner/operator/scan/logical_expressions_scan.h +++ b/src/include/planner/operator/scan/logical_expressions_scan.h @@ -10,8 +10,8 @@ namespace planner { class LogicalExpressionsScan : public LogicalOperator { public: explicit LogicalExpressionsScan(binder::expression_vector expressions) - : LogicalOperator{LogicalOperatorType::EXPRESSIONS_SCAN}, expressions{ - std::move(expressions)} {} + : LogicalOperator{LogicalOperatorType::EXPRESSIONS_SCAN}, + expressions{std::move(expressions)} {} inline void computeFactorizedSchema() final { computeSchema(); } inline void computeFlatSchema() final { computeSchema(); } diff --git a/src/include/planner/operator/scan/logical_index_scan.h b/src/include/planner/operator/scan/logical_index_scan.h index 87a84bbe825..06b61ac239d 100644 --- a/src/include/planner/operator/scan/logical_index_scan.h +++ b/src/include/planner/operator/scan/logical_index_scan.h @@ -8,10 +8,10 @@ namespace planner { class LogicalIndexScanNode : public LogicalOperator { public: - LogicalIndexScanNode( - std::vector infos, std::shared_ptr child) - : LogicalOperator{LogicalOperatorType::INDEX_SCAN_NODE, std::move(child)}, infos{std::move( - infos)} {} + LogicalIndexScanNode(std::vector infos, + std::shared_ptr child) + : LogicalOperator{LogicalOperatorType::INDEX_SCAN_NODE, std::move(child)}, + infos{std::move(infos)} {} void computeFactorizedSchema() override; void computeFlatSchema() override; diff --git a/src/include/planner/operator/scan/logical_scan_file.h b/src/include/planner/operator/scan/logical_scan_file.h index cc7c4ed134d..e3ab967ad08 100644 --- a/src/include/planner/operator/scan/logical_scan_file.h +++ b/src/include/planner/operator/scan/logical_scan_file.h @@ -8,22 +8,28 @@ namespace planner { class LogicalScanFile : public LogicalOperator { public: - explicit LogicalScanFile(binder::BoundFileScanInfo info) - : LogicalOperator{LogicalOperatorType::SCAN_FILE}, info{std::move(info)} {} + LogicalScanFile(binder::BoundFileScanInfo info, std::shared_ptr offset) + : LogicalOperator{LogicalOperatorType::SCAN_FILE}, info{std::move(info)}, + offset{std::move(offset)} {} - inline std::string getExpressionsForPrinting() const override { return std::string(); } + std::string getExpressionsForPrinting() const override { return std::string(); } - inline const binder::BoundFileScanInfo* getInfo() const { return &info; } + const binder::BoundFileScanInfo* getInfo() const { return &info; } + bool hasOffset() const { return offset != nullptr; } + std::shared_ptr getOffset() const { return offset; } void computeFactorizedSchema() final; void computeFlatSchema() final; - inline std::unique_ptr copy() final { - return std::make_unique(info.copy()); + std::unique_ptr copy() final { + return std::make_unique(info.copy(), offset); } private: binder::BoundFileScanInfo info; + // ScanFile may be used as a source operator for COPY pipeline. In such case, row offset needs + // to be provided in order to generate internal ID. + std::shared_ptr offset; }; } // namespace planner diff --git a/src/include/planner/operator/scan/logical_scan_internal_id.h b/src/include/planner/operator/scan/logical_scan_internal_id.h index f069196306c..38099ab1d2c 100644 --- a/src/include/planner/operator/scan/logical_scan_internal_id.h +++ b/src/include/planner/operator/scan/logical_scan_internal_id.h @@ -7,10 +7,10 @@ namespace planner { class LogicalScanInternalID : public LogicalOperator { public: - explicit LogicalScanInternalID( - std::shared_ptr internalID, std::vector tableIDs) - : LogicalOperator{LogicalOperatorType::SCAN_INTERNAL_ID}, - internalID{std::move(internalID)}, tableIDs{std::move(tableIDs)} {} + explicit LogicalScanInternalID(std::shared_ptr internalID, + std::vector tableIDs) + : LogicalOperator{LogicalOperatorType::SCAN_INTERNAL_ID}, internalID{std::move(internalID)}, + tableIDs{std::move(tableIDs)} {} void computeFactorizedSchema() final; void computeFlatSchema() final; diff --git a/src/include/planner/operator/scan/logical_scan_node_property.h b/src/include/planner/operator/scan/logical_scan_node_property.h index 958a1d14712..d6926ce2096 100644 --- a/src/include/planner/operator/scan/logical_scan_node_property.h +++ b/src/include/planner/operator/scan/logical_scan_node_property.h @@ -12,8 +12,8 @@ class LogicalScanNodeProperty : public LogicalOperator { std::vector nodeTableIDs, binder::expression_vector properties, std::shared_ptr child) : LogicalOperator{LogicalOperatorType::SCAN_NODE_PROPERTY, std::move(child)}, - nodeID{std::move(nodeID)}, nodeTableIDs{std::move(nodeTableIDs)}, properties{std::move( - properties)} {} + nodeID{std::move(nodeID)}, nodeTableIDs{std::move(nodeTableIDs)}, + properties{std::move(properties)} {} void computeFactorizedSchema() final; void computeFlatSchema() final; @@ -27,8 +27,8 @@ class LogicalScanNodeProperty : public LogicalOperator { inline binder::expression_vector getProperties() const { return properties; } inline std::unique_ptr copy() final { - return make_unique( - nodeID, nodeTableIDs, properties, children[0]->copy()); + return make_unique(nodeID, nodeTableIDs, properties, + children[0]->copy()); } private: diff --git a/src/include/planner/operator/schema.h b/src/include/planner/operator/schema.h index 4597e780201..eaaadf7ba28 100644 --- a/src/include/planner/operator/schema.h +++ b/src/include/planner/operator/schema.h @@ -76,14 +76,14 @@ class Schema { f_group_pos createGroup(); void insertToScope(const std::shared_ptr& expression, uint32_t groupPos); - void insertToGroupAndScope( - const std::shared_ptr& expression, uint32_t groupPos); + void insertToGroupAndScope(const std::shared_ptr& expression, + uint32_t groupPos); // Use these unsafe insert functions only if the operator may work with duplicate expressions. // E.g. group by a.age, a.age - void insertToScopeMayRepeat( - const std::shared_ptr& expression, uint32_t groupPos); - void insertToGroupAndScopeMayRepeat( - const std::shared_ptr& expression, uint32_t groupPos); + void insertToScopeMayRepeat(const std::shared_ptr& expression, + uint32_t groupPos); + void insertToGroupAndScopeMayRepeat(const std::shared_ptr& expression, + uint32_t groupPos); void insertToGroupAndScope(const binder::expression_vector& expressions, uint32_t groupPos); @@ -142,13 +142,13 @@ class SchemaUtils { // Given a set of factorization group, a leading group is selected as the unFlat group (caller // should ensure at most one unFlat group which is our general assumption of factorization). If // all groups are flat, we select any (the first) group as leading group. - static f_group_pos getLeadingGroupPos( - const std::unordered_set& groupPositions, const Schema& schema); + static f_group_pos getLeadingGroupPos(const std::unordered_set& groupPositions, + const Schema& schema); - static void validateAtMostOneUnFlatGroup( - const std::unordered_set& groupPositions, const Schema& schema); - static void validateNoUnFlatGroup( - const std::unordered_set& groupPositions, const Schema& schema); + static void validateAtMostOneUnFlatGroup(const std::unordered_set& groupPositions, + const Schema& schema); + static void validateNoUnFlatGroup(const std::unordered_set& groupPositions, + const Schema& schema); }; } // namespace planner diff --git a/src/include/planner/planner.h b/src/include/planner/planner.h index 48448695bc7..248d7fb29b3 100644 --- a/src/include/planner/planner.h +++ b/src/include/planner/planner.h @@ -32,7 +32,7 @@ struct LogicalSetPropertyInfo; class Planner { public: - Planner(catalog::Catalog* catalog, storage::StorageManager* storageManager); + explicit Planner(main::ClientContext* clientContext); DELETE_COPY_AND_MOVE(Planner); std::unique_ptr getBestPlan(const binder::BoundStatement& statement); @@ -50,20 +50,22 @@ class Planner { void appendCreateMacro(const binder::BoundStatement& statement, LogicalPlan& plan); void appendTransaction(const binder::BoundStatement& statement, LogicalPlan& plan); void appendExtension(const binder::BoundStatement& statement, LogicalPlan& plan); + void appendAttachDatabase(const binder::BoundStatement& statement, LogicalPlan& plan); + void appendDetachDatabase(const binder::BoundStatement& statement, LogicalPlan& plan); // Plan copy. std::unique_ptr planCopyTo(const binder::BoundStatement& statement); std::unique_ptr planCopyFrom(const binder::BoundStatement& statement); - std::unique_ptr planCopyNodeFrom( - const binder::BoundCopyFromInfo* info, binder::expression_vector outExprs); - std::unique_ptr planCopyResourceFrom( - const binder::BoundCopyFromInfo* info, binder::expression_vector results); - std::unique_ptr planCopyRelFrom( - const binder::BoundCopyFromInfo* info, binder::expression_vector outExprs); - std::unique_ptr planCopyRdfFrom( - const binder::BoundCopyFromInfo* info, binder::expression_vector outExprs); - - // Plan export database + std::unique_ptr planCopyNodeFrom(const binder::BoundCopyFromInfo* info, + binder::expression_vector outExprs); + std::unique_ptr planCopyResourceFrom(const binder::BoundCopyFromInfo* info, + binder::expression_vector results); + std::unique_ptr planCopyRelFrom(const binder::BoundCopyFromInfo* info, + binder::expression_vector outExprs); + std::unique_ptr planCopyRdfFrom(const binder::BoundCopyFromInfo* info, + binder::expression_vector outExprs); + + // Plan export/import database std::unique_ptr planExportDatabase(const binder::BoundStatement& statement); std::unique_ptr planImportDatabase(const binder::BoundStatement& statement); @@ -109,12 +111,17 @@ class Planner { // Plan subquery void planOptionalMatch(const binder::QueryGraphCollection& queryGraphCollection, - const binder::expression_vector& predicates, LogicalPlan& leftPlan); + const binder::expression_vector& predicates, const binder::expression_vector& corrExprs, + LogicalPlan& leftPlan); void planRegularMatch(const binder::QueryGraphCollection& queryGraphCollection, const binder::expression_vector& predicates, LogicalPlan& leftPlan); void planSubquery(const std::shared_ptr& subquery, LogicalPlan& outerPlan); - void planSubqueryIfNecessary( - const std::shared_ptr& expression, LogicalPlan& plan); + void planSubqueryIfNecessary(const std::shared_ptr& expression, + LogicalPlan& plan); + + static binder::expression_vector getCorrelatedExprs( + const binder::QueryGraphCollection& collection, const binder::expression_vector& predicates, + Schema* outerSchema); // Plan query graphs std::unique_ptr planQueryGraphCollection( @@ -132,8 +139,8 @@ class Planner { const binder::QueryGraph& queryGraph, binder::expression_vector& predicates); // Plan node/rel table scan - void planBaseTableScans( - SubqueryType subqueryType, const binder::expression_vector& correlatedExpressions); + void planBaseTableScans(SubqueryType subqueryType, + const binder::expression_vector& correlatedExpressions); void planCorrelatedExpressionsScan(const binder::expression_vector& correlatedExpressions); void planNodeScan(uint32_t nodePos); void planNodeIDScan(uint32_t nodePos); @@ -168,18 +175,18 @@ class Planner { std::vector> rightPlans); // Append updating operators - void appendInsertNode( - const std::vector& boundInsertInfos, LogicalPlan& plan); - void appendInsertRel( - const std::vector& boundInsertInfos, LogicalPlan& plan); - void appendSetNodeProperty( - const std::vector& boundInfos, LogicalPlan& plan); - void appendSetRelProperty( - const std::vector& boundInfos, LogicalPlan& plan); - void appendDeleteNode( - const std::vector& boundInfos, LogicalPlan& plan); - void appendDeleteRel( - const std::vector& boundInfos, LogicalPlan& plan); + void appendInsertNode(const std::vector& boundInsertInfos, + LogicalPlan& plan); + void appendInsertRel(const std::vector& boundInsertInfos, + LogicalPlan& plan); + void appendSetNodeProperty(const std::vector& boundInfos, + LogicalPlan& plan); + void appendSetRelProperty(const std::vector& boundInfos, + LogicalPlan& plan); + void appendDeleteNode(const std::vector& boundInfos, + LogicalPlan& plan); + void appendDeleteRel(const std::vector& boundInfos, + LogicalPlan& plan); std::unique_ptr createLogicalInsertInfo(const binder::BoundInsertInfo* info); std::unique_ptr createLogicalSetPropertyInfo( const binder::BoundSetPropertyInfo* boundSetPropertyInfo); @@ -210,8 +217,8 @@ class Planner { const std::shared_ptr& nbrNode, const std::shared_ptr& rel, ExtendDirection direction, LogicalPlan& plan); - void createRecursivePlan( - const binder::RecursiveInfo& recursiveInfo, ExtendDirection direction, LogicalPlan& plan); + void createRecursivePlan(const binder::RecursiveInfo& recursiveInfo, ExtendDirection direction, + LogicalPlan& plan); void createPathNodePropertyScanPlan(const std::shared_ptr& node, const binder::expression_vector& properties, LogicalPlan& plan); void createPathRelPropertyScanPlan(const std::shared_ptr& boundNode, @@ -223,7 +230,7 @@ class Planner { // Append Join operators void appendHashJoin(const binder::expression_vector& joinNodeIDs, common::JoinType joinType, - LogicalPlan& probePlan, LogicalPlan& buildPlan); + LogicalPlan& probePlan, LogicalPlan& buildPlan, LogicalPlan& resultPlan); void appendMarkJoin(const binder::expression_vector& joinNodeIDs, const std::shared_ptr& mark, LogicalPlan& probePlan, LogicalPlan& buildPlan); @@ -231,14 +238,21 @@ class Planner { binder::expression_vector& boundNodeIDs, LogicalPlan& probePlan, std::vector>& buildPlans); - void appendCrossProduct( - common::AccumulateType accumulateType, LogicalPlan& probePlan, LogicalPlan& buildPlan); + void appendCrossProduct(common::AccumulateType accumulateType, const LogicalPlan& probePlan, + const LogicalPlan& buildPlan, LogicalPlan& resultPlan); - inline void appendAccumulate(common::AccumulateType accumulateType, LogicalPlan& plan) { - appendAccumulate(accumulateType, binder::expression_vector{}, plan); - } + // Append accumulate + void appendAccumulate(common::AccumulateType accumulateType, LogicalPlan& plan); + // Append accumulate with a set of expressions being flattened first. + void appendAccumulate(common::AccumulateType accumulateType, + const binder::expression_vector& flatExprs, LogicalPlan& plan); + // Append accumulate with a set of expressions being flattened first. + // Additionally, scan table with row offset. void appendAccumulate(common::AccumulateType accumulateType, - const binder::expression_vector& expressionsToFlatten, LogicalPlan& plan); + const binder::expression_vector& flatExprs, std::shared_ptr offset, + LogicalPlan& plan); + void appendMarkAccumulate(const binder::expression_vector& keys, + std::shared_ptr mark, LogicalPlan& plan); void appendDummyScan(LogicalPlan& plan); @@ -252,9 +266,13 @@ class Planner { void appendFilters(const binder::expression_vector& predicates, LogicalPlan& plan); void appendFilter(const std::shared_ptr& predicate, LogicalPlan& plan); - void appendScanFile(const binder::BoundFileScanInfo* fileScanInfo, LogicalPlan& plan); + // Append scan file. + void appendScanFile(const binder::BoundFileScanInfo* info, LogicalPlan& plan); + // Append scan file. Additionally, scan row offset. + void appendScanFile(const binder::BoundFileScanInfo* info, + std::shared_ptr offset, LogicalPlan& plan); - void appendDistinct(const binder::expression_vector& expressionsToDistinct, LogicalPlan& plan); + void appendDistinct(const binder::expression_vector& keys, LogicalPlan& plan); std::unique_ptr createUnionPlan( std::vector>& childrenPlans, bool isUnionAll); @@ -269,8 +287,7 @@ class Planner { void exitContext(JoinOrderEnumeratorContext prevContext); private: - catalog::Catalog* catalog; - storage::StorageManager* storageManager; + main::ClientContext* clientContext; binder::expression_vector propertiesToScan; CardinalityEstimator cardinalityEstimator; JoinOrderEnumeratorContext context; diff --git a/src/include/processor/operator/aggregate/aggregate_hash_table.h b/src/include/processor/operator/aggregate/aggregate_hash_table.h index fb39e8f7147..e918621d47e 100644 --- a/src/include/processor/operator/aggregate/aggregate_hash_table.h +++ b/src/include/processor/operator/aggregate/aggregate_hash_table.h @@ -2,7 +2,7 @@ #include "aggregate_input.h" #include "function/aggregate_function.h" -#include "processor/operator/base_hash_table.h" +#include "processor/result/base_hash_table.h" #include "storage/buffer_manager/memory_manager.h" namespace kuzu { @@ -14,6 +14,8 @@ struct HashSlot { // groupKeyN, aggregateState1, ..., aggregateStateN, hashValue]. }; +enum class HashTableType : uint8_t { AGGREGATE_HASH_TABLE = 0, MARK_HASH_TABLE = 1 }; + /** * AggregateHashTable Design * @@ -31,7 +33,6 @@ struct HashSlot { * */ class AggregateHashTable; -using compare_function_t = std::function; using update_agg_function_t = std::function&, const std::vector&, std::unique_ptr&, @@ -41,25 +42,25 @@ class AggregateHashTable : public BaseHashTable { public: // Used by distinct aggregate hash table only. AggregateHashTable(storage::MemoryManager& memoryManager, - const std::vector& keysDataTypes, + const common::logical_type_vec_t& keysDataTypes, const std::vector>& aggregateFunctions, - uint64_t numEntriesToAllocate) + uint64_t numEntriesToAllocate, std::unique_ptr tableSchema) : AggregateHashTable(memoryManager, keysDataTypes, std::vector(), - aggregateFunctions, numEntriesToAllocate) {} + aggregateFunctions, numEntriesToAllocate, std::move(tableSchema)) {} AggregateHashTable(storage::MemoryManager& memoryManager, std::vector keysDataTypes, std::vector payloadsDataTypes, const std::vector>& aggregateFunctions, - uint64_t numEntriesToAllocate); + uint64_t numEntriesToAllocate, std::unique_ptr tableSchema); - inline uint8_t* getEntry(uint64_t idx) { return factorizedTable->getTuple(idx); } + uint8_t* getEntry(uint64_t idx) { return factorizedTable->getTuple(idx); } - inline FactorizedTable* getFactorizedTable() { return factorizedTable.get(); } + FactorizedTable* getFactorizedTable() { return factorizedTable.get(); } - inline uint64_t getNumEntries() const { return factorizedTable->getNumTuples(); } + uint64_t getNumEntries() const { return factorizedTable->getNumTuples(); } - inline void append(const std::vector& flatKeyVectors, + void append(const std::vector& flatKeyVectors, const std::vector& unFlatKeyVectors, common::DataChunkState* leadingState, const std::vector>& aggregateInputs, @@ -87,12 +88,26 @@ class AggregateHashTable : public BaseHashTable { void resize(uint64_t newSize); - static void getCompareEntryWithKeysFunc( - const common::LogicalType& logicalType, compare_function_t& func); +protected: + virtual uint64_t matchFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, uint64_t numMayMatches, + uint64_t numNoMatches); + + virtual void initializeFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, + const std::vector& dependentKeyVectors, + uint64_t numFTEntriesToInitialize); + + uint64_t matchUnFlatVecWithFTColumn(common::ValueVector* vector, uint64_t numMayMatches, + uint64_t& numNoMatches, uint32_t colIdx); + + uint64_t matchFlatVecWithFTColumn(common::ValueVector* vector, uint64_t numMayMatches, + uint64_t& numNoMatches, uint32_t colIdx); private: void initializeFT( - const std::vector>& aggregateFunctions); + const std::vector>& aggregateFunctions, + std::unique_ptr tableSchema); void initializeHashTable(uint64_t numEntriesToAllocate); @@ -100,22 +115,17 @@ class AggregateHashTable : public BaseHashTable { // ! This function will only be used by distinct aggregate, which assumes that all groupByKeys // are flat. - uint8_t* findEntryInDistinctHT( - const std::vector& groupByKeyVectors, common::hash_t hash); + uint8_t* findEntryInDistinctHT(const std::vector& groupByKeyVectors, + common::hash_t hash); - void initializeFTEntryWithFlatVec( - common::ValueVector* flatVector, uint64_t numEntriesToInitialize, uint32_t colIdx); + void initializeFTEntryWithFlatVec(common::ValueVector* flatVector, + uint64_t numEntriesToInitialize, uint32_t colIdx); - void initializeFTEntryWithUnFlatVec( - common::ValueVector* unFlatVector, uint64_t numEntriesToInitialize, uint32_t colIdx); + void initializeFTEntryWithUnFlatVec(common::ValueVector* unFlatVector, + uint64_t numEntriesToInitialize, uint32_t colIdx); - void initializeFTEntries(const std::vector& flatKeyVectors, - const std::vector& unFlatKeyVectors, - const std::vector& dependentKeyVectors, - uint64_t numFTEntriesToInitialize); - - uint8_t* createEntryInDistinctHT( - const std::vector& groupByHashKeyVectors, common::hash_t hash); + uint8_t* createEntryInDistinctHT(const std::vector& groupByHashKeyVectors, + common::hash_t hash); void increaseSlotIdx(uint64_t& slotIdx) const; @@ -128,11 +138,6 @@ class AggregateHashTable : public BaseHashTable { const std::vector& dependentKeyVectors, common::DataChunkState* leadingState); - void computeAndCombineVecHash( - const std::vector& unFlatKeyVectors, uint32_t startVecIdx); - void computeVectorHashes(const std::vector& flatKeyVectors, - const std::vector& unFlatKeyVectors); - void updateDistinctAggState(const std::vector& flatKeyVectors, const std::vector& unFlatKeyVectors, std::unique_ptr& aggregateFunction, @@ -154,16 +159,6 @@ class AggregateHashTable : public BaseHashTable { // are flat. bool matchFlatGroupByKeys(const std::vector& keyVectors, uint8_t* entry); - uint64_t matchUnFlatVecWithFTColumn(common::ValueVector* vector, uint64_t numMayMatches, - uint64_t& numNoMatches, uint32_t colIdx); - - uint64_t matchFlatVecWithFTColumn(common::ValueVector* vector, uint64_t numMayMatches, - uint64_t& numNoMatches, uint32_t colIdx); - - uint64_t matchFTEntries(const std::vector& flatKeyVectors, - const std::vector& unFlatKeyVectors, uint64_t numMayMatches, - uint64_t numNoMatches); - void fillEntryWithInitialNullAggregateState(uint8_t* entry); //! find an uninitialized hash slot for given hash and fill hash slot with block id and offset @@ -214,29 +209,27 @@ class AggregateHashTable : public BaseHashTable { std::unique_ptr& aggregateFunction, common::ValueVector* aggVector, uint64_t multiplicity, uint32_t aggStateOffset); +protected: + uint32_t hashColIdxInFT; + std::unique_ptr mayMatchIdxes; + std::unique_ptr noMatchIdxes; + std::unique_ptr entryIdxesToInitialize; + std::unique_ptr hashSlotsToUpdateAggState; + private: - std::vector keyDataTypes; std::vector dependentKeyDataTypes; std::vector> aggregateFunctions; //! special handling of distinct aggregate std::vector> distinctHashTables; - uint32_t hashColIdxInFT; uint32_t hashColOffsetInFT; uint32_t aggStateColOffsetInFT; uint32_t aggStateColIdxInFT; uint32_t numBytesForKeys = 0; uint32_t numBytesForDependentKeys = 0; - std::vector compareFuncs; std::vector updateAggFuncs; // Temporary arrays to hold intermediate results. - std::shared_ptr hashState; - std::unique_ptr hashVector; - std::unique_ptr hashSlotsToUpdateAggState; std::unique_ptr tmpValueIdxes; - std::unique_ptr entryIdxesToInitialize; - std::unique_ptr mayMatchIdxes; - std::unique_ptr noMatchIdxes; std::unique_ptr tmpSlotIdxes; }; diff --git a/src/include/processor/operator/aggregate/aggregate_input.h b/src/include/processor/operator/aggregate/aggregate_input.h index b391ee7d343..3392c3016e8 100644 --- a/src/include/processor/operator/aggregate/aggregate_input.h +++ b/src/include/processor/operator/aggregate/aggregate_input.h @@ -10,8 +10,8 @@ struct AggregateInputInfo { DataPos aggregateVectorPos; std::vector multiplicityChunksPos; - AggregateInputInfo( - const DataPos& vectorPos, std::vector multiplicityChunksPos) + AggregateInputInfo(const DataPos& vectorPos, + std::vector multiplicityChunksPos) : aggregateVectorPos{vectorPos}, multiplicityChunksPos{std::move(multiplicityChunksPos)} {} AggregateInputInfo(const AggregateInputInfo& other) : AggregateInputInfo(other.aggregateVectorPos, other.multiplicityChunksPos) {} diff --git a/src/include/processor/operator/aggregate/base_aggregate.h b/src/include/processor/operator/aggregate/base_aggregate.h index 65365e45c33..8a1d693ec02 100644 --- a/src/include/processor/operator/aggregate/base_aggregate.h +++ b/src/include/processor/operator/aggregate/base_aggregate.h @@ -30,8 +30,8 @@ class BaseAggregate : public Sink { std::unique_ptr child, uint32_t id, const std::string& paramsString) : Sink{std::move(resultSetDescriptor), PhysicalOperatorType::AGGREGATE, std::move(child), id, paramsString}, - aggregateFunctions{std::move(aggregateFunctions)}, aggregateInputInfos{ - std::move(aggregateInputInfos)} {} + aggregateFunctions{std::move(aggregateFunctions)}, + aggregateInputInfos{std::move(aggregateInputInfos)} {} void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; diff --git a/src/include/processor/operator/aggregate/base_aggregate_scan.h b/src/include/processor/operator/aggregate/base_aggregate_scan.h index f276fc8846f..f9073a3ae2b 100644 --- a/src/include/processor/operator/aggregate/base_aggregate_scan.h +++ b/src/include/processor/operator/aggregate/base_aggregate_scan.h @@ -14,8 +14,8 @@ class BaseAggregateScan : public PhysicalOperator { paramsString}, aggregatesPos{std::move(aggregatesPos)} {} - BaseAggregateScan( - std::vector aggregatesPos, uint32_t id, const std::string& paramsString) + BaseAggregateScan(std::vector aggregatesPos, uint32_t id, + const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::AGGREGATE_SCAN, id, paramsString}, aggregatesPos{std::move(aggregatesPos)} {} @@ -28,8 +28,8 @@ class BaseAggregateScan : public PhysicalOperator { std::unique_ptr clone() override = 0; protected: - void writeAggregateResultToVector( - common::ValueVector& vector, uint64_t pos, function::AggregateState* aggregateState); + void writeAggregateResultToVector(common::ValueVector& vector, uint64_t pos, + function::AggregateState* aggregateState); protected: std::vector aggregatesPos; diff --git a/src/include/processor/operator/aggregate/hash_aggregate.h b/src/include/processor/operator/aggregate/hash_aggregate.h index f8ba2321e77..0f224db67da 100644 --- a/src/include/processor/operator/aggregate/hash_aggregate.h +++ b/src/include/processor/operator/aggregate/hash_aggregate.h @@ -26,23 +26,49 @@ class HashAggregateSharedState final : public BaseAggregateSharedState { FactorizedTable* getFactorizedTable() { return globalAggregateHashTable->getFactorizedTable(); } + uint64_t getCurrentOffset() const { return currentOffset; } + private: std::vector> localAggregateHashTables; std::unique_ptr globalAggregateHashTable; }; +struct HashAggregateInfo { + std::vector flatKeysPos; + std::vector unFlatKeysPos; + std::vector dependentKeysPos; + std::unique_ptr tableSchema; + HashTableType hashTableType; + + HashAggregateInfo(std::vector flatKeysPos, std::vector unFlatKeysPos, + std::vector dependentKeysPos, std::unique_ptr tableSchema, + HashTableType hashTableType); + HashAggregateInfo(const HashAggregateInfo& other); +}; + +struct HashAggregateLocalState { + std::vector flatKeyVectors; + std::vector unFlatKeyVectors; + std::vector dependentKeyVectors; + common::DataChunkState* leadingState; + std::unique_ptr aggregateHashTable; + + void init(ResultSet& resultSet, main::ClientContext* context, HashAggregateInfo& info, + std::vector>& aggregateFunctions); + void append(std::vector>& aggregateInputs, + uint64_t multiplicity) const; +}; + class HashAggregate : public BaseAggregate { public: HashAggregate(std::unique_ptr resultSetDescriptor, - std::shared_ptr sharedState, std::vector flatKeysPos, - std::vector unFlatKeysPos, std::vector dependentKeysPos, + std::shared_ptr sharedState, HashAggregateInfo aggregateInfo, std::vector> aggregateFunctions, std::vector> aggregateInputInfos, std::unique_ptr child, uint32_t id, const std::string& paramsString) : BaseAggregate{std::move(resultSetDescriptor), std::move(aggregateFunctions), std::move(aggregateInputInfos), std::move(child), id, paramsString}, - flatKeysPos{std::move(flatKeysPos)}, unFlatKeysPos{std::move(unFlatKeysPos)}, - dependentKeysPos{std::move(dependentKeysPos)}, sharedState{std::move(sharedState)} {} + aggregateInfo{std::move(aggregateInfo)}, sharedState{std::move(sharedState)} {} void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; @@ -50,24 +76,15 @@ class HashAggregate : public BaseAggregate { void finalize(ExecutionContext* context) override; - inline std::unique_ptr clone() override { - return make_unique(resultSetDescriptor->copy(), sharedState, flatKeysPos, - unFlatKeysPos, dependentKeysPos, cloneAggFunctions(), cloneAggInputInfos(), - children[0]->clone(), id, paramsString); + std::unique_ptr clone() override { + return make_unique(resultSetDescriptor->copy(), sharedState, aggregateInfo, + cloneAggFunctions(), cloneAggInputInfos(), children[0]->clone(), id, paramsString); } private: - std::vector flatKeysPos; - std::vector unFlatKeysPos; - std::vector dependentKeysPos; - - std::vector flatKeyVectors; - std::vector unFlatKeyVectors; - std::vector dependentKeyVectors; - common::DataChunkState* leadingState; - + HashAggregateInfo aggregateInfo; + HashAggregateLocalState localState; std::shared_ptr sharedState; - std::unique_ptr localAggregateHashTable; }; } // namespace processor diff --git a/src/include/processor/operator/aggregate/hash_aggregate_scan.h b/src/include/processor/operator/aggregate/hash_aggregate_scan.h index 00d763e0991..0715bf7b6cb 100644 --- a/src/include/processor/operator/aggregate/hash_aggregate_scan.h +++ b/src/include/processor/operator/aggregate/hash_aggregate_scan.h @@ -12,15 +12,15 @@ class HashAggregateScan : public BaseAggregateScan { std::vector groupByKeyVectorsPos, std::vector aggregatesPos, std::unique_ptr child, uint32_t id, const std::string& paramsString) : BaseAggregateScan{std::move(aggregatesPos), std::move(child), id, paramsString}, - groupByKeyVectorsPos{std::move(groupByKeyVectorsPos)}, sharedState{ - std::move(sharedState)} {} + groupByKeyVectorsPos{std::move(groupByKeyVectorsPos)}, + sharedState{std::move(sharedState)} {} HashAggregateScan(std::shared_ptr sharedState, std::vector groupByKeyVectorsPos, std::vector aggregatesPos, uint32_t id, const std::string& paramsString) : BaseAggregateScan{std::move(aggregatesPos), id, paramsString}, - groupByKeyVectorsPos{std::move(groupByKeyVectorsPos)}, sharedState{ - std::move(sharedState)} {} + groupByKeyVectorsPos{std::move(groupByKeyVectorsPos)}, + sharedState{std::move(sharedState)} {} inline std::shared_ptr getSharedState() const { return sharedState; } @@ -29,10 +29,12 @@ class HashAggregateScan : public BaseAggregateScan { bool getNextTuplesInternal(ExecutionContext* context) override; std::unique_ptr clone() override { - return std::make_unique( - sharedState, groupByKeyVectorsPos, aggregatesPos, id, paramsString); + return std::make_unique(sharedState, groupByKeyVectorsPos, aggregatesPos, + id, paramsString); } + double getProgress(ExecutionContext* context) const override; + private: std::vector groupByKeyVectorsPos; std::vector groupByKeyVectors; diff --git a/src/include/processor/operator/attach_database.h b/src/include/processor/operator/attach_database.h new file mode 100644 index 00000000000..70783998e95 --- /dev/null +++ b/src/include/processor/operator/attach_database.h @@ -0,0 +1,29 @@ +#pragma once + +#include "parser/parsed_data/attach_info.h" +#include "processor/operator/physical_operator.h" + +namespace kuzu { +namespace processor { + +class AttachDatabase final : public PhysicalOperator { +public: + AttachDatabase(parser::AttachInfo attachInfo, uint32_t id, const std::string& paramsString) + : PhysicalOperator{PhysicalOperatorType::ATTACH_DATABASE, id, paramsString}, + attachInfo{std::move(attachInfo)} {} + + bool isSource() const override { return true; } + bool canParallel() const override { return false; } + + bool getNextTuplesInternal(ExecutionContext* context) override; + + std::unique_ptr clone() override { + return std::make_unique(attachInfo, id, paramsString); + } + +private: + parser::AttachInfo attachInfo; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/operator/base_hash_table.h b/src/include/processor/operator/base_hash_table.h deleted file mode 100644 index 4699b32eab6..00000000000 --- a/src/include/processor/operator/base_hash_table.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include "common/utils.h" -#include "processor/result/factorized_table.h" -#include "storage/buffer_manager/memory_manager.h" - -namespace kuzu { -namespace processor { - -class BaseHashTable { -public: - explicit BaseHashTable(storage::MemoryManager& memoryManager) - : maxNumHashSlots{0}, bitmask{0}, numSlotsPerBlockLog2{0}, slotIdxInBlockMask{0}, - memoryManager{memoryManager} {} - - virtual ~BaseHashTable() = default; - -protected: - inline void setMaxNumHashSlots(uint64_t newSize) { - maxNumHashSlots = newSize; - bitmask = maxNumHashSlots - 1; - } - - inline void initSlotConstant(uint64_t numSlotsPerBlock_) { - KU_ASSERT(numSlotsPerBlock_ == common::nextPowerOfTwo(numSlotsPerBlock_)); - numSlotsPerBlock = numSlotsPerBlock_; - numSlotsPerBlockLog2 = std::log2(numSlotsPerBlock); - slotIdxInBlockMask = - common::BitmaskUtils::all1sMaskForLeastSignificantBits(numSlotsPerBlockLog2); - } - - inline uint64_t getSlotIdxForHash(common::hash_t hash) const { return hash & bitmask; } - -protected: - uint64_t maxNumHashSlots; - uint64_t bitmask; - uint64_t numSlotsPerBlock; - uint64_t numSlotsPerBlockLog2; - uint64_t slotIdxInBlockMask; - std::vector> hashSlotsBlocks; - storage::MemoryManager& memoryManager; - std::unique_ptr factorizedTable; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/call/in_query_call.h b/src/include/processor/operator/call/in_query_call.h index 1b3a1047d35..e533223361d 100644 --- a/src/include/processor/operator/call/in_query_call.h +++ b/src/include/processor/operator/call/in_query_call.h @@ -32,7 +32,7 @@ enum class TableScanOutputType : uint8_t { }; struct InQueryCallInfo { - function::TableFunction* function; + function::TableFunction function; std::unique_ptr bindData; std::vector outPosV; DataPos rowOffsetPos; @@ -66,7 +66,7 @@ class InQueryCall : public PhysicalOperator { bool isSource() const override { return true; } - bool canParallel() const override { return info.function->canParallelFunc(); } + bool canParallel() const override { return info.function.canParallelFunc(); } void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; @@ -74,6 +74,8 @@ class InQueryCall : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) override; + double getProgress(ExecutionContext* context) const override; + std::unique_ptr clone() override { return std::make_unique(info.copy(), sharedState, id, paramsString); } diff --git a/src/include/processor/operator/call/standalone_call.h b/src/include/processor/operator/call/standalone_call.h index 6172f9d93a6..ba957ecdcd7 100644 --- a/src/include/processor/operator/call/standalone_call.h +++ b/src/include/processor/operator/call/standalone_call.h @@ -24,8 +24,8 @@ class StandaloneCall : public PhysicalOperator { public: StandaloneCall(std::unique_ptr localState, PhysicalOperatorType operatorType, uint32_t id, const std::string& paramsString) - : PhysicalOperator{operatorType, id, paramsString}, standaloneCallInfo{ - std::move(localState)} {} + : PhysicalOperator{operatorType, id, paramsString}, + standaloneCallInfo{std::move(localState)} {} inline bool isSource() const override { return true; } inline bool canParallel() const final { return false; } @@ -33,8 +33,8 @@ class StandaloneCall : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) override; inline std::unique_ptr clone() override { - return std::make_unique( - standaloneCallInfo->copy(), operatorType, id, paramsString); + return std::make_unique(standaloneCallInfo->copy(), operatorType, id, + paramsString); } private: diff --git a/src/include/processor/operator/comment_on.h b/src/include/processor/operator/comment_on.h index 5514d67817a..944181b99a1 100644 --- a/src/include/processor/operator/comment_on.h +++ b/src/include/processor/operator/comment_on.h @@ -24,16 +24,16 @@ struct CommentOnInfo { class CommentOn : public PhysicalOperator { public: - CommentOn( - std::unique_ptr localState, uint32_t id, const std::string& paramsString) + CommentOn(std::unique_ptr localState, uint32_t id, + const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::COMMENT_ON, id, paramsString}, commentOnInfo{std::move(localState)} {} inline bool isSource() const override { return true; } inline bool canParallel() const final { return false; } - inline void initLocalStateInternal( - ResultSet* resultSet, ExecutionContext* /*context*/) override { + inline void initLocalStateInternal(ResultSet* resultSet, + ExecutionContext* /*context*/) override { outputVector = resultSet->getValueVector(commentOnInfo->outputPos).get(); } diff --git a/src/include/processor/operator/cross_product.h b/src/include/processor/operator/cross_product.h index 535b35f2c53..5c0286109e4 100644 --- a/src/include/processor/operator/cross_product.h +++ b/src/include/processor/operator/cross_product.h @@ -66,8 +66,8 @@ class CrossProduct : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) override; std::unique_ptr clone() override { - return std::make_unique( - info->copy(), localState->copy(), children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), localState->copy(), + children[0]->clone(), id, paramsString); } private: diff --git a/src/include/processor/operator/ddl/add_node_property.h b/src/include/processor/operator/ddl/add_node_property.h deleted file mode 100644 index 1f93a2d3cf4..00000000000 --- a/src/include/processor/operator/ddl/add_node_property.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "processor/operator/ddl/add_property.h" - -namespace kuzu { -namespace processor { - -class AddNodeProperty final : public AddProperty { -public: - AddNodeProperty(catalog::Catalog* catalog, common::table_id_t tableID, std::string propertyName, - std::unique_ptr dataType, - std::unique_ptr defaultValueEvaluator, - storage::StorageManager& storageManager, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : AddProperty{catalog, tableID, std::move(propertyName), std::move(dataType), - std::move(defaultValueEvaluator), storageManager, outputPos, id, paramsString} {} - - void executeDDLInternal(ExecutionContext* context) final; - - std::unique_ptr clone() override { - return make_unique(catalog, tableID, propertyName, dataType->copy(), - defaultValueEvaluator->clone(), storageManager, outputPos, id, paramsString); - } -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/add_property.h b/src/include/processor/operator/ddl/add_property.h deleted file mode 100644 index 00e8b4865e7..00000000000 --- a/src/include/processor/operator/ddl/add_property.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "ddl.h" -#include "expression_evaluator/expression_evaluator.h" -#include "storage/storage_manager.h" - -namespace kuzu { -namespace processor { - -class AddProperty : public DDL { -public: - AddProperty(catalog::Catalog* catalog, common::table_id_t tableID, std::string propertyName, - std::unique_ptr dataType, - std::unique_ptr defaultValueEvaluator, - storage::StorageManager& storageManager, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : DDL{PhysicalOperatorType::ADD_PROPERTY, catalog, outputPos, id, paramsString}, - tableID{tableID}, propertyName{std::move(propertyName)}, dataType{std::move(dataType)}, - defaultValueEvaluator{std::move(defaultValueEvaluator)}, storageManager{storageManager} {} - - void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override { - DDL::initLocalStateInternal(resultSet, context); - defaultValueEvaluator->init(*resultSet, context->clientContext->getMemoryManager()); - } - - void executeDDLInternal(ExecutionContext* context) override = 0; - - std::string getOutputMsg() override { return {"Add Succeed."}; } - -protected: - common::ValueVector* getDefaultValVector(ExecutionContext* context); - -protected: - common::table_id_t tableID; - std::string propertyName; - std::unique_ptr dataType; - std::unique_ptr defaultValueEvaluator; - storage::StorageManager& storageManager; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/add_rel_property.h b/src/include/processor/operator/ddl/add_rel_property.h deleted file mode 100644 index fd9c4e0641e..00000000000 --- a/src/include/processor/operator/ddl/add_rel_property.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "add_property.h" - -namespace kuzu { -namespace processor { - -class AddRelProperty final : public AddProperty { -public: - AddRelProperty(catalog::Catalog* catalog, common::table_id_t tableID, std::string propertyName, - std::unique_ptr dataType, - std::unique_ptr expressionEvaluator, - storage::StorageManager& storageManager, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : AddProperty(catalog, tableID, std::move(propertyName), std::move(dataType), - std::move(expressionEvaluator), storageManager, outputPos, id, paramsString) {} - - void executeDDLInternal(ExecutionContext* context) override; - - std::unique_ptr clone() override { - return make_unique(catalog, tableID, propertyName, dataType->copy(), - defaultValueEvaluator->clone(), storageManager, outputPos, id, paramsString); - } -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/alter.h b/src/include/processor/operator/ddl/alter.h new file mode 100644 index 00000000000..1f907e6ea42 --- /dev/null +++ b/src/include/processor/operator/ddl/alter.h @@ -0,0 +1,41 @@ +#pragma once + +#include "binder/ddl/bound_alter_info.h" +#include "expression_evaluator/expression_evaluator.h" +#include "processor/operator/ddl/ddl.h" + +namespace kuzu { +namespace processor { + +class Alter : public DDL { +public: + Alter(binder::BoundAlterInfo info, + std::unique_ptr defaultValueEvaluator, + const DataPos& outputPos, uint32_t id, const std::string& paramsString) + : DDL{PhysicalOperatorType::ALTER, outputPos, id, paramsString}, info{std::move(info)}, + defaultValueEvaluator{std::move(defaultValueEvaluator)} {} + + void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override { + DDL::initLocalStateInternal(resultSet, context); + if (defaultValueEvaluator) { + defaultValueEvaluator->init(*resultSet, context->clientContext->getMemoryManager()); + } + } + + void executeDDLInternal(ExecutionContext* context) final; + + std::string getOutputMsg() final; + + std::unique_ptr clone() final { + return std::make_unique(info.copy(), + defaultValueEvaluator == nullptr ? nullptr : defaultValueEvaluator->clone(), outputPos, + id, paramsString); + } + +private: + binder::BoundAlterInfo info; + std::unique_ptr defaultValueEvaluator; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/operator/ddl/create_node_table.h b/src/include/processor/operator/ddl/create_node_table.h deleted file mode 100644 index b45323ee2cb..00000000000 --- a/src/include/processor/operator/ddl/create_node_table.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "processor/operator/ddl/ddl.h" - -namespace kuzu { -namespace processor { - -class CreateNodeTable : public DDL { -public: - CreateNodeTable(catalog::Catalog* catalog, storage::StorageManager* storageManager, - binder::BoundCreateTableInfo info, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : DDL{PhysicalOperatorType::CREATE_NODE_TABLE, catalog, outputPos, id, paramsString}, - storageManager{storageManager}, info{std::move(info)} {} - - void executeDDLInternal(ExecutionContext* context) final; - - std::string getOutputMsg() final; - - std::unique_ptr clone() final { - return std::make_unique( - catalog, storageManager, info.copy(), outputPos, id, paramsString); - } - -private: - storage::StorageManager* storageManager; - binder::BoundCreateTableInfo info; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/create_rdf_graph.h b/src/include/processor/operator/ddl/create_rdf_graph.h deleted file mode 100644 index 3321475ae29..00000000000 --- a/src/include/processor/operator/ddl/create_rdf_graph.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "ddl.h" -#include "storage/storage_manager.h" - -namespace kuzu { -namespace processor { - -class CreateRdfGraph final : public DDL { -public: - CreateRdfGraph(catalog::Catalog* catalog, storage::StorageManager* storageManager, - binder::BoundCreateTableInfo info, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : DDL{PhysicalOperatorType::CREATE_RDF_GRAPH, catalog, outputPos, id, paramsString}, - storageManager{storageManager}, - nodesStatistics{storageManager->getNodesStatisticsAndDeletedIDs()}, - relsStatistics{storageManager->getRelsStatistics()}, info{std::move(info)} {} - - void executeDDLInternal(ExecutionContext* context) override; - - std::string getOutputMsg() override; - - inline std::unique_ptr clone() override { - return std::make_unique( - catalog, storageManager, info.copy(), outputPos, id, paramsString); - } - -private: - storage::StorageManager* storageManager; - storage::NodesStoreStatsAndDeletedIDs* nodesStatistics; - storage::RelsStoreStats* relsStatistics; - binder::BoundCreateTableInfo info; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/create_rel_table.h b/src/include/processor/operator/ddl/create_rel_table.h deleted file mode 100644 index 24d8da1dd3f..00000000000 --- a/src/include/processor/operator/ddl/create_rel_table.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "processor/operator/ddl/ddl.h" - -namespace kuzu { -namespace processor { - -class CreateRelTable final : public DDL { -public: - CreateRelTable(catalog::Catalog* catalog, storage::StorageManager* storageManager, - binder::BoundCreateTableInfo info, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : DDL{PhysicalOperatorType::CREATE_REL_TABLE, catalog, outputPos, id, paramsString}, - storageManager{storageManager}, info{std::move(info)} {} - - void executeDDLInternal(ExecutionContext* context) override; - - std::string getOutputMsg() override; - - std::unique_ptr clone() override { - return make_unique( - catalog, storageManager, info.copy(), outputPos, id, paramsString); - } - -private: - storage::StorageManager* storageManager; - binder::BoundCreateTableInfo info; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/create_rel_table_group.h b/src/include/processor/operator/ddl/create_rel_table_group.h deleted file mode 100644 index 6789ed9536d..00000000000 --- a/src/include/processor/operator/ddl/create_rel_table_group.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "processor/operator/ddl/ddl.h" - -namespace kuzu { -namespace processor { - -class CreateRelTableGroup : public DDL { -public: - CreateRelTableGroup(catalog::Catalog* catalog, storage::StorageManager* storageManager, - binder::BoundCreateTableInfo info, const DataPos& outputPos, uint32_t id, - const std::string& paramsString) - : DDL{PhysicalOperatorType::CREATE_REL_TABLE, catalog, outputPos, id, paramsString}, - storageManager{storageManager}, info{std::move(info)} {} - - void executeDDLInternal(ExecutionContext* context) override; - - std::string getOutputMsg() override; - - std::unique_ptr clone() override { - return make_unique( - catalog, storageManager, info.copy(), outputPos, id, paramsString); - } - -private: - storage::StorageManager* storageManager; - binder::BoundCreateTableInfo info; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/create_table.h b/src/include/processor/operator/ddl/create_table.h new file mode 100644 index 00000000000..6b45ca1d008 --- /dev/null +++ b/src/include/processor/operator/ddl/create_table.h @@ -0,0 +1,29 @@ +#pragma once + +#include "binder/ddl/bound_create_table_info.h" +#include "processor/operator/ddl/ddl.h" + +namespace kuzu { +namespace processor { + +class CreateTable : public DDL { +public: + CreateTable(binder::BoundCreateTableInfo info, const DataPos& outputPos, uint32_t id, + const std::string& paramsString) + : DDL{PhysicalOperatorType::CREATE_TABLE, outputPos, id, paramsString}, + info{std::move(info)} {} + + void executeDDLInternal(ExecutionContext* context) final; + + std::string getOutputMsg() final; + + std::unique_ptr clone() final { + return std::make_unique(info.copy(), outputPos, id, paramsString); + } + +private: + binder::BoundCreateTableInfo info; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/operator/ddl/ddl.h b/src/include/processor/operator/ddl/ddl.h index c715d345031..85ab5ee965b 100644 --- a/src/include/processor/operator/ddl/ddl.h +++ b/src/include/processor/operator/ddl/ddl.h @@ -1,6 +1,5 @@ #pragma once -#include "catalog/catalog.h" #include "processor/operator/physical_operator.h" namespace kuzu { @@ -8,13 +7,13 @@ namespace processor { class DDL : public PhysicalOperator { public: - DDL(PhysicalOperatorType operatorType, catalog::Catalog* catalog, const DataPos& outputPos, - uint32_t id, const std::string& paramsString) - : PhysicalOperator{operatorType, id, paramsString}, catalog{catalog}, outputPos{outputPos}, + DDL(PhysicalOperatorType operatorType, const DataPos& outputPos, uint32_t id, + const std::string& paramsString) + : PhysicalOperator{operatorType, id, paramsString}, outputPos{outputPos}, outputVector{nullptr}, hasExecuted{false} {} - inline bool isSource() const final { return true; } - inline bool canParallel() const final { return false; } + bool isSource() const final { return true; } + bool canParallel() const final { return false; } void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; @@ -25,7 +24,6 @@ class DDL : public PhysicalOperator { virtual void executeDDLInternal(ExecutionContext* context) = 0; protected: - catalog::Catalog* catalog; DataPos outputPos; common::ValueVector* outputVector; diff --git a/src/include/processor/operator/ddl/drop_property.h b/src/include/processor/operator/ddl/drop_property.h deleted file mode 100644 index 13d88308be9..00000000000 --- a/src/include/processor/operator/ddl/drop_property.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "ddl.h" -#include "storage/storage_manager.h" - -namespace kuzu { -namespace processor { - -class DropProperty : public DDL { -public: - DropProperty(catalog::Catalog* catalog, common::table_id_t tableID, - common::property_id_t propertyID, const DataPos& outputPos, - storage::StorageManager& storageManager, uint32_t id, const std::string& paramsString) - : DDL{PhysicalOperatorType::DROP_PROPERTY, catalog, outputPos, id, paramsString}, - storageManager{storageManager}, tableID{tableID}, propertyID{propertyID} {} - - void executeDDLInternal(ExecutionContext* context) final; - - std::string getOutputMsg() final { return {"Drop succeed."}; } - - std::unique_ptr clone() override { - return make_unique( - catalog, tableID, propertyID, outputPos, storageManager, id, paramsString); - } - -protected: - storage::StorageManager& storageManager; - common::table_id_t tableID; - common::property_id_t propertyID; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/drop_table.h b/src/include/processor/operator/ddl/drop_table.h index 76df09d0d6c..0a7c1c2367f 100644 --- a/src/include/processor/operator/ddl/drop_table.h +++ b/src/include/processor/operator/ddl/drop_table.h @@ -7,9 +7,9 @@ namespace processor { class DropTable : public DDL { public: - DropTable(catalog::Catalog* catalog, std::string tableName, common::table_id_t tableID, - const DataPos& outputPos, uint32_t id, const std::string& paramsString) - : DDL{PhysicalOperatorType::DROP_TABLE, catalog, outputPos, id, paramsString}, + DropTable(std::string tableName, common::table_id_t tableID, const DataPos& outputPos, + uint32_t id, const std::string& paramsString) + : DDL{PhysicalOperatorType::DROP_TABLE, outputPos, id, paramsString}, tableName{std::move(tableName)}, tableID{tableID} {} void executeDDLInternal(ExecutionContext* context) override; @@ -17,7 +17,7 @@ class DropTable : public DDL { std::string getOutputMsg() override; std::unique_ptr clone() override { - return make_unique(catalog, tableName, tableID, outputPos, id, paramsString); + return make_unique(tableName, tableID, outputPos, id, paramsString); } protected: diff --git a/src/include/processor/operator/ddl/rename_property.h b/src/include/processor/operator/ddl/rename_property.h deleted file mode 100644 index ac3ad075ca4..00000000000 --- a/src/include/processor/operator/ddl/rename_property.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "ddl.h" - -namespace kuzu { -namespace processor { - -class RenameProperty : public DDL { -public: - RenameProperty(catalog::Catalog* catalog, common::table_id_t tableID, - common::property_id_t propertyID, std::string newName, const DataPos& outputPos, - uint32_t id, const std::string& paramsString) - : DDL{PhysicalOperatorType::RENAME_PROPERTY, catalog, outputPos, id, paramsString}, - tableID{tableID}, propertyID{propertyID}, newName{std::move(newName)} {} - - void executeDDLInternal(ExecutionContext* /*context*/) override { - catalog->renameProperty(tableID, propertyID, newName); - } - - std::string getOutputMsg() override { return "Property renamed"; } - - std::unique_ptr clone() override { - return make_unique( - catalog, tableID, propertyID, newName, outputPos, id, paramsString); - } - -protected: - common::table_id_t tableID; - common::property_id_t propertyID; - std::string newName; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/ddl/rename_table.h b/src/include/processor/operator/ddl/rename_table.h deleted file mode 100644 index 42b0b2b1ecb..00000000000 --- a/src/include/processor/operator/ddl/rename_table.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "ddl.h" - -namespace kuzu { -namespace processor { - -class RenameTable final : public DDL { -public: - RenameTable(catalog::Catalog* catalog, common::table_id_t tableID, std::string newName, - const DataPos& outputPos, uint32_t id, const std::string& paramsString) - : DDL{PhysicalOperatorType::RENAME_TABLE, catalog, outputPos, id, paramsString}, - tableID{tableID}, newName{std::move(newName)} {} - - void executeDDLInternal(ExecutionContext* /*context*/) override { - catalog->renameTable(tableID, newName); - } - - std::string getOutputMsg() override { return "Table renamed"; } - - std::unique_ptr clone() override { - return make_unique(catalog, tableID, newName, outputPos, id, paramsString); - } - -protected: - common::table_id_t tableID; - std::string newName; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/detach_database.h b/src/include/processor/operator/detach_database.h new file mode 100644 index 00000000000..f40304eab6b --- /dev/null +++ b/src/include/processor/operator/detach_database.h @@ -0,0 +1,28 @@ +#pragma once + +#include "processor/operator/physical_operator.h" + +namespace kuzu { +namespace processor { + +class DetachDatabase final : public PhysicalOperator { +public: + DetachDatabase(std::string dbName, uint32_t id, const std::string& paramsString) + : PhysicalOperator{PhysicalOperatorType::DETACH_DATABASE, id, paramsString}, + dbName{std::move(dbName)} {} + + bool isSource() const override { return true; } + bool canParallel() const override { return false; } + + bool getNextTuplesInternal(ExecutionContext* context) override; + + std::unique_ptr clone() override { + return std::make_unique(dbName, id, paramsString); + } + +private: + std::string dbName; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/operator/filter.h b/src/include/processor/operator/filter.h index 424b7c029ac..741d7acc004 100644 --- a/src/include/processor/operator/filter.h +++ b/src/include/processor/operator/filter.h @@ -35,8 +35,8 @@ struct NodeLabelFilterInfo { DataPos nodeVectorPos; std::unordered_set nodeLabelSet; - NodeLabelFilterInfo( - const DataPos& nodeVectorPos, std::unordered_set nodeLabelSet) + NodeLabelFilterInfo(const DataPos& nodeVectorPos, + std::unordered_set nodeLabelSet) : nodeVectorPos{nodeVectorPos}, nodeLabelSet{std::move(nodeLabelSet)} {} NodeLabelFilterInfo(const NodeLabelFilterInfo& other) : nodeVectorPos{other.nodeVectorPos}, nodeLabelSet{other.nodeLabelSet} {} @@ -58,8 +58,8 @@ class NodeLabelFiler : public PhysicalOperator, public SelVectorOverWriter { bool getNextTuplesInternal(ExecutionContext* context) override; inline std::unique_ptr clone() final { - return std::make_unique( - info->copy(), children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), children[0]->clone(), id, + paramsString); } private: diff --git a/src/include/processor/operator/hash_join/hash_join_probe.h b/src/include/processor/operator/hash_join/hash_join_probe.h index f2d3b311450..d59c9b7bed5 100644 --- a/src/include/processor/operator/hash_join/hash_join_probe.h +++ b/src/include/processor/operator/hash_join/hash_join_probe.h @@ -15,7 +15,7 @@ struct ProbeState { probedTuples = std::make_unique(common::DEFAULT_VECTOR_CAPACITY); matchedSelVector = std::make_unique(common::DEFAULT_VECTOR_CAPACITY); - matchedSelVector->resetSelectorToValuePosBuffer(); + matchedSelVector->setToFiltered(); } // Each key corresponds to a pointer with the same hash value from the ht directory. diff --git a/src/include/processor/operator/hash_join/join_hash_table.h b/src/include/processor/operator/hash_join/join_hash_table.h index e31510a9081..34c81fb940e 100644 --- a/src/include/processor/operator/hash_join/join_hash_table.h +++ b/src/include/processor/operator/hash_join/join_hash_table.h @@ -1,21 +1,14 @@ #pragma once -#include - -#include "processor/operator/base_hash_table.h" +#include "processor/result/base_hash_table.h" #include "storage/buffer_manager/memory_manager.h" namespace kuzu { namespace processor { class JoinHashTable : public BaseHashTable { - using hash_function_t = std::function; - using compare_function_t = - std::function; - public: - JoinHashTable(storage::MemoryManager& memoryManager, - std::vector> keyTypes, + JoinHashTable(storage::MemoryManager& memoryManager, common::logical_type_vec_t keyTypes, std::unique_ptr tableSchema); void appendVectors(const std::vector& keyVectors, @@ -24,8 +17,8 @@ class JoinHashTable : public BaseHashTable { const std::vector& appendInfos, ft_col_idx_t colIdx); // Used in worst-case optimal join - void appendVectorWithSorting( - common::ValueVector* keyVector, std::vector payloadVectors); + void appendVectorWithSorting(common::ValueVector* keyVector, + std::vector payloadVectors); void allocateHashSlots(uint64_t numTuples); void buildHashSlots(); @@ -40,42 +33,38 @@ class JoinHashTable : public BaseHashTable { common::sel_t matchUnFlatKey(common::ValueVector* keyVector, uint8_t** probedTuples, uint8_t** matchedTuples, common::SelectionVector* matchedTuplesSelVector); - inline void lookup(std::vector& vectors, - std::vector& colIdxesToScan, uint8_t** tuplesToRead, uint64_t startPos, - uint64_t numTuplesToRead) { + void lookup(std::vector& vectors, std::vector& colIdxesToScan, + uint8_t** tuplesToRead, uint64_t startPos, uint64_t numTuplesToRead) { factorizedTable->lookup(vectors, colIdxesToScan, tuplesToRead, startPos, numTuplesToRead); } - inline void merge(JoinHashTable& other) { factorizedTable->merge(*other.factorizedTable); } - inline uint64_t getNumTuples() { return factorizedTable->getNumTuples(); } - inline uint8_t** getPrevTuple(const uint8_t* tuple) const { + void merge(JoinHashTable& other) { factorizedTable->merge(*other.factorizedTable); } + uint64_t getNumTuples() { return factorizedTable->getNumTuples(); } + uint8_t** getPrevTuple(const uint8_t* tuple) const { return (uint8_t**)(tuple + prevPtrColOffset); } - inline uint8_t* getTupleForHash(common::hash_t hash) { + uint8_t* getTupleForHash(common::hash_t hash) { auto slotIdx = getSlotIdxForHash(hash); return ((uint8_t**)(hashSlotsBlocks[slotIdx >> numSlotsPerBlockLog2] ->getData()))[slotIdx & slotIdxInBlockMask]; } - inline FactorizedTable* getFactorizedTable() { return factorizedTable.get(); } - inline const FactorizedTableSchema* getTableSchema() { - return factorizedTable->getTableSchema(); - } + FactorizedTable* getFactorizedTable() { return factorizedTable.get(); } + const FactorizedTableSchema* getTableSchema() { return factorizedTable->getTableSchema(); } private: - uint8_t** findHashSlot(uint8_t* tuple) const; + uint8_t** findHashSlot(const uint8_t* tuple) const; // This function returns the pointer that previously stored in the same slot. uint8_t* insertEntry(uint8_t* tuple) const; bool compareFlatKeys(const std::vector& keyVectors, const uint8_t* tuple); - void initFunctions(); - void getHashFunction(common::PhysicalTypeID physicalTypeID, hash_function_t& func); - void getCompareFunction(common::PhysicalTypeID physicalTypeID, compare_function_t& func); + // Join hash table assumes all keys to be flat. + void computeVectorHashes(std::vector keyVectors); -private: - std::vector> keyTypes; - std::vector entryHashFunctions; - std::vector entryCompareFunctions; + common::offset_t getHashValueColOffset() const; +private: + static constexpr uint64_t PREV_PTR_COL_IDX = 1; + static constexpr uint64_t HASH_COL_IDX = 2; const FactorizedTableSchema* tableSchema; uint64_t prevPtrColOffset; }; diff --git a/src/include/processor/operator/install_extension.h b/src/include/processor/operator/install_extension.h index b08203c4e8e..af86c649180 100644 --- a/src/include/processor/operator/install_extension.h +++ b/src/include/processor/operator/install_extension.h @@ -11,12 +11,12 @@ class InstallExtension final : public PhysicalOperator { : PhysicalOperator{PhysicalOperatorType::INSTALL_EXTENSION, id, paramsString}, name{std::move(name)}, hasExecuted{false} {} - inline bool isSource() const override { return true; } - inline bool canParallel() const override { return false; } + bool isSource() const override { return true; } + bool canParallel() const override { return false; } bool getNextTuplesInternal(ExecutionContext* context) override; - inline std::unique_ptr clone() override { + std::unique_ptr clone() override { return std::make_unique(name, id, paramsString); } diff --git a/src/include/processor/operator/intersect/intersect.h b/src/include/processor/operator/intersect/intersect.h index 14d26617278..62981220df5 100644 --- a/src/include/processor/operator/intersect/intersect.h +++ b/src/include/processor/operator/intersect/intersect.h @@ -19,8 +19,8 @@ class Intersect : public PhysicalOperator { std::vector> children, uint32_t id, const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::INTERSECT, std::move(children), id, paramsString}, - outputDataPos{outputDataPos}, - intersectDataInfos{std::move(intersectDataInfos)}, sharedHTs{std::move(sharedHTs)} { + outputDataPos{outputDataPos}, intersectDataInfos{std::move(intersectDataInfos)}, + sharedHTs{std::move(sharedHTs)} { tupleIdxPerBuildSide.resize(this->sharedHTs.size(), 0); carryBuildSideIdx = -1u; probedFlatTuples.resize(this->sharedHTs.size()); @@ -44,8 +44,8 @@ class Intersect : public PhysicalOperator { static void twoWayIntersect(common::nodeID_t* leftNodeIDs, common::SelectionVector& lSelVector, common::nodeID_t* rightNodeIDs, common::SelectionVector& rSelVector); void intersectLists(const std::vector& listsToIntersect); - void populatePayloads( - const std::vector& tuples, const std::vector& listIdxes); + void populatePayloads(const std::vector& tuples, + const std::vector& listIdxes); bool hasNextTuplesToIntersect(); inline uint32_t getNumBuilds() { return sharedHTs.size(); } diff --git a/src/include/processor/operator/intersect/intersect_build.h b/src/include/processor/operator/intersect/intersect_build.h index 8f43e7b176e..16baeba5280 100644 --- a/src/include/processor/operator/intersect/intersect_build.h +++ b/src/include/processor/operator/intersect/intersect_build.h @@ -18,7 +18,7 @@ class IntersectBuild : public HashJoinBuild { children[0]->clone(), id, paramsString); } - inline void appendVectors() final { + void appendVectors() final { KU_ASSERT(keyVectors.size() == 1); hashTable->appendVectorWithSorting(keyVectors[0], payloadVectors); } diff --git a/src/include/processor/operator/macro/create_macro.h b/src/include/processor/operator/macro/create_macro.h index 7da9604cb8c..1eafc8cfa87 100644 --- a/src/include/processor/operator/macro/create_macro.h +++ b/src/include/processor/operator/macro/create_macro.h @@ -27,22 +27,22 @@ class CreateMacro : public PhysicalOperator { public: CreateMacro(PhysicalOperatorType operatorType, std::unique_ptr createMacroInfo, uint32_t id, const std::string& paramsString) - : PhysicalOperator{operatorType, id, paramsString}, createMacroInfo{ - std::move(createMacroInfo)} {} + : PhysicalOperator{operatorType, id, paramsString}, + createMacroInfo{std::move(createMacroInfo)} {} inline bool isSource() const override { return true; } inline bool canParallel() const final { return false; } - inline void initLocalStateInternal( - ResultSet* resultSet, ExecutionContext* /*context*/) override { + inline void initLocalStateInternal(ResultSet* resultSet, + ExecutionContext* /*context*/) override { outputVector = resultSet->getValueVector(createMacroInfo->outputPos).get(); } bool getNextTuplesInternal(ExecutionContext* context) override; std::unique_ptr clone() override { - return std::make_unique( - operatorType, createMacroInfo->copy(), id, paramsString); + return std::make_unique(operatorType, createMacroInfo->copy(), id, + paramsString); } private: diff --git a/src/include/processor/operator/multiplicity_reducer.h b/src/include/processor/operator/multiplicity_reducer.h index 9ecb158f993..1b36c921627 100644 --- a/src/include/processor/operator/multiplicity_reducer.h +++ b/src/include/processor/operator/multiplicity_reducer.h @@ -8,8 +8,8 @@ namespace processor { class MultiplicityReducer : public PhysicalOperator { public: - MultiplicityReducer( - std::unique_ptr child, uint32_t id, const std::string& paramsString) + MultiplicityReducer(std::unique_ptr child, uint32_t id, + const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::MULTIPLICITY_REDUCER, std::move(child), id, paramsString}, prevMultiplicity{1}, numRepeat{0} {} diff --git a/src/include/processor/operator/order_by/key_block_merger.h b/src/include/processor/operator/order_by/key_block_merger.h index 57e3796dee7..66c65a79ce6 100644 --- a/src/include/processor/operator/order_by/key_block_merger.h +++ b/src/include/processor/operator/order_by/key_block_merger.h @@ -28,8 +28,8 @@ struct StrKeyColInfo { class MergedKeyBlocks { public: - MergedKeyBlocks( - uint32_t numBytesPerTuple, uint64_t numTuples, storage::MemoryManager* memoryManager); + MergedKeyBlocks(uint32_t numBytesPerTuple, uint64_t numTuples, + storage::MemoryManager* memoryManager); // This constructor is used to convert a dataBlock to a MergedKeyBlocks. MergedKeyBlocks(uint32_t numBytesPerTuple, std::shared_ptr keyBlock); @@ -51,8 +51,8 @@ class MergedKeyBlocks { return keyBlocks[idx]->getData(); } - uint8_t* getBlockEndTuplePtr( - uint32_t blockIdx, uint64_t endTupleIdx, uint32_t endTupleBlockIdx) const; + uint8_t* getBlockEndTuplePtr(uint32_t blockIdx, uint64_t endTupleIdx, + uint32_t endTupleBlockIdx) const; private: uint32_t numBytesPerTuple; diff --git a/src/include/processor/operator/order_by/order_by_data_info.h b/src/include/processor/operator/order_by/order_by_data_info.h index 45863ee22c7..9594808d825 100644 --- a/src/include/processor/operator/order_by/order_by_data_info.h +++ b/src/include/processor/operator/order_by/order_by_data_info.h @@ -20,17 +20,16 @@ struct OrderByDataInfo { std::vector> payloadTypes, std::vector isAscOrder, std::unique_ptr payloadTableSchema, std::vector keyInPayloadPos) - : keysPos{std::move(keysPos)}, payloadsPos{std::move(payloadsPos)}, keyTypes{std::move( - keyTypes)}, - payloadTypes{std::move(payloadTypes)}, isAscOrder{std::move(isAscOrder)}, - payloadTableSchema{std::move(payloadTableSchema)}, keyInPayloadPos{ - std::move(keyInPayloadPos)} {} + : keysPos{std::move(keysPos)}, payloadsPos{std::move(payloadsPos)}, + keyTypes{std::move(keyTypes)}, payloadTypes{std::move(payloadTypes)}, + isAscOrder{std::move(isAscOrder)}, payloadTableSchema{std::move(payloadTableSchema)}, + keyInPayloadPos{std::move(keyInPayloadPos)} {} OrderByDataInfo(const OrderByDataInfo& other) - : keysPos{other.keysPos}, - payloadsPos{other.payloadsPos}, keyTypes{common::LogicalType::copy(other.keyTypes)}, + : keysPos{other.keysPos}, payloadsPos{other.payloadsPos}, + keyTypes{common::LogicalType::copy(other.keyTypes)}, payloadTypes{common::LogicalType::copy(other.payloadTypes)}, isAscOrder{other.isAscOrder}, - payloadTableSchema{other.payloadTableSchema->copy()}, keyInPayloadPos{ - other.keyInPayloadPos} {} + payloadTableSchema{other.payloadTableSchema->copy()}, + keyInPayloadPos{other.keyInPayloadPos} {} std::unique_ptr copy() const { return std::make_unique(*this); diff --git a/src/include/processor/operator/order_by/order_by_key_encoder.h b/src/include/processor/operator/order_by/order_by_key_encoder.h index 1a6df18dc38..05aeed8df0d 100644 --- a/src/include/processor/operator/order_by/order_by_key_encoder.h +++ b/src/include/processor/operator/order_by/order_by_key_encoder.h @@ -11,20 +11,20 @@ namespace kuzu { namespace processor { #define BSWAP64(x) \ - ((uint64_t)((((uint64_t)(x)&0xff00000000000000ull) >> 56) | \ - (((uint64_t)(x)&0x00ff000000000000ull) >> 40) | \ - (((uint64_t)(x)&0x0000ff0000000000ull) >> 24) | \ - (((uint64_t)(x)&0x000000ff00000000ull) >> 8) | \ - (((uint64_t)(x)&0x00000000ff000000ull) << 8) | \ - (((uint64_t)(x)&0x0000000000ff0000ull) << 24) | \ - (((uint64_t)(x)&0x000000000000ff00ull) << 40) | \ - (((uint64_t)(x)&0x00000000000000ffull) << 56))) + ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \ + (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \ + (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \ + (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \ + (((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \ + (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \ + (((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \ + (((uint64_t)(x) & 0x00000000000000ffull) << 56))) #define BSWAP32(x) \ - ((uint32_t)((((uint32_t)(x)&0xff000000) >> 24) | (((uint32_t)(x)&0x00ff0000) >> 8) | \ - (((uint32_t)(x)&0x0000ff00) << 8) | (((uint32_t)(x)&0x000000ff) << 24))) + ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | (((uint32_t)(x) & 0x00ff0000) >> 8) | \ + (((uint32_t)(x) & 0x0000ff00) << 8) | (((uint32_t)(x) & 0x000000ff) << 24))) -#define BSWAP16(x) ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | (((uint16_t)(x)&0x00ff) << 8))) +#define BSWAP16(x) ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | (((uint16_t)(x) & 0x00ff) << 8))) // The OrderByKeyEncoder encodes all columns in the ORDER BY clause into a single binary sequence // that, when compared using memcmp will yield the correct overall sorting order. On little-endian diff --git a/src/include/processor/operator/order_by/order_by_scan.h b/src/include/processor/operator/order_by/order_by_scan.h index a2453f5050d..fcb3929e1e6 100644 --- a/src/include/processor/operator/order_by/order_by_scan.h +++ b/src/include/processor/operator/order_by/order_by_scan.h @@ -9,12 +9,18 @@ namespace processor { struct OrderByScanLocalState { std::vector vectorsToRead; std::unique_ptr payloadScanner; + uint64_t numTuples; + uint64_t numTuplesRead; - void init( - std::vector& outVectorPos, SortSharedState& sharedState, ResultSet& resultSet); + void init(std::vector& outVectorPos, SortSharedState& sharedState, + ResultSet& resultSet); // NOLINTNEXTLINE(readability-make-member-function-const): Updates vectorsToRead. - inline uint64_t scan() { return payloadScanner->scan(vectorsToRead); } + uint64_t scan() { + uint64_t tuplesRead = payloadScanner->scan(vectorsToRead); + numTuplesRead += tuplesRead; + return tuplesRead; + } }; // To preserve the ordering of tuples, the orderByScan operator will only @@ -25,16 +31,16 @@ class OrderByScan : public PhysicalOperator { std::unique_ptr child, uint32_t id, const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::ORDER_BY_SCAN, std::move(child), id, paramsString}, outVectorPos{std::move(outVectorPos)}, - localState{std::make_unique()}, sharedState{ - std::move(sharedState)} {} + localState{std::make_unique()}, + sharedState{std::move(sharedState)} {} // This constructor is used for cloning only. OrderByScan(std::vector outVectorPos, std::shared_ptr sharedState, uint32_t id, const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::ORDER_BY_SCAN, id, paramsString}, outVectorPos{std::move(outVectorPos)}, - localState{std::make_unique()}, sharedState{ - std::move(sharedState)} {} + localState{std::make_unique()}, + sharedState{std::move(sharedState)} {} inline bool isSource() const final { return true; } // Ordered table should be scanned in single-thread mode. @@ -48,6 +54,8 @@ class OrderByScan : public PhysicalOperator { return std::make_unique(outVectorPos, sharedState, id, paramsString); } + double getProgress(ExecutionContext* context) const override; + private: std::vector outVectorPos; std::unique_ptr localState; diff --git a/src/include/processor/operator/order_by/radix_sort.h b/src/include/processor/operator/order_by/radix_sort.h index c0dbdf36c1c..d868e9811d0 100644 --- a/src/include/processor/operator/order_by/radix_sort.h +++ b/src/include/processor/operator/order_by/radix_sort.h @@ -24,14 +24,17 @@ struct TieRange { // seen so far. If there are tie tuples, it will compare the overflow ptr of strings. For subsequent // columns, the algorithm only calls radixSort on tie tuples. class RadixSort { +private: + static constexpr uint16_t COUNTING_ARRAY_SIZE = 256; + public: RadixSort(storage::MemoryManager* memoryManager, FactorizedTable& factorizedTable, OrderByKeyEncoder& orderByKeyEncoder, std::vector strKeyColsInfo) : tmpSortingResultBlock{std::make_unique(memoryManager)}, tmpTuplePtrSortingBlock{std::make_unique(memoryManager)}, factorizedTable{factorizedTable}, strKeyColsInfo{std::move(strKeyColsInfo)}, - numBytesPerTuple{orderByKeyEncoder.getNumBytesPerTuple()}, numBytesToRadixSort{ - numBytesPerTuple - 8} {} + numBytesPerTuple{orderByKeyEncoder.getNumBytesPerTuple()}, + numBytesToRadixSort{numBytesPerTuple - 8} {} void sortSingleKeyBlock(const DataBlock& keyBlock); diff --git a/src/include/processor/operator/order_by/top_k.h b/src/include/processor/operator/order_by/top_k.h index 62219a88cb7..407e39c1638 100644 --- a/src/include/processor/operator/order_by/top_k.h +++ b/src/include/processor/operator/order_by/top_k.h @@ -64,8 +64,8 @@ class TopKBuffer { void initVectors(); template - void getSelectComparisonFunction( - common::PhysicalTypeID typeID, vector_select_comparison_func& selectFunc); + void getSelectComparisonFunction(common::PhysicalTypeID typeID, + vector_select_comparison_func& selectFunc); void initCompareFuncs(); @@ -79,8 +79,8 @@ class TopKBuffer { void compareUnflatKeys(common::vector_idx_t vectorIdxToCompare, const std::vector keyVectors); - static void appendSelState( - common::SelectionVector* selVector, common::SelectionVector* selVectorToAppend); + static void appendSelState(common::SelectionVector* selVector, + common::SelectionVector* selVectorToAppend); public: const OrderByDataInfo* orderByDataInfo; @@ -153,8 +153,8 @@ class TopK final : public Sink { void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; inline void initGlobalStateInternal(ExecutionContext* context) override { - sharedState->init( - *info, context->clientContext->getMemoryManager(), skipNumber, limitNumber); + sharedState->init(*info, context->clientContext->getMemoryManager(), skipNumber, + limitNumber); } void executeInternal(ExecutionContext* context) override; diff --git a/src/include/processor/operator/order_by/top_k_scanner.h b/src/include/processor/operator/order_by/top_k_scanner.h index 1b51f37a93e..c658d45465b 100644 --- a/src/include/processor/operator/order_by/top_k_scanner.h +++ b/src/include/processor/operator/order_by/top_k_scanner.h @@ -9,8 +9,8 @@ struct TopKLocalScanState { std::vector vectorsToScan; std::unique_ptr payloadScanner; - void init( - std::vector& outVectorPos, TopKSharedState& sharedState, ResultSet& resultSet); + void init(std::vector& outVectorPos, TopKSharedState& sharedState, + ResultSet& resultSet); // NOLINTNEXTLINE(readability-make-member-function-const): Semantically non-const. inline uint64_t scan() { return payloadScanner->scan(vectorsToScan); } @@ -33,8 +33,8 @@ class TopKScan : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) final; std::unique_ptr clone() final { - return std::make_unique( - outVectorPos, sharedState, children[0]->clone(), id, paramsString); + return std::make_unique(outVectorPos, sharedState, children[0]->clone(), id, + paramsString); } private: diff --git a/src/include/processor/operator/partitioner.h b/src/include/processor/operator/partitioner.h index 65800727cc6..38797f46611 100644 --- a/src/include/processor/operator/partitioner.h +++ b/src/include/processor/operator/partitioner.h @@ -1,7 +1,7 @@ #pragma once -#include "common/data_chunk/data_chunk_collection.h" #include "processor/operator/sink.h" +#include "storage/store/chunked_node_group_collection.h" namespace kuzu { namespace storage { @@ -20,7 +20,7 @@ struct PartitionerFunctions { // partitioning methods. For example, copy of rel tables require partitioning on both FWD and BWD // direction. Each partitioning method corresponds to a PartitioningState. struct PartitioningBuffer { - std::vector> partitions; + std::vector partitions; void merge(std::unique_ptr localPartitioningStates); }; @@ -28,9 +28,10 @@ struct PartitioningBuffer { // NOTE: Currently, Partitioner is tightly coupled with RelBatchInsert. We should generalize it // later when necessary. Here, each partition is essentially a node group. struct BatchInsertSharedState; +struct PartitioningInfo; struct PartitionerSharedState { + std::vector columnTypes; std::mutex mtx; - storage::MemoryManager* mm; storage::NodeTable* srcNodeTable; storage::NodeTable* dstNodeTable; @@ -42,18 +43,19 @@ struct PartitionerSharedState { // In copy rdf, we need to access num nodes before it is available in statistics. std::vector> nodeBatchInsertSharedStates; - explicit PartitionerSharedState(storage::MemoryManager* mm) : mm{mm} {} + explicit PartitionerSharedState(std::vector columnTypes) + : columnTypes{std::move(columnTypes)} {} - void initialize(); + void initialize(std::vector>& infos); common::partition_idx_t getNextPartition(common::vector_idx_t partitioningIdx); void resetState(); void merge(std::vector> localPartitioningStates); - inline common::DataChunkCollection* getPartitionBuffer( - common::vector_idx_t partitioningIdx, common::partition_idx_t partitionIdx) { + inline const storage::ChunkedNodeGroupCollection& getPartitionBuffer( + common::vector_idx_t partitioningIdx, common::partition_idx_t partitionIdx) const { KU_ASSERT(partitioningIdx < partitioningBuffers.size()); KU_ASSERT(partitionIdx < partitioningBuffers[partitioningIdx]->partitions.size()); - return partitioningBuffers[partitioningIdx]->partitions[partitionIdx].get(); + return partitioningBuffers[partitioningIdx]->partitions[partitionIdx]; } }; @@ -69,11 +71,11 @@ struct PartitionerLocalState { struct PartitioningInfo { DataPos keyDataPos; std::vector columnDataPositions; - common::logical_types_t columnTypes; + std::vector columnTypes; partitioner_func_t partitionerFunc; PartitioningInfo(DataPos keyDataPos, std::vector columnDataPositions, - common::logical_types_t columnTypes, partitioner_func_t partitionerFunc) + std::vector columnTypes, partitioner_func_t partitionerFunc) : keyDataPos{keyDataPos}, columnDataPositions{std::move(columnDataPositions)}, columnTypes{std::move(columnTypes)}, partitionerFunc{std::move(partitionerFunc)} {} inline std::unique_ptr copy() { @@ -100,15 +102,18 @@ class Partitioner : public Sink { std::unique_ptr clone() final; - static void initializePartitioningStates( + static void initializePartitioningStates(std::vector>& infos, std::vector>& partitioningBuffers, - std::vector numPartitions, storage::MemoryManager* mm); + std::vector numPartitions); private: + common::DataChunk constructDataChunk(const std::vector& columnPositions, + const std::vector& columnTypes, const ResultSet& resultSet, + const std::shared_ptr& state); // TODO: For now, RelBatchInsert will guarantee all data are inside one data chunk. Should be // generalized to resultSet later if needed. - void copyDataToPartitions( - common::partition_idx_t partitioningIdx, common::DataChunk* chunkToCopyFrom); + void copyDataToPartitions(common::partition_idx_t partitioningIdx, + common::DataChunk chunkToCopyFrom); private: std::vector> infos; diff --git a/src/include/processor/operator/persistent/batch_insert.h b/src/include/processor/operator/persistent/batch_insert.h index ccc380a1604..8f675d8967a 100644 --- a/src/include/processor/operator/persistent/batch_insert.h +++ b/src/include/processor/operator/persistent/batch_insert.h @@ -26,8 +26,8 @@ struct BatchInsertSharedState { std::shared_ptr fTable; storage::WAL* wal; - BatchInsertSharedState( - storage::Table* table, std::shared_ptr fTable, storage::WAL* wal) + BatchInsertSharedState(storage::Table* table, std::shared_ptr fTable, + storage::WAL* wal) : numRows{0}, table{table}, fTable{std::move(fTable)}, wal{wal} {}; BatchInsertSharedState(const BatchInsertSharedState& other) = delete; @@ -48,11 +48,11 @@ struct BatchInsertSharedState { wal->logCopyTableRecord(table->getTableID()); wal->flushAllPages(); } - inline void setNumTuplesForTable() { table->setNumTuples(getNumRows()); } + inline void updateNumTuplesForTable() { table->updateNumTuplesByValue(getNumRows()); } }; struct BatchInsertLocalState { - std::unique_ptr nodeGroup; + std::unique_ptr nodeGroup; virtual ~BatchInsertLocalState() = default; }; diff --git a/src/include/processor/operator/persistent/copy_rdf.h b/src/include/processor/operator/persistent/copy_rdf.h index b186ed6f451..8397ed46bbf 100644 --- a/src/include/processor/operator/persistent/copy_rdf.h +++ b/src/include/processor/operator/persistent/copy_rdf.h @@ -24,8 +24,8 @@ class CopyRdf : public Sink { void finalize(ExecutionContext*) override; std::unique_ptr clone() override { - return std::make_unique( - sharedState, resultSetDescriptor->copy(), id, paramsString); + return std::make_unique(sharedState, resultSetDescriptor->copy(), id, + paramsString); } private: diff --git a/src/include/processor/operator/persistent/copy_to.h b/src/include/processor/operator/persistent/copy_to.h index 405286da45f..a46b30e0d86 100644 --- a/src/include/processor/operator/persistent/copy_to.h +++ b/src/include/processor/operator/persistent/copy_to.h @@ -48,8 +48,8 @@ class CopyTo : public Sink { std::shared_ptr sharedState, PhysicalOperatorType opType, std::unique_ptr child, uint32_t id, const std::string& paramsString) : Sink{std::move(resultSetDescriptor), opType, std::move(child), id, paramsString}, - info{std::move(info)}, localState{std::move(localState)}, sharedState{ - std::move(sharedState)} {} + info{std::move(info)}, localState{std::move(localState)}, + sharedState{std::move(sharedState)} {} void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) final; diff --git a/src/include/processor/operator/persistent/copy_to_csv.h b/src/include/processor/operator/persistent/copy_to_csv.h index e4fe6a602ab..23c22b91441 100644 --- a/src/include/processor/operator/persistent/copy_to_csv.h +++ b/src/include/processor/operator/persistent/copy_to_csv.h @@ -21,8 +21,8 @@ struct CopyToCSVInfo final : public CopyToInfo { uint64_t getNumFlatVectors(); inline std::unique_ptr copy() override { - return std::make_unique( - names, dataPoses, fileName, isFlat, copyToOption.copy()); + return std::make_unique(names, dataPoses, fileName, isFlat, + copyToOption.copy()); } }; @@ -49,7 +49,7 @@ class CopyToCSVLocalState final : public CopyToLocalState { std::unique_ptr unflatCastDataChunk; std::unique_ptr flatCastDataChunk; std::vector castVectors; - std::vector castFuncs; + std::vector castFuncs; std::vector> vectorsToCast; }; diff --git a/src/include/processor/operator/persistent/copy_to_parquet.h b/src/include/processor/operator/persistent/copy_to_parquet.h index 3e801857b3a..f0a22e112ef 100644 --- a/src/include/processor/operator/persistent/copy_to_parquet.h +++ b/src/include/processor/operator/persistent/copy_to_parquet.h @@ -13,16 +13,18 @@ struct CopyToParquetInfo final : public CopyToInfo { kuzu_parquet::format::CompressionCodec::SNAPPY; std::unique_ptr tableSchema; std::vector> types; + DataPos countingVecPos; CopyToParquetInfo(std::unique_ptr tableSchema, std::vector> types, std::vector names, - std::vector dataPoses, std::string fileName) + std::vector dataPoses, std::string fileName, DataPos countingVecPos) : CopyToInfo{std::move(names), std::move(dataPoses), std::move(fileName)}, - tableSchema{std::move(tableSchema)}, types{std::move(types)} {} + tableSchema{std::move(tableSchema)}, types{std::move(types)}, + countingVecPos{std::move(countingVecPos)} {} - inline std::unique_ptr copy() override { - return std::make_unique( - tableSchema->copy(), common::LogicalType::copy(types), names, dataPoses, fileName); + std::unique_ptr copy() override { + return std::make_unique(tableSchema->copy(), + common::LogicalType::copy(types), names, dataPoses, fileName, countingVecPos); } }; @@ -35,8 +37,10 @@ class CopyToParquetLocalState final : public CopyToLocalState { private: std::unique_ptr ft; + uint64_t numTuplesInFT; std::vector vectorsToAppend; storage::MemoryManager* mm; + common::ValueVector* countingVec; }; class CopyToParquetSharedState final : public CopyToSharedState { diff --git a/src/include/processor/operator/persistent/delete_executor.h b/src/include/processor/operator/persistent/delete_executor.h index 9cc55b268c6..c06e12ab63e 100644 --- a/src/include/processor/operator/persistent/delete_executor.h +++ b/src/include/processor/operator/persistent/delete_executor.h @@ -66,8 +66,8 @@ class MultiLabelNodeDeleteExecutor final : public NodeDeleteExecutor { std::unordered_map tableIDToBwdRelTablesMap, common::DeleteNodeType deleteType, const DataPos& nodeIDPos) : NodeDeleteExecutor(deleteType, nodeIDPos), - tableIDToTableMap{std::move(tableIDToTableMap)}, tableIDToFwdRelTablesMap{std::move( - tableIDToFwdRelTablesMap)}, + tableIDToTableMap{std::move(tableIDToTableMap)}, + tableIDToFwdRelTablesMap{std::move(tableIDToFwdRelTablesMap)}, tableIDToBwdRelTablesMap{std::move(tableIDToBwdRelTablesMap)} {} MultiLabelNodeDeleteExecutor(const MultiLabelNodeDeleteExecutor& other) : NodeDeleteExecutor(other.deleteType, other.nodeIDPos), @@ -91,8 +91,8 @@ class MultiLabelNodeDeleteExecutor final : public NodeDeleteExecutor { class RelDeleteExecutor { public: - RelDeleteExecutor( - const DataPos& srcNodeIDPos, const DataPos& dstNodeIDPos, const DataPos& relIDPos) + RelDeleteExecutor(const DataPos& srcNodeIDPos, const DataPos& dstNodeIDPos, + const DataPos& relIDPos) : srcNodeIDPos{srcNodeIDPos}, dstNodeIDPos{dstNodeIDPos}, relIDPos{relIDPos}, srcNodeIDVector(nullptr), dstNodeIDVector(nullptr), relIDVector(nullptr) {} virtual ~RelDeleteExecutor() = default; @@ -136,8 +136,8 @@ class MultiLabelRelDeleteExecutor final : public RelDeleteExecutor { MultiLabelRelDeleteExecutor( std::unordered_map tableIDToTableMap, const DataPos& srcNodeIDPos, const DataPos& dstNodeIDPos, const DataPos& relIDPos) - : RelDeleteExecutor(srcNodeIDPos, dstNodeIDPos, relIDPos), tableIDToTableMap{std::move( - tableIDToTableMap)} {} + : RelDeleteExecutor(srcNodeIDPos, dstNodeIDPos, relIDPos), + tableIDToTableMap{std::move(tableIDToTableMap)} {} MultiLabelRelDeleteExecutor(const MultiLabelRelDeleteExecutor& other) = default; void delete_(ExecutionContext* context) override; diff --git a/src/include/processor/operator/persistent/export_db.h b/src/include/processor/operator/persistent/export_db.h index fb94ba52095..3c7216d925b 100644 --- a/src/include/processor/operator/persistent/export_db.h +++ b/src/include/processor/operator/persistent/export_db.h @@ -21,8 +21,8 @@ class ExportDB : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) override; inline std::unique_ptr clone() override { - return std::make_unique( - std::move(boundFileInfo), id, paramsString, std::move(children)); + return std::make_unique(std::move(boundFileInfo), id, paramsString, + std::move(children)); } private: diff --git a/src/include/processor/operator/persistent/file_writer.h b/src/include/processor/operator/persistent/file_writer.h index 0fe52e373f4..f1d8b36bd5c 100644 --- a/src/include/processor/operator/persistent/file_writer.h +++ b/src/include/processor/operator/persistent/file_writer.h @@ -10,8 +10,8 @@ class FileWriter { public: FileWriter(std::string filePath, std::vector columnNames, std::vector> columnTypes) - : filePath{std::move(filePath)}, columnNames{std::move(columnNames)}, columnTypes{std::move( - columnTypes)} {} + : filePath{std::move(filePath)}, columnNames{std::move(columnNames)}, + columnTypes{std::move(columnTypes)} {} virtual ~FileWriter() = default; virtual void init() = 0; virtual void openFile() = 0; diff --git a/src/include/processor/operator/persistent/index_builder.h b/src/include/processor/operator/persistent/index_builder.h index 529e28e0724..ec4e4648740 100644 --- a/src/include/processor/operator/persistent/index_builder.h +++ b/src/include/processor/operator/persistent/index_builder.h @@ -16,9 +16,6 @@ namespace kuzu { namespace processor { -constexpr size_t BUFFER_SIZE = 1024; -template -using Buffer = common::StaticVector, BUFFER_SIZE>; const size_t SHOULD_FLUSH_QUEUE_SIZE = 32; class IndexBuilderGlobalQueues { @@ -28,7 +25,7 @@ class IndexBuilderGlobalQueues { void flushToDisk() const; template - void insert(size_t index, Buffer elem) { + void insert(size_t index, storage::IndexBuffer elem) { auto& typedQueues = std::get>(queues).array; typedQueues[index].push(std::move(elem)); if (typedQueues[index].approxSize() < SHOULD_FLUSH_QUEUE_SIZE) { @@ -49,7 +46,7 @@ class IndexBuilderGlobalQueues { template struct Queue { - std::array>, storage::NUM_HASH_INDEXES> array; + std::array>, storage::NUM_HASH_INDEXES> array; // Type information to help std::visit. Value is not used T type; }; @@ -92,7 +89,7 @@ class IndexBuilderLocalBuffers { // These arrays are much too large to be inline. template - using Buffers = std::array, storage::NUM_HASH_INDEXES>; + using Buffers = std::array, storage::NUM_HASH_INDEXES>; template using UniqueBuffers = std::unique_ptr>; std::variant, UniqueBuffers, UniqueBuffers, @@ -153,8 +150,8 @@ class IndexBuilder { IndexBuilder clone() { return IndexBuilder(sharedState); } - void insert( - storage::ColumnChunk* chunk, common::offset_t nodeOffset, common::offset_t numNodes); + void insert(const storage::ColumnChunk& chunk, common::offset_t nodeOffset, + common::offset_t numNodes); ProducerToken getProducerToken() const { return ProducerToken(sharedState); } @@ -162,7 +159,8 @@ class IndexBuilder { void finalize(ExecutionContext* context); private: - void checkNonNullConstraint(storage::NullColumnChunk* nullChunk, common::offset_t numNodes); + void checkNonNullConstraint(const storage::NullColumnChunk& nullChunk, + common::offset_t numNodes); std::shared_ptr sharedState; IndexBuilderLocalBuffers localBuffers; diff --git a/src/include/processor/operator/persistent/insert_executor.h b/src/include/processor/operator/persistent/insert_executor.h index 37164743dff..b74a0b14131 100644 --- a/src/include/processor/operator/persistent/insert_executor.h +++ b/src/include/processor/operator/persistent/insert_executor.h @@ -9,7 +9,6 @@ namespace kuzu { namespace processor { -// TODO(Guodong): the following class should be moved to storage. class NodeInsertExecutor { public: NodeInsertExecutor(storage::NodeTable* table, @@ -18,9 +17,9 @@ class NodeInsertExecutor { std::vector columnVectorsPos, std::vector> columnDataEvaluators, common::ConflictAction conflictAction) - : table{table}, fwdRelTables{std::move(fwdRelTables)}, bwdRelTables{std::move( - bwdRelTables)}, - nodeIDVectorPos{nodeIDVectorPos}, columnVectorsPos{std::move(columnVectorsPos)}, + : table{table}, fwdRelTables{std::move(fwdRelTables)}, + bwdRelTables{std::move(bwdRelTables)}, nodeIDVectorPos{nodeIDVectorPos}, + columnVectorsPos{std::move(columnVectorsPos)}, columnDataEvaluators{std::move(columnDataEvaluators)}, conflictAction{conflictAction}, nodeIDVector{nullptr} {} EXPLICIT_COPY_DEFAULT_MOVE(NodeInsertExecutor); @@ -29,9 +28,15 @@ class NodeInsertExecutor { void insert(transaction::Transaction* transaction, ExecutionContext* context); + void evaluateResult(ExecutionContext* context); + + void writeResult(); + private: NodeInsertExecutor(const NodeInsertExecutor& other); + bool checkConfict(transaction::Transaction* transaction); + private: // Node table to insert. storage::NodeTable* table; @@ -67,6 +72,8 @@ class RelInsertExecutor { void insert(transaction::Transaction* transaction, ExecutionContext* context); + void writeResult(); + private: RelInsertExecutor(const RelInsertExecutor& other); diff --git a/src/include/processor/operator/persistent/merge.h b/src/include/processor/operator/persistent/merge.h index 7eea1e3959b..f7488dec45e 100644 --- a/src/include/processor/operator/persistent/merge.h +++ b/src/include/processor/operator/persistent/merge.h @@ -9,7 +9,8 @@ namespace processor { class Merge : public PhysicalOperator { public: - Merge(const DataPos& markPos, std::vector nodeInsertExecutors, + Merge(const DataPos& existenceMark, const DataPos& distinctMark, + std::vector nodeInsertExecutors, std::vector relInsertExecutors, std::vector> onCreateNodeSetExecutors, std::vector> onCreateRelSetExecutors, @@ -17,9 +18,10 @@ class Merge : public PhysicalOperator { std::vector> onMatchRelSetExecutors, std::unique_ptr child, uint32_t id, const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::MERGE, std::move(child), id, paramsString}, - markPos{markPos}, nodeInsertExecutors{std::move(nodeInsertExecutors)}, - relInsertExecutors{std::move(relInsertExecutors)}, onCreateNodeSetExecutors{std::move( - onCreateNodeSetExecutors)}, + existenceMark{existenceMark}, distinctMark{distinctMark}, + nodeInsertExecutors{std::move(nodeInsertExecutors)}, + relInsertExecutors{std::move(relInsertExecutors)}, + onCreateNodeSetExecutors{std::move(onCreateNodeSetExecutors)}, onCreateRelSetExecutors{std::move(onCreateRelSetExecutors)}, onMatchNodeSetExecutors{std::move(onMatchNodeSetExecutors)}, onMatchRelSetExecutors{std::move(onMatchRelSetExecutors)} {} @@ -31,7 +33,7 @@ class Merge : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return std::make_unique(markPos, copyVector(nodeInsertExecutors), + return std::make_unique(existenceMark, distinctMark, copyVector(nodeInsertExecutors), copyVector(relInsertExecutors), NodeSetExecutor::copy(onCreateNodeSetExecutors), RelSetExecutor::copy(onCreateRelSetExecutors), NodeSetExecutor::copy(onMatchNodeSetExecutors), @@ -39,8 +41,10 @@ class Merge : public PhysicalOperator { } private: - DataPos markPos; - common::ValueVector* markVector = nullptr; + DataPos existenceMark; + DataPos distinctMark; + common::ValueVector* existenceVector = nullptr; + common::ValueVector* distinctVector = nullptr; std::vector nodeInsertExecutors; std::vector relInsertExecutors; diff --git a/src/include/processor/operator/persistent/node_batch_insert.h b/src/include/processor/operator/persistent/node_batch_insert.h index b1a4c14f644..26a2dd940a4 100644 --- a/src/include/processor/operator/persistent/node_batch_insert.h +++ b/src/include/processor/operator/persistent/node_batch_insert.h @@ -4,7 +4,7 @@ #include "processor/operator/call/in_query_call.h" #include "processor/operator/persistent/batch_insert.h" #include "processor/operator/persistent/index_builder.h" -#include "storage/store/node_group.h" +#include "storage/store/chunked_node_group.h" #include "storage/store/node_table.h" namespace kuzu { @@ -13,11 +13,11 @@ namespace processor { struct NodeBatchInsertInfo final : public BatchInsertInfo { std::vector columnPositions; bool containSerial = false; - std::vector> columnTypes; + std::vector columnTypes; NodeBatchInsertInfo(catalog::TableCatalogEntry* tableEntry, bool compressionEnabled, std::vector columnPositions, bool containSerial, - std::vector> columnTypes) + std::vector columnTypes) : BatchInsertInfo{tableEntry, compressionEnabled}, columnPositions{columnPositions}, containSerial{containSerial}, columnTypes{std::move(columnTypes)} {} @@ -44,10 +44,10 @@ struct NodeBatchInsertSharedState final : public BatchInsertSharedState { uint64_t currentNodeGroupIdx; // The sharedNodeGroup is to accumulate left data within local node groups in NodeBatchInsert // ops. - std::unique_ptr sharedNodeGroup; + std::unique_ptr sharedNodeGroup; - NodeBatchInsertSharedState( - storage::Table* table, std::shared_ptr fTable, storage::WAL* wal) + NodeBatchInsertSharedState(storage::Table* table, std::shared_ptr fTable, + storage::WAL* wal) : BatchInsertSharedState{table, fTable, wal}, readerSharedState{nullptr}, distinctSharedState{nullptr}, currentNodeGroupIdx{0}, sharedNodeGroup{nullptr} {}; @@ -60,7 +60,7 @@ struct NodeBatchInsertSharedState final : public BatchInsertSharedState { inline uint64_t getCurNodeGroupIdx() const { return currentNodeGroupIdx; } - void appendIncompleteNodeGroup(std::unique_ptr localNodeGroup, + void appendIncompleteNodeGroup(std::unique_ptr localNodeGroup, std::optional& indexBuilder); inline common::offset_t getNextNodeGroupIdxWithoutLock() { return currentNodeGroupIdx++; } @@ -107,7 +107,7 @@ class NodeBatchInsert final : public BatchInsert { static void writeAndResetNodeGroup(common::node_group_idx_t nodeGroupIdx, std::optional& indexBuilder, common::column_id_t pkColumnID, - storage::NodeTable* table, storage::NodeGroup* nodeGroup); + storage::NodeTable* table, storage::ChunkedNodeGroup* nodeGroup); private: void copyToNodeGroup(); diff --git a/src/include/processor/operator/persistent/reader/csv/base_csv_reader.h b/src/include/processor/operator/persistent/reader/csv/base_csv_reader.h index 9a904781730..59ff9933f88 100644 --- a/src/include/processor/operator/persistent/reader/csv/base_csv_reader.h +++ b/src/include/processor/operator/persistent/reader/csv/base_csv_reader.h @@ -26,6 +26,9 @@ class BaseCSVReader { uint64_t countRows(); bool isEOF() const; + uint64_t getFileSize(); + // Get the file offset of the current buffer position. + uint64_t getFileOffset() const; protected: template @@ -56,8 +59,6 @@ class BaseCSVReader { inline bool isNewLine(char c) { return c == '\n' || c == '\r'; } - // Get the file offset of the current buffer position. - uint64_t getFileOffset() const; uint64_t getLineNumber(); protected: diff --git a/src/include/processor/operator/persistent/reader/csv/parallel_csv_reader.h b/src/include/processor/operator/persistent/reader/csv/parallel_csv_reader.h index 742c78d8c13..bd078762015 100644 --- a/src/include/processor/operator/persistent/reader/csv/parallel_csv_reader.h +++ b/src/include/processor/operator/persistent/reader/csv/parallel_csv_reader.h @@ -2,7 +2,7 @@ #include "base_csv_reader.h" #include "common/types/types.h" -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/bind_input.h" #include "function/table/scan_functions.h" #include "function/table_functions.h" @@ -39,15 +39,18 @@ struct ParallelCSVScanSharedState final : public function::ScanFileSharedState { explicit ParallelCSVScanSharedState(common::ReaderConfig readerConfig, uint64_t numRows, uint64_t numColumns, main::ClientContext* context, common::CSVReaderConfig csvReaderConfig) : ScanFileSharedState{std::move(readerConfig), numRows, context}, numColumns{numColumns}, - csvReaderConfig{std::move(csvReaderConfig)} {} + numBlocksReadByFiles{0}, csvReaderConfig{std::move(csvReaderConfig)} {} void setFileComplete(uint64_t completedFileIdx); uint64_t numColumns; + uint64_t numBlocksReadByFiles = 0; common::CSVReaderConfig csvReaderConfig; }; struct ParallelCSVScan { + static constexpr const char* name = "READ_CSV_PARALLEL"; + static function::function_set getFunctionSet(); }; diff --git a/src/include/processor/operator/persistent/reader/csv/serial_csv_reader.h b/src/include/processor/operator/persistent/reader/csv/serial_csv_reader.h index 072e5332d69..fc20f180bba 100644 --- a/src/include/processor/operator/persistent/reader/csv/serial_csv_reader.h +++ b/src/include/processor/operator/persistent/reader/csv/serial_csv_reader.h @@ -1,7 +1,7 @@ #pragma once #include "base_csv_reader.h" -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/bind_input.h" #include "function/table/scan_functions.h" @@ -25,12 +25,13 @@ class SerialCSVReader final : public BaseCSVReader { struct SerialCSVScanSharedState final : public function::ScanFileSharedState { std::unique_ptr reader; uint64_t numColumns; + uint64_t totalReadSizeByFile; common::CSVReaderConfig csvReaderConfig; SerialCSVScanSharedState(common::ReaderConfig readerConfig, uint64_t numRows, uint64_t numColumns, common::CSVReaderConfig csvReaderConfig, main::ClientContext* context) : ScanFileSharedState{std::move(readerConfig), numRows, context}, numColumns{numColumns}, - csvReaderConfig{std::move(csvReaderConfig)} { + totalReadSizeByFile{0}, csvReaderConfig{std::move(csvReaderConfig)} { initReader(context); } @@ -40,6 +41,8 @@ struct SerialCSVScanSharedState final : public function::ScanFileSharedState { }; struct SerialCSVScan { + static constexpr const char* name = "READ_CSV_SERIAL"; + static function::function_set getFunctionSet(); static void bindColumns(const function::ScanTableFuncBindInput* bindInput, std::vector& columnNames, std::vector& columnTypes); diff --git a/src/include/processor/operator/persistent/reader/npy/npy_reader.h b/src/include/processor/operator/persistent/reader/npy/npy_reader.h index 6a3494b27e7..c2a76f85aeb 100644 --- a/src/include/processor/operator/persistent/reader/npy/npy_reader.h +++ b/src/include/processor/operator/persistent/reader/npy/npy_reader.h @@ -5,7 +5,7 @@ #include "common/data_chunk/data_chunk.h" #include "common/types/types.h" -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/scan_functions.h" namespace kuzu { @@ -62,6 +62,8 @@ struct NpyScanSharedState final : public function::ScanSharedState { }; struct NpyScanFunction { + static constexpr const char* name = "READ_NPY"; + static function::function_set getFunctionSet(); }; diff --git a/src/include/processor/operator/persistent/reader/parquet/boolean_column_reader.h b/src/include/processor/operator/persistent/reader/parquet/boolean_column_reader.h index 5961b23cf35..ed8db5ef80d 100644 --- a/src/include/processor/operator/persistent/reader/parquet/boolean_column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/boolean_column_reader.h @@ -16,8 +16,8 @@ class BooleanColumnReader : public TemplatedColumnReader type, const kuzu_parquet::format::SchemaElement& schema, uint64_t schemaIdx, uint64_t maxDefine, uint64_t maxRepeat) - : TemplatedColumnReader( - reader, std::move(type), schema, schemaIdx, maxDefine, maxRepeat), + : TemplatedColumnReader(reader, std::move(type), + schema, schemaIdx, maxDefine, maxRepeat), bytePos(0){}; uint8_t bytePos; diff --git a/src/include/processor/operator/persistent/reader/parquet/callback_column_reader.h b/src/include/processor/operator/persistent/reader/parquet/callback_column_reader.h index ecfef53094f..b66ba250ab0 100644 --- a/src/include/processor/operator/persistent/reader/parquet/callback_column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/callback_column_reader.h @@ -23,12 +23,12 @@ class CallbackColumnReader const kuzu_parquet::format::SchemaElement& schema_p, uint64_t file_idx_p, uint64_t max_define_p, uint64_t max_repeat_p) : TemplatedColumnReader>( - reader, std::move(type_p), schema_p, file_idx_p, max_define_p, max_repeat_p) {} + CallbackParquetValueConversion>(reader, + std::move(type_p), schema_p, file_idx_p, max_define_p, max_repeat_p) {} protected: - void dictionary( - const std::shared_ptr& dictionaryData, uint64_t numEntries) override { + void dictionary(const std::shared_ptr& dictionaryData, + uint64_t numEntries) override { BaseType::allocateDict(numEntries * sizeof(KU_PHYSICAL_TYPE)); auto dictPtr = (KU_PHYSICAL_TYPE*)this->dict->ptr; for (auto i = 0u; i < numEntries; i++) { diff --git a/src/include/processor/operator/persistent/reader/parquet/column_reader.h b/src/include/processor/operator/persistent/reader/parquet/column_reader.h index 9a61863b652..6766daddda3 100644 --- a/src/include/processor/operator/persistent/reader/parquet/column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/column_reader.h @@ -27,8 +27,8 @@ class ColumnReader { inline bool hasDefines() const { return maxDefine > 0; } inline bool hasRepeats() const { return maxRepeat > 0; } virtual inline void skip(uint64_t numValues) { pendingSkips += numValues; } - virtual inline void dictionary( - const std::shared_ptr& /*data*/, uint64_t /*num_entries*/) { + virtual inline void dictionary(const std::shared_ptr& /*data*/, + uint64_t /*num_entries*/) { KU_UNREACHABLE; } virtual inline void offsets(uint32_t* /*offsets*/, uint8_t* /*defines*/, uint64_t /*numValues*/, diff --git a/src/include/processor/operator/persistent/reader/parquet/decode_utils.h b/src/include/processor/operator/persistent/reader/parquet/decode_utils.h index 3cd2e29b2ca..430db31d63e 100644 --- a/src/include/processor/operator/persistent/reader/parquet/decode_utils.h +++ b/src/include/processor/operator/persistent/reader/parquet/decode_utils.h @@ -19,8 +19,8 @@ class ParquetDecodeUtils { static const uint8_t BITPACK_DLEN; template - static uint32_t BitUnpack( - ByteBuffer& buffer, uint8_t& bitpack_pos, T* dest, uint32_t count, uint8_t width) { + static uint32_t BitUnpack(ByteBuffer& buffer, uint8_t& bitpack_pos, T* dest, uint32_t count, + uint8_t width) { if (width >= ParquetDecodeUtils::BITPACK_MASKS_SIZE) { throw common::CopyException(common::stringFormat( "The width ({}) of the bitpacked data exceeds the supported max width ({}), " diff --git a/src/include/processor/operator/persistent/reader/parquet/interval_column_reader.h b/src/include/processor/operator/persistent/reader/parquet/interval_column_reader.h index 31297e048a3..41eb1d1b99b 100644 --- a/src/include/processor/operator/persistent/reader/parquet/interval_column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/interval_column_reader.h @@ -7,8 +7,8 @@ namespace kuzu { namespace processor { struct IntervalValueConversion { - static inline common::interval_t dictRead( - ByteBuffer& dict, uint32_t& offset, ColumnReader& /*reader*/) { + static inline common::interval_t dictRead(ByteBuffer& dict, uint32_t& offset, + ColumnReader& /*reader*/) { return (reinterpret_cast(dict.ptr))[offset]; } @@ -28,12 +28,12 @@ class IntervalColumnReader IntervalColumnReader(ParquetReader& reader, std::unique_ptr type, const kuzu_parquet::format::SchemaElement& schema, uint64_t fileIdx, uint64_t maxDefine, uint64_t maxRepeat) - : TemplatedColumnReader( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat){}; + : TemplatedColumnReader(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat){}; protected: - void dictionary( - const std::shared_ptr& dictionary_data, uint64_t num_entries) override; + void dictionary(const std::shared_ptr& dictionary_data, + uint64_t num_entries) override; }; } // namespace processor diff --git a/src/include/processor/operator/persistent/reader/parquet/list_column_reader.h b/src/include/processor/operator/persistent/reader/parquet/list_column_reader.h index 1e94f8757df..de3aea6cb05 100644 --- a/src/include/processor/operator/persistent/reader/parquet/list_column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/list_column_reader.h @@ -7,7 +7,7 @@ namespace processor { class ListColumnReader : public ColumnReader { public: - static constexpr const common::PhysicalTypeID TYPE = common::PhysicalTypeID::VAR_LIST; + static constexpr const common::PhysicalTypeID TYPE = common::PhysicalTypeID::LIST; public: ListColumnReader(ParquetReader& reader, std::unique_ptr type, diff --git a/src/include/processor/operator/persistent/reader/parquet/parquet_reader.h b/src/include/processor/operator/persistent/reader/parquet/parquet_reader.h index 9f6ada7b526..b39a0c12df1 100644 --- a/src/include/processor/operator/persistent/reader/parquet/parquet_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/parquet_reader.h @@ -3,7 +3,7 @@ #include "column_reader.h" #include "common/data_chunk/data_chunk.h" #include "common/types/types.h" -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/bind_input.h" #include "function/table/scan_functions.h" #include "parquet/parquet_types.h" @@ -91,10 +91,12 @@ class ParquetReader { }; struct ParquetScanSharedState final : public function::ScanFileSharedState { - explicit ParquetScanSharedState( - const common::ReaderConfig readerConfig, uint64_t numRows, main::ClientContext* context); + explicit ParquetScanSharedState(const common::ReaderConfig readerConfig, uint64_t numRows, + main::ClientContext* context); std::vector> readers; + uint64_t totalRowsGroups; + uint64_t numBlocksReadByFiles; }; struct ParquetScanLocalState final : public function::TableFuncLocalState { @@ -105,6 +107,8 @@ struct ParquetScanLocalState final : public function::TableFuncLocalState { }; struct ParquetScanFunction { + static constexpr const char* name = "READ_PARQUET"; + static function::function_set getFunctionSet(); }; diff --git a/src/include/processor/operator/persistent/reader/parquet/parquet_rle_bp_decoder.h b/src/include/processor/operator/persistent/reader/parquet/parquet_rle_bp_decoder.h index 65a62ea4de3..95ecabe8def 100644 --- a/src/include/processor/operator/persistent/reader/parquet/parquet_rle_bp_decoder.h +++ b/src/include/processor/operator/persistent/reader/parquet/parquet_rle_bp_decoder.h @@ -27,17 +27,17 @@ class RleBpDecoder { while (values_read < batch_size) { if (repeat_count_ > 0) { - int repeat_batch = std::min( - batch_size - values_read, static_cast(repeat_count_)); + int repeat_batch = std::min(batch_size - values_read, + static_cast(repeat_count_)); std::fill(values + values_read, values + values_read + repeat_batch, static_cast(current_value_)); repeat_count_ -= repeat_batch; values_read += repeat_batch; } else if (literal_count_ > 0) { - uint32_t literal_batch = std::min( - batch_size - values_read, static_cast(literal_count_)); - uint32_t actual_read = ParquetDecodeUtils::BitUnpack( - buffer_, bitpack_pos, values + values_read, literal_batch, bit_width_); + uint32_t literal_batch = std::min(batch_size - values_read, + static_cast(literal_count_)); + uint32_t actual_read = ParquetDecodeUtils::BitUnpack(buffer_, bitpack_pos, + values + values_read, literal_batch, bit_width_); if (literal_batch != actual_read) { throw std::runtime_error("Did not find enough values"); } diff --git a/src/include/processor/operator/persistent/reader/parquet/string_column_reader.h b/src/include/processor/operator/persistent/reader/parquet/string_column_reader.h index 97b53906973..06859b6b785 100644 --- a/src/include/processor/operator/persistent/reader/parquet/string_column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/string_column_reader.h @@ -28,8 +28,8 @@ class StringColumnReader uint64_t fixedWidthStringLength; public: - void dictionary( - const std::shared_ptr& dictionary_data, uint64_t numEntries) override; + void dictionary(const std::shared_ptr& dictionary_data, + uint64_t numEntries) override; static uint32_t verifyString(const char* strData, uint32_t strLen, const bool isVarchar); uint32_t verifyString(const char* strData, uint32_t strLen); }; diff --git a/src/include/processor/operator/persistent/reader/parquet/templated_column_reader.h b/src/include/processor/operator/persistent/reader/parquet/templated_column_reader.h index 55552c88ebb..0980127ce6e 100644 --- a/src/include/processor/operator/persistent/reader/parquet/templated_column_reader.h +++ b/src/include/processor/operator/persistent/reader/parquet/templated_column_reader.h @@ -64,12 +64,12 @@ class TemplatedColumnReader : public ColumnReader { void plain(const std::shared_ptr& plainData, uint8_t* defines, uint64_t numValues, parquet_filter_t& filter, uint64_t resultOffset, common::ValueVector* result) override { - plainTemplated( - plainData, defines, numValues, filter, resultOffset, result); + plainTemplated(plainData, defines, numValues, filter, + resultOffset, result); } - void dictionary( - const std::shared_ptr& data, uint64_t /*num_entries*/) override { + void dictionary(const std::shared_ptr& data, + uint64_t /*num_entries*/) override { dict = data; } }; @@ -78,8 +78,8 @@ template struct CallbackParquetValueConversion { static DUCKDB_PHYSICAL_TYPE dictRead(ByteBuffer& dict, uint32_t& offset, ColumnReader& reader) { - return TemplatedParquetValueConversion::dictRead( - dict, offset, reader); + return TemplatedParquetValueConversion::dictRead(dict, offset, + reader); } static DUCKDB_PHYSICAL_TYPE plainRead(ByteBuffer& plainData, ColumnReader& /*reader*/) { diff --git a/src/include/processor/operator/persistent/reader/parquet/thrift_tools.h b/src/include/processor/operator/persistent/reader/parquet/thrift_tools.h index 3181b0c3add..a7ad305c28c 100644 --- a/src/include/processor/operator/persistent/reader/parquet/thrift_tools.h +++ b/src/include/processor/operator/persistent/reader/parquet/thrift_tools.h @@ -130,8 +130,8 @@ class ThriftFileTransport if (!prefetch_buffer->data_isset) { prefetch_buffer->Allocate(); - handle->readFromFile( - prefetch_buffer->data.get(), prefetch_buffer->size, prefetch_buffer->location); + handle->readFromFile(prefetch_buffer->data.get(), prefetch_buffer->size, + prefetch_buffer->location); prefetch_buffer->data_isset = true; } memcpy(buf, prefetch_buffer->data.get() + location - prefetch_buffer->location, len); diff --git a/src/include/processor/operator/persistent/reader/rdf/rdf_reader.h b/src/include/processor/operator/persistent/reader/rdf/rdf_reader.h index 78f9e28fd02..5307f249f3b 100644 --- a/src/include/processor/operator/persistent/reader/rdf/rdf_reader.h +++ b/src/include/processor/operator/persistent/reader/rdf/rdf_reader.h @@ -29,10 +29,9 @@ class RdfReader { protected: RdfReader(common::RdfReaderConfig rdfConfig, uint32_t fileIdx, std::string filePath, common::FileType fileType, RdfStore* store_, const common::offset_t startOffset) - : store_{store_}, cursor{0}, startOffset{startOffset}, - numLiteralTriplesScanned{0}, rdfConfig{std::move(rdfConfig)}, fileIdx{fileIdx}, - filePath{std::move(filePath)}, fileType{fileType}, reader{nullptr}, status{SERD_SUCCESS} { - } + : store_{store_}, cursor{0}, startOffset{startOffset}, numLiteralTriplesScanned{0}, + rdfConfig{std::move(rdfConfig)}, fileIdx{fileIdx}, filePath{std::move(filePath)}, + fileType{fileType}, reader{nullptr}, status{SERD_SUCCESS} {} void initInternal(SerdStatementSink statementHandle); diff --git a/src/include/processor/operator/persistent/reader/rdf/rdf_scan.h b/src/include/processor/operator/persistent/reader/rdf/rdf_scan.h index a9eaa214191..ec53afeed62 100644 --- a/src/include/processor/operator/persistent/reader/rdf/rdf_scan.h +++ b/src/include/processor/operator/persistent/reader/rdf/rdf_scan.h @@ -1,6 +1,6 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/bind_data.h" #include "function/table/scan_functions.h" #include "rdf_reader.h" @@ -17,8 +17,8 @@ struct RdfScanSharedState : public function::ScanSharedState { std::shared_ptr store) : ScanSharedState{std::move(readerConfig), 0}, rdfConfig{std::move(rdfConfig)}, store{std::move(store)}, numLiteralTriplesScanned{0} {} - explicit RdfScanSharedState( - common::ReaderConfig readerConfig, common::RdfReaderConfig rdfConfig) + explicit RdfScanSharedState(common::ReaderConfig readerConfig, + common::RdfReaderConfig rdfConfig) : RdfScanSharedState{std::move(readerConfig), std::move(rdfConfig), nullptr} {} void read(common::DataChunk& dataChunk); @@ -27,16 +27,16 @@ struct RdfScanSharedState : public function::ScanSharedState { void initReader(); private: - virtual void createReader( - uint32_t fileIdx, const std::string& path, common::offset_t startOffset) = 0; + virtual void createReader(uint32_t fileIdx, const std::string& path, + common::offset_t startOffset) = 0; common::offset_t numLiteralTriplesScanned; }; struct RdfResourceScanSharedState final : public RdfScanSharedState { - explicit RdfResourceScanSharedState( - common::ReaderConfig readerConfig, common::RdfReaderConfig rdfConfig) + explicit RdfResourceScanSharedState(common::ReaderConfig readerConfig, + common::RdfReaderConfig rdfConfig) : RdfScanSharedState{std::move(readerConfig), std::move(rdfConfig)} { KU_ASSERT(store == nullptr); store = std::make_shared(); @@ -44,15 +44,15 @@ struct RdfResourceScanSharedState final : public RdfScanSharedState { } inline void createReader(uint32_t fileIdx, const std::string& path, common::offset_t) override { - reader = std::make_unique( - rdfConfig, fileIdx, path, readerConfig.fileType, store.get()); + reader = std::make_unique(rdfConfig, fileIdx, path, + readerConfig.fileType, store.get()); } }; struct RdfLiteralScanSharedState final : public RdfScanSharedState { - explicit RdfLiteralScanSharedState( - common::ReaderConfig readerConfig, common::RdfReaderConfig rdfConfig) + explicit RdfLiteralScanSharedState(common::ReaderConfig readerConfig, + common::RdfReaderConfig rdfConfig) : RdfScanSharedState{std::move(readerConfig), std::move(rdfConfig)} { KU_ASSERT(store == nullptr); store = std::make_shared(); @@ -60,15 +60,15 @@ struct RdfLiteralScanSharedState final : public RdfScanSharedState { } inline void createReader(uint32_t fileIdx, const std::string& path, common::offset_t) override { - reader = std::make_unique( - rdfConfig, fileIdx, path, readerConfig.fileType, store.get()); + reader = std::make_unique(rdfConfig, fileIdx, path, readerConfig.fileType, + store.get()); } }; struct RdfResourceTripleScanSharedState final : public RdfScanSharedState { - explicit RdfResourceTripleScanSharedState( - common::ReaderConfig readerConfig, common::RdfReaderConfig rdfConfig) + explicit RdfResourceTripleScanSharedState(common::ReaderConfig readerConfig, + common::RdfReaderConfig rdfConfig) : RdfScanSharedState{std::move(readerConfig), std::move(rdfConfig)} { KU_ASSERT(store == nullptr); store = std::make_shared(); @@ -76,25 +76,25 @@ struct RdfResourceTripleScanSharedState final : public RdfScanSharedState { } inline void createReader(uint32_t fileIdx, const std::string& path, common::offset_t) override { - reader = std::make_unique( - rdfConfig, fileIdx, path, readerConfig.fileType, store.get()); + reader = std::make_unique(rdfConfig, fileIdx, path, + readerConfig.fileType, store.get()); } }; struct RdfLiteralTripleScanSharedState final : public RdfScanSharedState { - explicit RdfLiteralTripleScanSharedState( - common::ReaderConfig readerConfig, common::RdfReaderConfig rdfConfig) + explicit RdfLiteralTripleScanSharedState(common::ReaderConfig readerConfig, + common::RdfReaderConfig rdfConfig) : RdfScanSharedState{std::move(readerConfig), std::move(rdfConfig)} { KU_ASSERT(store == nullptr); store = std::make_shared(); initReader(); } - void createReader( - uint32_t fileIdx, const std::string& path, common::offset_t startOffset) override { - reader = std::make_unique( - rdfConfig, fileIdx, path, readerConfig.fileType, store.get(), startOffset); + void createReader(uint32_t fileIdx, const std::string& path, + common::offset_t startOffset) override { + reader = std::make_unique(rdfConfig, fileIdx, path, + readerConfig.fileType, store.get(), startOffset); } }; @@ -107,8 +107,8 @@ struct RdfTripleScanSharedState final : public RdfScanSharedState { } void createReader(uint32_t fileIdx, const std::string& path, common::offset_t) override { - reader = std::make_unique( - rdfConfig, fileIdx, path, readerConfig.fileType, store.get()); + reader = std::make_unique(rdfConfig, fileIdx, path, readerConfig.fileType, + store.get()); } }; @@ -154,70 +154,57 @@ struct RdfInMemScanSharedState : public function::BaseScanSharedState { }; struct RdfResourceScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "READ_RDF_RESOURCE"; - static std::unique_ptr initSharedState( - function::TableFunctionInitInput& input); + static function::function_set getFunctionSet(); }; struct RdfLiteralScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "READ_RDF_LITERAL"; - static std::unique_ptr initSharedState( - function::TableFunctionInitInput& input); + static function::function_set getFunctionSet(); }; struct RdfResourceTripleScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "READ_RDF_RESOURCE_TRIPLE"; - static std::unique_ptr initSharedState( - function::TableFunctionInitInput& input); + static function::function_set getFunctionSet(); }; struct RdfLiteralTripleScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "READ_RDF_LITERAL_TRIPLE"; - static std::unique_ptr initSharedState( - function::TableFunctionInitInput& input); + static function::function_set getFunctionSet(); }; struct RdfAllTripleScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "READ_RDF_ALL_TRIPLE"; - static common::offset_t tableFunc( - function::TableFuncInput& input, function::TableFuncOutput& output); - static std::unique_ptr bindFunc( - main::ClientContext*, function::TableFuncBindInput* input_); - static std::unique_ptr initSharedState( - function::TableFunctionInitInput& input); + static function::function_set getFunctionSet(); }; struct RdfResourceInMemScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "IN_MEM_READ_RDF_RESOURCE"; - static common::offset_t tableFunc( - function::TableFuncInput& input, function::TableFuncOutput& output); + static function::function_set getFunctionSet(); }; struct RdfLiteralInMemScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "IN_MEM_READ_RDF_LITERAL"; - static common::offset_t tableFunc( - function::TableFuncInput& input, function::TableFuncOutput& output); + static function::function_set getFunctionSet(); }; struct RdfResourceTripleInMemScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "IN_MEM_READ_RDF_RESOURCE_TRIPLE"; - static common::offset_t tableFunc( - function::TableFuncInput& input, function::TableFuncOutput& output); + static function::function_set getFunctionSet(); }; struct RdfLiteralTripleInMemScan { - static function::function_set getFunctionSet(); + static constexpr const char* name = "IN_MEM_READ_RDF_LITERAL_TRIPLE"; - static common::offset_t tableFunc( - function::TableFuncInput& input, function::TableFuncOutput& output); + static function::function_set getFunctionSet(); }; } // namespace processor diff --git a/src/include/processor/operator/persistent/rel_batch_insert.h b/src/include/processor/operator/persistent/rel_batch_insert.h index ed10d2091f7..a026665315a 100644 --- a/src/include/processor/operator/persistent/rel_batch_insert.h +++ b/src/include/processor/operator/persistent/rel_batch_insert.h @@ -3,7 +3,8 @@ #include "common/enums/rel_direction.h" #include "processor/operator/partitioner.h" #include "processor/operator/persistent/batch_insert.h" -#include "storage/store/node_group.h" +#include "storage/store/chunked_node_group.h" +#include "storage/store/column_chunk.h" namespace kuzu { namespace processor { @@ -11,19 +12,18 @@ namespace processor { struct RelBatchInsertInfo final : public BatchInsertInfo { common::RelDataDirection direction; uint64_t partitioningIdx; - common::vector_idx_t offsetVectorIdx; - std::vector> columnTypes; + common::column_id_t offsetColumnID; + std::vector columnTypes; RelBatchInsertInfo(catalog::TableCatalogEntry* tableEntry, bool compressionEnabled, common::RelDataDirection direction, uint64_t partitioningIdx, - common::vector_idx_t offsetVectorIdx, - std::vector> columnTypes) + common::column_id_t offsetColumnID, std::vector columnTypes) : BatchInsertInfo{tableEntry, compressionEnabled}, direction{direction}, - partitioningIdx{partitioningIdx}, offsetVectorIdx{offsetVectorIdx}, columnTypes{std::move( - columnTypes)} {} + partitioningIdx{partitioningIdx}, offsetColumnID{offsetColumnID}, + columnTypes{std::move(columnTypes)} {} RelBatchInsertInfo(const RelBatchInsertInfo& other) : BatchInsertInfo{other.tableEntry, other.compressionEnabled}, direction{other.direction}, - partitioningIdx{other.partitioningIdx}, offsetVectorIdx{other.offsetVectorIdx}, + partitioningIdx{other.partitioningIdx}, offsetColumnID{other.offsetColumnID}, columnTypes{common::LogicalType::copy(other.columnTypes)} {} inline std::unique_ptr copy() const override { @@ -60,24 +60,30 @@ class RelBatchInsert final : public BatchInsert { } private: - void prepareCSRNodeGroup(common::DataChunkCollection* partition, - common::offset_t startNodeOffset, common::vector_idx_t offsetVectorIdx, - common::offset_t numNodes); + static void appendNewNodeGroup(const RelBatchInsertInfo& relInfo, + RelBatchInsertLocalState& localState, BatchInsertSharedState& sharedState, + const PartitionerSharedState& partitionerSharedState); + static void mergeNodeGroup(ExecutionContext* context, const RelBatchInsertInfo& relInfo, + RelBatchInsertLocalState& localState, BatchInsertSharedState& sharedState, + const PartitionerSharedState& partitionerSharedState); + + static void prepareCSRNodeGroup(const storage::ChunkedNodeGroupCollection& partition, + common::offset_t startNodeOffset, const RelBatchInsertInfo& relInfo, + RelBatchInsertLocalState& localState, common::offset_t numNodes); static common::length_t getGapSize(common::length_t length); static std::vector populateStartCSROffsetsAndLengths( - storage::CSRHeaderChunks& csrHeader, common::offset_t numNodes, - common::DataChunkCollection* partition, common::vector_idx_t offsetVectorIdx); - static void populateEndCSROffsets( - storage::CSRHeaderChunks& csrHeader, std::vector& gaps); - static void setOffsetToWithinNodeGroup( - common::ValueVector* vector, common::offset_t startOffset); - static void setOffsetFromCSROffsets( - common::ValueVector* offsetVector, storage::ColumnChunk* offsetChunk); - - // We only check rel multiplcity constraint (MANY_ONE, ONE_ONE) for now. - std::optional checkRelMultiplicityConstraint( - const storage::CSRHeaderChunks& csrHeader); + storage::ChunkedCSRHeader& csrHeader, common::offset_t numNodes, + const storage::ChunkedNodeGroupCollection& partition, common::column_id_t offsetColumnID); + static void populateEndCSROffsets(storage::ChunkedCSRHeader& csrHeader, + std::vector& gaps); + static void setOffsetToWithinNodeGroup(storage::ColumnChunk& chunk, + common::offset_t startOffset); + static void setOffsetFromCSROffsets(storage::ColumnChunk& nodeOffsetChunk, + storage::ColumnChunk& csrOffsetChunk); + + static std::optional checkRelMultiplicityConstraint( + const storage::ChunkedCSRHeader& csrHeader, const RelBatchInsertInfo& relInfo); private: std::shared_ptr partitionerSharedState; diff --git a/src/include/processor/operator/persistent/set.h b/src/include/processor/operator/persistent/set.h index e8d8ff7985b..198a2682f4d 100644 --- a/src/include/processor/operator/persistent/set.h +++ b/src/include/processor/operator/persistent/set.h @@ -21,8 +21,8 @@ class SetNodeProperty : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return make_unique( - NodeSetExecutor::copy(executors), children[0]->clone(), id, paramsString); + return make_unique(NodeSetExecutor::copy(executors), children[0]->clone(), + id, paramsString); } private: @@ -44,8 +44,8 @@ class SetRelProperty : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return make_unique( - RelSetExecutor::copy(executors), children[0]->clone(), id, paramsString); + return make_unique(RelSetExecutor::copy(executors), children[0]->clone(), + id, paramsString); } private: diff --git a/src/include/processor/operator/persistent/writer/parquet/basic_column_writer.h b/src/include/processor/operator/persistent/writer/parquet/basic_column_writer.h index 4b38ad4bf80..57dafd66728 100644 --- a/src/include/processor/operator/persistent/writer/parquet/basic_column_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/basic_column_writer.h @@ -26,8 +26,8 @@ class BasicColumnWriter : public ColumnWriter { BasicColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schemaPath, uint64_t maxRepeat, uint64_t maxDefine, bool canHaveNulls) - : ColumnWriter( - writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, canHaveNulls) {} + : ColumnWriter(writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, + canHaveNulls) {} public: std::unique_ptr initializeWriteState( @@ -61,12 +61,12 @@ class BasicColumnWriter : public ColumnWriter { } // Flushes the writer for a specific page. Only used for scalar types. - virtual void flushPageState( - common::Serializer& /*bufferedSerializer*/, ColumnWriterPageState* /*state*/) {} + virtual void flushPageState(common::Serializer& /*bufferedSerializer*/, + ColumnWriterPageState* /*state*/) {} // Retrieves the row size of a vector at the specified location. Only used for scalar types. - virtual uint64_t getRowSize( - common::ValueVector* /*vector*/, uint64_t /*index*/, BasicColumnWriterState& /*state*/) { + virtual uint64_t getRowSize(common::ValueVector* /*vector*/, uint64_t /*index*/, + BasicColumnWriterState& /*state*/) { KU_UNREACHABLE; } // Writes a (subset of a) vector to the specified serializer. Only used for scalar types. @@ -79,13 +79,13 @@ class BasicColumnWriter : public ColumnWriter { virtual uint64_t dictionarySize(BasicColumnWriterState& /*writerState*/) { KU_UNREACHABLE; } void writeDictionary(BasicColumnWriterState& state, std::unique_ptr bufferedSerializer, uint64_t rowCount); - virtual void flushDictionary( - BasicColumnWriterState& /*state*/, ColumnWriterStatistics* /*stats*/) { + virtual void flushDictionary(BasicColumnWriterState& /*state*/, + ColumnWriterStatistics* /*stats*/) { KU_UNREACHABLE; } - void setParquetStatistics( - BasicColumnWriterState& state, kuzu_parquet::format::ColumnChunk& column); + void setParquetStatistics(BasicColumnWriterState& state, + kuzu_parquet::format::ColumnChunk& column); void registerToRowGroup(kuzu_parquet::format::RowGroup& rowGroup); }; diff --git a/src/include/processor/operator/persistent/writer/parquet/boolean_column_writer.h b/src/include/processor/operator/persistent/writer/parquet/boolean_column_writer.h index 33cc094f17a..d5d8159939e 100644 --- a/src/include/processor/operator/persistent/writer/parquet/boolean_column_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/boolean_column_writer.h @@ -38,8 +38,8 @@ class BooleanColumnWriter : public BasicColumnWriter { BooleanColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schemaPath, uint64_t maxRepeat, uint64_t maxDefine, bool canHaveNulls) - : BasicColumnWriter( - writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, canHaveNulls) {} + : BasicColumnWriter(writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, + canHaveNulls) {} inline std::unique_ptr initializeStatsState() override { return std::make_unique(); @@ -59,8 +59,8 @@ class BooleanColumnWriter : public BasicColumnWriter { ColumnWriterStatistics* writerStatistics, ColumnWriterPageState* writerPageState, common::ValueVector* vector, uint64_t chunkStart, uint64_t chunkEnd) override; - void flushPageState( - common::Serializer& temp_writer, ColumnWriterPageState* writerPageState) override; + void flushPageState(common::Serializer& temp_writer, + ColumnWriterPageState* writerPageState) override; }; } // namespace processor diff --git a/src/include/processor/operator/persistent/writer/parquet/interval_column_writer.h b/src/include/processor/operator/persistent/writer/parquet/interval_column_writer.h index f3c69d8384d..9fcd49df73c 100644 --- a/src/include/processor/operator/persistent/writer/parquet/interval_column_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/interval_column_writer.h @@ -12,8 +12,8 @@ class IntervalColumnWriter : public BasicColumnWriter { IntervalColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schemaPath, uint64_t maxRepeat, uint64_t maxDefine, bool canHaveNulls) - : BasicColumnWriter( - writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, canHaveNulls) {} + : BasicColumnWriter(writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, + canHaveNulls) {} public: static void writeParquetInterval(common::interval_t input, uint8_t* result); diff --git a/src/include/processor/operator/persistent/writer/parquet/var_list_column_writer.h b/src/include/processor/operator/persistent/writer/parquet/list_column_writer.h similarity index 84% rename from src/include/processor/operator/persistent/writer/parquet/var_list_column_writer.h rename to src/include/processor/operator/persistent/writer/parquet/list_column_writer.h index 30a5d1f08fa..fafe2cd5fdb 100644 --- a/src/include/processor/operator/persistent/writer/parquet/var_list_column_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/list_column_writer.h @@ -5,9 +5,9 @@ namespace kuzu { namespace processor { -class VarListColumnWriter : public ColumnWriter { +class ListColumnWriter : public ColumnWriter { public: - VarListColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schema, + ListColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schema, uint64_t maxRepeat, uint64_t maxDefine, std::unique_ptr childWriter, bool canHaveNulls) : ColumnWriter(writer, schemaIdx, std::move(schema), maxRepeat, maxDefine, canHaveNulls), @@ -22,8 +22,8 @@ class VarListColumnWriter : public ColumnWriter { void prepare(ColumnWriterState& writerState, ColumnWriterState* parent, common::ValueVector* vector, uint64_t count) override; void beginWrite(ColumnWriterState& state) override; - void write( - ColumnWriterState& writerState, common::ValueVector* vector, uint64_t count) override; + void write(ColumnWriterState& writerState, common::ValueVector* vector, + uint64_t count) override; void finalizeWrite(ColumnWriterState& writerState) override; private: diff --git a/src/include/processor/operator/persistent/writer/parquet/parquet_writer.h b/src/include/processor/operator/persistent/writer/parquet/parquet_writer.h index 27d86249be3..e5abee8a80d 100644 --- a/src/include/processor/operator/persistent/writer/parquet/parquet_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/parquet_writer.h @@ -60,8 +60,8 @@ class ParquetWriter { void flush(FactorizedTable& ft); void finalize(); static kuzu_parquet::format::Type::type convertToParquetType(common::LogicalType* type); - static void setSchemaProperties( - common::LogicalType* type, kuzu_parquet::format::SchemaElement& schemaElement); + static void setSchemaProperties(common::LogicalType* type, + kuzu_parquet::format::SchemaElement& schemaElement); private: void prepareRowGroup(FactorizedTable& ft, PreparedRowGroup& result); diff --git a/src/include/processor/operator/persistent/writer/parquet/standard_column_writer.h b/src/include/processor/operator/persistent/writer/parquet/standard_column_writer.h index c9054821f7d..a7c73ab35c3 100644 --- a/src/include/processor/operator/persistent/writer/parquet/standard_column_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/standard_column_writer.h @@ -70,8 +70,8 @@ class StandardColumnWriter : public BasicColumnWriter { StandardColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schemaPath, uint64_t maxRepeat, uint64_t maxDefine, bool canHaveNulls) - : BasicColumnWriter( - writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, canHaveNulls) {} + : BasicColumnWriter(writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, + canHaveNulls) {} inline std::unique_ptr initializeStatsState() override { return OP::template initializeStats(); diff --git a/src/include/processor/operator/persistent/writer/parquet/string_column_writer.h b/src/include/processor/operator/persistent/writer/parquet/string_column_writer.h index 6282fbe6289..d1cdfd749cf 100644 --- a/src/include/processor/operator/persistent/writer/parquet/string_column_writer.h +++ b/src/include/processor/operator/persistent/writer/parquet/string_column_writer.h @@ -38,8 +38,8 @@ class StringStatisticsState : public ColumnWriterStatistics { class StringColumnWriterState : public BasicColumnWriterState { public: - StringColumnWriterState( - kuzu_parquet::format::RowGroup& rowGroup, uint64_t colIdx, storage::MemoryManager* mm) + StringColumnWriterState(kuzu_parquet::format::RowGroup& rowGroup, uint64_t colIdx, + storage::MemoryManager* mm) : BasicColumnWriterState{rowGroup, colIdx}, overflowBuffer{std::make_unique(mm)} {} @@ -77,8 +77,8 @@ class StringColumnWriter : public BasicColumnWriter { StringColumnWriter(ParquetWriter& writer, uint64_t schemaIdx, std::vector schemaPath, uint64_t maxRepeat, uint64_t maxDefine, bool canHaveNulls, storage::MemoryManager* mm) - : BasicColumnWriter( - writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, canHaveNulls), + : BasicColumnWriter(writer, schemaIdx, std::move(schemaPath), maxRepeat, maxDefine, + canHaveNulls), mm{mm} {} public: @@ -124,14 +124,14 @@ class StringColumnWriter : public BasicColumnWriter { ColumnWriterPageState* writerPageState, common::ValueVector* vector, uint64_t chunkStart, uint64_t chunkEnd) override; - void flushPageState( - common::Serializer& bufferedSerializer, ColumnWriterPageState* writerPageState) override; + void flushPageState(common::Serializer& bufferedSerializer, + ColumnWriterPageState* writerPageState) override; - void flushDictionary( - BasicColumnWriterState& writerState, ColumnWriterStatistics* writerStats) override; + void flushDictionary(BasicColumnWriterState& writerState, + ColumnWriterStatistics* writerStats) override; - uint64_t getRowSize( - common::ValueVector* vector, uint64_t index, BasicColumnWriterState& writerState) override; + uint64_t getRowSize(common::ValueVector* vector, uint64_t index, + BasicColumnWriterState& writerState) override; private: storage::MemoryManager* mm; diff --git a/src/include/processor/operator/physical_operator.h b/src/include/processor/operator/physical_operator.h index 55f5e26d349..203329da2a5 100644 --- a/src/include/processor/operator/physical_operator.h +++ b/src/include/processor/operator/physical_operator.h @@ -1,6 +1,5 @@ #pragma once -#include "common/exception/interrupt.h" #include "processor/execution_context.h" #include "processor/result/result_set.h" @@ -8,23 +7,22 @@ namespace kuzu { namespace processor { enum class PhysicalOperatorType : uint8_t { - ADD_PROPERTY, + ALTER, AGGREGATE, AGGREGATE_SCAN, + ATTACH_DATABASE, BATCH_INSERT, COMMENT_ON, CREATE_MACRO, + DETACH_DATABASE, STANDALONE_CALL, IN_QUERY_CALL, COPY_RDF, COPY_TO, - CREATE_NODE_TABLE, - CREATE_REL_TABLE, - CREATE_RDF_GRAPH, + CREATE_TABLE, CROSS_PRODUCT, DELETE_NODE, DELETE_REL, - DROP_PROPERTY, DROP_TABLE, EMPTY_RESULT, EXPORT_DATABASE, @@ -95,8 +93,7 @@ class PhysicalOperator { public: // Leaf operator PhysicalOperator(PhysicalOperatorType operatorType, uint32_t id, std::string paramsString) - : id{id}, operatorType{operatorType}, transaction{nullptr}, paramsString{ - std::move(paramsString)} {} + : id{id}, operatorType{operatorType}, paramsString{std::move(paramsString)} {} // Unary operator PhysicalOperator(PhysicalOperatorType operatorType, std::unique_ptr child, uint32_t id, const std::string& paramsString); @@ -131,15 +128,7 @@ class PhysicalOperator { // Local state is initialized for each thread. void initLocalState(ResultSet* resultSet, ExecutionContext* context); - inline bool getNextTuple(ExecutionContext* context) { - if (context->clientContext->isInterrupted()) { - throw common::InterruptException{}; - } - metrics->executionTime.start(); - auto result = getNextTuplesInternal(context); - metrics->executionTime.stop(); - return result; - } + bool getNextTuple(ExecutionContext* context); std::unordered_map getProfilerKeyValAttributes( common::Profiler& profiler) const; @@ -147,6 +136,8 @@ class PhysicalOperator { virtual std::unique_ptr clone() = 0; + virtual double getProgress(ExecutionContext* context) const; + protected: virtual void initGlobalStateInternal(ExecutionContext* /*context*/) {} virtual void initLocalStateInternal(ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) {} @@ -167,8 +158,6 @@ class PhysicalOperator { PhysicalOperatorType operatorType; physical_op_vector_t children; - // TODO(Xiyang/Guodong): Remove this field, as it should be covered in ExecutionContext now. - transaction::Transaction* transaction; ResultSet* resultSet; std::string paramsString; diff --git a/src/include/processor/operator/profile.h b/src/include/processor/operator/profile.h index 6ead2cf4c31..6e4ab2fcbc2 100644 --- a/src/include/processor/operator/profile.h +++ b/src/include/processor/operator/profile.h @@ -30,8 +30,8 @@ class Profile : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) override; std::unique_ptr clone() override { - return std::make_unique( - outputPos, info, localState, id, paramsString, children[0]->clone()); + return std::make_unique(outputPos, info, localState, id, paramsString, + children[0]->clone()); } private: diff --git a/src/include/processor/operator/projection.h b/src/include/processor/operator/projection.h index 869f5434a43..f358ccc59c8 100644 --- a/src/include/processor/operator/projection.h +++ b/src/include/processor/operator/projection.h @@ -13,8 +13,8 @@ class Projection : public PhysicalOperator { std::unordered_set discardedDataChunksPos, std::unique_ptr child, uint32_t id, const std::string& paramsString) : PhysicalOperator(PhysicalOperatorType::PROJECTION, std::move(child), id, paramsString), - expressionEvaluators(std::move(expressionEvaluators)), expressionsOutputPos{std::move( - expressionsOutputPos)}, + expressionEvaluators(std::move(expressionEvaluators)), + expressionsOutputPos{std::move(expressionsOutputPos)}, discardedDataChunksPos{std::move(discardedDataChunksPos)}, prevMultiplicity{1} {} void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; diff --git a/src/include/processor/operator/recursive_extend/bfs_state.h b/src/include/processor/operator/recursive_extend/bfs_state.h index 1461f351e6e..bd0daf7aacb 100644 --- a/src/include/processor/operator/recursive_extend/bfs_state.h +++ b/src/include/processor/operator/recursive_extend/bfs_state.h @@ -40,8 +40,8 @@ class TargetDstNodes { class BaseBFSState { public: explicit BaseBFSState(uint8_t upperBound, TargetDstNodes* targetDstNodes) - : upperBound{upperBound}, currentLevel{0}, nextNodeIdxToExtend{0}, targetDstNodes{ - targetDstNodes} {} + : upperBound{upperBound}, currentLevel{0}, nextNodeIdxToExtend{0}, + targetDstNodes{targetDstNodes} {} virtual ~BaseBFSState() = default; // Get next node offset to extend from current level. diff --git a/src/include/processor/operator/recursive_extend/path_property_probe.h b/src/include/processor/operator/recursive_extend/path_property_probe.h index e9afe25e4f2..3886d966cf9 100644 --- a/src/include/processor/operator/recursive_extend/path_property_probe.h +++ b/src/include/processor/operator/recursive_extend/path_property_probe.h @@ -12,8 +12,8 @@ struct PathPropertyProbeSharedState { PathPropertyProbeSharedState(std::shared_ptr nodeHashTableState, std::shared_ptr relHashTableState) - : nodeHashTableState{std::move(nodeHashTableState)}, relHashTableState{ - std::move(relHashTableState)} {} + : nodeHashTableState{std::move(nodeHashTableState)}, + relHashTableState{std::move(relHashTableState)} {} }; struct PathPropertyProbeLocalState { @@ -41,14 +41,14 @@ struct PathPropertyProbeDataInfo { std::vector nodeTableColumnIndices, std::vector relTableColumnIndices) : pathPos{pathPos}, nodeFieldIndices{std::move(nodeFieldIndices)}, - relFieldIndices{std::move(relFieldIndices)}, nodeTableColumnIndices{std::move( - nodeTableColumnIndices)}, + relFieldIndices{std::move(relFieldIndices)}, + nodeTableColumnIndices{std::move(nodeTableColumnIndices)}, relTableColumnIndices{std::move(relTableColumnIndices)} {} PathPropertyProbeDataInfo(const PathPropertyProbeDataInfo& other) : pathPos{other.pathPos}, nodeFieldIndices{other.nodeFieldIndices}, relFieldIndices{other.relFieldIndices}, - nodeTableColumnIndices{other.nodeTableColumnIndices}, relTableColumnIndices{ - other.relTableColumnIndices} {} + nodeTableColumnIndices{other.nodeTableColumnIndices}, + relTableColumnIndices{other.relTableColumnIndices} {} std::unique_ptr copy() const { return std::make_unique(*this); @@ -76,8 +76,8 @@ class PathPropertyProbe : public PhysicalOperator { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return std::make_unique( - info->copy(), sharedState, children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), sharedState, children[0]->clone(), + id, paramsString); } private: diff --git a/src/include/processor/operator/recursive_extend/recursive_join.h b/src/include/processor/operator/recursive_extend/recursive_join.h index 479442f950a..72c1eceaae1 100644 --- a/src/include/processor/operator/recursive_extend/recursive_join.h +++ b/src/include/processor/operator/recursive_extend/recursive_join.h @@ -45,10 +45,10 @@ struct RecursiveJoinDataInfo { : srcNodePos{srcNodePos}, dstNodePos{dstNodePos}, dstNodeTableIDs{std::move(dstNodeTableIDs)}, pathLengthPos{pathLengthPos}, localResultSetDescriptor{std::move(localResultSetDescriptor)}, - recursiveDstNodeIDPos{recursiveDstNodeIDPos}, recursiveDstNodeTableIDs{std::move( - recursiveDstNodeTableIDs)}, - recursiveEdgeIDPos{recursiveEdgeIDPos}, pathPos{pathPos}, tableIDToName{ - std::move(tableIDToName)} {} + recursiveDstNodeIDPos{recursiveDstNodeIDPos}, + recursiveDstNodeTableIDs{std::move(recursiveDstNodeTableIDs)}, + recursiveEdgeIDPos{recursiveEdgeIDPos}, pathPos{pathPos}, + tableIDToName{std::move(tableIDToName)} {} inline std::unique_ptr copy() { return std::make_unique(srcNodePos, dstNodePos, dstNodeTableIDs, @@ -103,7 +103,7 @@ class RecursiveJoin : public PhysicalOperator { private: void initLocalRecursivePlan(ExecutionContext* context); - void populateTargetDstNodes(); + void populateTargetDstNodes(ExecutionContext* context); bool scanOutput(); diff --git a/src/include/processor/operator/recursive_extend/scan_frontier.h b/src/include/processor/operator/recursive_extend/scan_frontier.h index adee72fea67..736ffb8e544 100644 --- a/src/include/processor/operator/recursive_extend/scan_frontier.h +++ b/src/include/processor/operator/recursive_extend/scan_frontier.h @@ -17,8 +17,8 @@ class ScanFrontier : public PhysicalOperator { inline bool isSource() const override { return true; } - inline void initLocalStateInternal( - ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) override { + inline void initLocalStateInternal(ResultSet* /*resultSet_*/, + ExecutionContext* /*context*/) override { nodeIDVector = resultSet->getValueVector(info.nodeIDPos).get(); flagVector = resultSet->getValueVector(info.flagPos).get(); } diff --git a/src/include/processor/operator/scan/scan_multi_node_tables.h b/src/include/processor/operator/scan/scan_multi_node_tables.h index 09919e8aeb6..6c93e6e0652 100644 --- a/src/include/processor/operator/scan/scan_multi_node_tables.h +++ b/src/include/processor/operator/scan/scan_multi_node_tables.h @@ -17,8 +17,9 @@ class ScanMultiNodeTables : public ScanTable { inline void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override { ScanTable::initLocalStateInternal(resultSet, context); - for (auto& [tableID, _] : tables) { - readStates[tableID] = std::make_unique(); + for (auto& [tableID, scanInfo] : tables) { + readStates[tableID] = std::make_unique(*inVector, + scanInfo->columnIDs, outVectors); } } bool getNextTuplesInternal(ExecutionContext* context) override; diff --git a/src/include/processor/operator/scan/scan_multi_rel_tables.h b/src/include/processor/operator/scan/scan_multi_rel_tables.h index 1e6f98c3b6b..697b16c07fd 100644 --- a/src/include/processor/operator/scan/scan_multi_rel_tables.h +++ b/src/include/processor/operator/scan/scan_multi_rel_tables.h @@ -15,7 +15,8 @@ class RelTableCollectionScanner { nextTableIdx = 0; } - void init(); + void init(common::ValueVector* inVector, + const std::vector& outputVectors); bool scan(common::ValueVector* inVector, const std::vector& outputVectors, transaction::Transaction* transaction); @@ -23,7 +24,7 @@ class RelTableCollectionScanner { private: std::vector> scanInfos; - std::vector> readStates; + std::vector> readStates; uint32_t currentTableIdx = UINT32_MAX; uint32_t nextTableIdx = 0; }; diff --git a/src/include/processor/operator/scan/scan_node_table.h b/src/include/processor/operator/scan/scan_node_table.h index 9edf6fbc5fb..dbc68e7990a 100644 --- a/src/include/processor/operator/scan/scan_node_table.h +++ b/src/include/processor/operator/scan/scan_node_table.h @@ -30,17 +30,18 @@ class ScanSingleNodeTable : public ScanTable { : ScanSingleNodeTable{PhysicalOperatorType::SCAN_NODE_TABLE, std::move(info), inVectorPos, std::move(outVectorsPos), std::move(child), id, paramsString} {} - inline void initLocalStateInternal( - ResultSet* resultSet, ExecutionContext* executionContext) final { + inline void initLocalStateInternal(ResultSet* resultSet, + ExecutionContext* executionContext) final { ScanTable::initLocalStateInternal(resultSet, executionContext); - readState = std::make_unique(); + readState = + std::make_unique(*inVector, info->columnIDs, outVectors); } bool getNextTuplesInternal(ExecutionContext* context) override; inline std::unique_ptr clone() override { - return make_unique( - info->copy(), inVectorPos, outVectorsPos, children[0]->clone(), id, paramsString); + return make_unique(info->copy(), inVectorPos, outVectorsPos, + children[0]->clone(), id, paramsString); } protected: diff --git a/src/include/processor/operator/scan/scan_rel_table.h b/src/include/processor/operator/scan/scan_rel_table.h index 42ae44b76d6..98dad613901 100644 --- a/src/include/processor/operator/scan/scan_rel_table.h +++ b/src/include/processor/operator/scan/scan_rel_table.h @@ -28,16 +28,23 @@ class ScanRelTable : public ScanTable { std::vector outVectorsPos, std::unique_ptr child, uint32_t id, const std::string& paramsString) : ScanRelTable{PhysicalOperatorType::SCAN_REL_TABLE, std::move(info), inVectorPos, - std::move(outVectorsPos), std::move(child), id, paramsString} { - scanState = std::make_unique(); - } + std::move(outVectorsPos), std::move(child), id, paramsString} {} ~ScanRelTable() override = default; + inline void initLocalStateInternal(ResultSet* resultSet, + ExecutionContext* executionContext) override { + ScanTable::initLocalStateInternal(resultSet, executionContext); + if (info) { + scanState = std::make_unique(*inVector, info->columnIDs, + outVectors, info->direction); + } + } + bool getNextTuplesInternal(ExecutionContext* context) override; inline std::unique_ptr clone() override { - return std::make_unique( - info->copy(), inVectorPos, outVectorsPos, children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), inVectorPos, outVectorsPos, + children[0]->clone(), id, paramsString); } protected: @@ -50,7 +57,7 @@ class ScanRelTable : public ScanTable { protected: std::unique_ptr info; - std::unique_ptr scanState; + std::unique_ptr scanState; }; } // namespace processor diff --git a/src/include/processor/operator/scan_node_id.h b/src/include/processor/operator/scan_node_id.h index 6ec3edd3255..afe2b26b7f1 100644 --- a/src/include/processor/operator/scan_node_id.h +++ b/src/include/processor/operator/scan_node_id.h @@ -47,7 +47,12 @@ class ScanNodeIDSharedState { std::tuple getNextRangeToRead(); + uint64_t getNumNodes() const { return numNodes; } + uint64_t getNumNodesScanned() const { return numNodesScanned; } + private: + uint64_t numNodes; + uint64_t numNodesScanned; std::mutex mtx; std::vector> tableStates; uint32_t currentStateIdx; @@ -72,13 +77,15 @@ class ScanNodeID : public PhysicalOperator { return std::make_unique(outDataPos, sharedState, id, paramsString); } + double getProgress(ExecutionContext* context) const override; + private: inline void initGlobalStateInternal(ExecutionContext* context) override { sharedState->initialize(context->clientContext->getTx()); } - void setSelVector( - NodeTableScanState* tableState, common::offset_t startOffset, common::offset_t endOffset); + void setSelVector(ExecutionContext* context, NodeTableScanState* tableState, + common::offset_t startOffset, common::offset_t endOffset); private: DataPos outDataPos; diff --git a/src/include/processor/operator/semi_masker.h b/src/include/processor/operator/semi_masker.h index e8f4f968514..cef0e76c29f 100644 --- a/src/include/processor/operator/semi_masker.h +++ b/src/include/processor/operator/semi_masker.h @@ -68,8 +68,8 @@ class SingleTableSemiMasker : public BaseSemiMasker { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return std::make_unique( - info->copy(), children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), children[0]->clone(), id, + paramsString); } }; @@ -82,8 +82,8 @@ class MultiTableSemiMasker : public BaseSemiMasker { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return std::make_unique( - info->copy(), children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), children[0]->clone(), id, + paramsString); } }; @@ -110,8 +110,8 @@ class PathSingleTableSemiMasker : public PathSemiMasker { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return std::make_unique( - info->copy(), children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), children[0]->clone(), id, + paramsString); } }; @@ -124,8 +124,8 @@ class PathMultipleTableSemiMasker : public PathSemiMasker { bool getNextTuplesInternal(ExecutionContext* context) final; inline std::unique_ptr clone() final { - return std::make_unique( - info->copy(), children[0]->clone(), id, paramsString); + return std::make_unique(info->copy(), children[0]->clone(), id, + paramsString); } }; diff --git a/src/include/processor/operator/sink.h b/src/include/processor/operator/sink.h index a5a7e33d0eb..3f1e05421d3 100644 --- a/src/include/processor/operator/sink.h +++ b/src/include/processor/operator/sink.h @@ -11,8 +11,8 @@ class Sink : public PhysicalOperator { public: Sink(std::unique_ptr resultSetDescriptor, PhysicalOperatorType operatorType, uint32_t id, const std::string& paramsString) - : PhysicalOperator{operatorType, id, paramsString}, resultSetDescriptor{ - std::move(resultSetDescriptor)} {} + : PhysicalOperator{operatorType, id, paramsString}, + resultSetDescriptor{std::move(resultSetDescriptor)} {} Sink(std::unique_ptr resultSetDescriptor, PhysicalOperatorType operatorType, std::unique_ptr child, uint32_t id, const std::string& paramsString) @@ -30,7 +30,7 @@ class Sink : public PhysicalOperator { metrics->executionTime.stop(); } - virtual void finalize(ExecutionContext* /*context*/){}; + virtual void finalize(ExecutionContext* /*context*/) {}; std::unique_ptr clone() override = 0; diff --git a/src/include/processor/operator/skip.h b/src/include/processor/operator/skip.h index 4e1eadb41dc..da9491259a7 100644 --- a/src/include/processor/operator/skip.h +++ b/src/include/processor/operator/skip.h @@ -13,8 +13,8 @@ class Skip : public PhysicalOperator, public SelVectorOverWriter { std::unique_ptr child, uint32_t id, const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::SKIP, std::move(child), id, paramsString}, skipNumber{skipNumber}, counter{std::move(counter)}, - dataChunkToSelectPos{dataChunkToSelectPos}, dataChunksPosInScope{ - std::move(dataChunksPosInScope)} {} + dataChunkToSelectPos{dataChunkToSelectPos}, + dataChunksPosInScope{std::move(dataChunksPosInScope)} {} void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; diff --git a/src/include/processor/operator/table_scan/ftable_scan_function.h b/src/include/processor/operator/table_scan/ftable_scan_function.h index c5fb4f4196e..dcfa2df7d9c 100644 --- a/src/include/processor/operator/table_scan/ftable_scan_function.h +++ b/src/include/processor/operator/table_scan/ftable_scan_function.h @@ -1,6 +1,6 @@ #pragma once -#include "function/scalar_function.h" +#include "function/function.h" #include "function/table/bind_data.h" #include "processor/result/factorized_table.h" @@ -26,6 +26,8 @@ struct FTableScanBindData : public function::TableFuncBindData { }; struct FTableScan { + static constexpr const char* name = "READ_FTABLE"; + static function::function_set getFunctionSet(); }; diff --git a/src/include/processor/operator/table_scan/union_all_scan.h b/src/include/processor/operator/table_scan/union_all_scan.h index 4ba751c4e61..f901ce3066f 100644 --- a/src/include/processor/operator/table_scan/union_all_scan.h +++ b/src/include/processor/operator/table_scan/union_all_scan.h @@ -31,10 +31,10 @@ struct UnionAllScanMorsel { class UnionAllScanSharedState { public: - UnionAllScanSharedState( - std::vector> tables, uint64_t maxMorselSize) - : tables{std::move(tables)}, maxMorselSize{maxMorselSize}, tableIdx{0}, nextTupleIdxToScan{ - 0} {} + UnionAllScanSharedState(std::vector> tables, + uint64_t maxMorselSize) + : tables{std::move(tables)}, maxMorselSize{maxMorselSize}, tableIdx{0}, + nextTupleIdxToScan{0} {} std::unique_ptr getMorsel(); diff --git a/src/include/processor/operator/transaction.h b/src/include/processor/operator/transaction.h index d6c2c0b2e88..c62e60ed0b8 100644 --- a/src/include/processor/operator/transaction.h +++ b/src/include/processor/operator/transaction.h @@ -16,8 +16,8 @@ class Transaction : public PhysicalOperator { inline bool isSource() const final { return true; } inline bool canParallel() const final { return false; } - inline void initLocalStateInternal( - ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) final { + inline void initLocalStateInternal(ResultSet* /*resultSet_*/, + ExecutionContext* /*context*/) final { hasExecuted = false; } diff --git a/src/include/processor/operator/unwind.h b/src/include/processor/operator/unwind.h index 091a1d0172a..9016940ea7d 100644 --- a/src/include/processor/operator/unwind.h +++ b/src/include/processor/operator/unwind.h @@ -9,19 +9,19 @@ namespace processor { class Unwind : public PhysicalOperator { public: - Unwind(common::LogicalType outDataType, DataPos outDataPos, + Unwind(DataPos outDataPos, DataPos idPos, std::unique_ptr expressionEvaluator, std::unique_ptr child, uint32_t id, const std::string& paramsString) : PhysicalOperator{PhysicalOperatorType::UNWIND, std::move(child), id, paramsString}, - outDataType{std::move(outDataType)}, outDataPos{outDataPos}, - expressionEvaluator{std::move(expressionEvaluator)}, startIndex{0u} {} + outDataPos{outDataPos}, idPos(idPos), expressionEvaluator{std::move(expressionEvaluator)}, + startIndex{0u} {} bool getNextTuplesInternal(ExecutionContext* context) override; void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; - inline std::unique_ptr clone() override { - return make_unique(outDataType, outDataPos, expressionEvaluator->clone(), + std::unique_ptr clone() override { + return make_unique(outDataPos, idPos, expressionEvaluator->clone(), children[0]->clone(), id, paramsString); } @@ -29,11 +29,12 @@ class Unwind : public PhysicalOperator { bool hasMoreToRead() const; void copyTuplesToOutVector(uint64_t startPos, uint64_t endPos) const; - common::LogicalType outDataType; DataPos outDataPos; + DataPos idPos; std::unique_ptr expressionEvaluator; std::shared_ptr outValueVector; + common::ValueVector* idVector = nullptr; uint32_t startIndex; common::list_entry_t listEntry; }; diff --git a/src/include/processor/plan_mapper.h b/src/include/processor/plan_mapper.h index cf193bf9888..9e9ca5b5e78 100644 --- a/src/include/processor/plan_mapper.h +++ b/src/include/processor/plan_mapper.h @@ -6,7 +6,6 @@ #include "planner/operator/logical_plan.h" #include "processor/operator/result_collector.h" #include "processor/physical_plan.h" -#include "storage/storage_manager.h" namespace kuzu { namespace main { @@ -33,13 +32,11 @@ struct PartitionerSharedState; class PlanMapper { public: // Create plan mapper with default mapper context. - PlanMapper(storage::StorageManager& storageManager, storage::MemoryManager* memoryManager, - catalog::Catalog* catalog, main::ClientContext* clientContext) - : storageManager{storageManager}, memoryManager{memoryManager}, expressionMapper{}, - catalog{catalog}, clientContext{clientContext}, physicalOperatorID{0} {} + explicit PlanMapper(main::ClientContext* clientContext) + : expressionMapper{}, clientContext{clientContext}, physicalOperatorID{0} {} - std::unique_ptr mapLogicalPlanToPhysical( - planner::LogicalPlan* logicalPlan, const binder::expression_vector& expressionsToCollect); + std::unique_ptr mapLogicalPlanToPhysical(planner::LogicalPlan* logicalPlan, + const binder::expression_vector& expressionsToCollect); private: std::unique_ptr mapOperator(planner::LogicalOperator* logicalOperator); @@ -72,6 +69,7 @@ class PlanMapper { std::unique_ptr mapOrderBy(planner::LogicalOperator* logicalOperator); std::unique_ptr mapUnionAll(planner::LogicalOperator* logicalOperator); std::unique_ptr mapAccumulate(planner::LogicalOperator* logicalOperator); + std::unique_ptr mapMarkAccumulate(planner::LogicalOperator* logicalOperator); std::unique_ptr mapDummyScan(planner::LogicalOperator* logicalOperator); std::unique_ptr mapInsert(planner::LogicalOperator* logicalOperator); std::unique_ptr mapSetNodeProperty(planner::LogicalOperator* logicalOperator); @@ -79,11 +77,6 @@ class PlanMapper { std::unique_ptr mapDeleteNode(planner::LogicalOperator* logicalOperator); std::unique_ptr mapDeleteRel(planner::LogicalOperator* logicalOperator); std::unique_ptr mapCreateTable(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapCreateNodeTable(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapCreateRelTable(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapCreateRelTableGroup( - planner::LogicalOperator* logicalOperator); - std::unique_ptr mapCreateRdfGraph(planner::LogicalOperator* logicalOperator); std::unique_ptr mapCopyFrom(planner::LogicalOperator* logicalOperator); std::unique_ptr mapCopyTo(planner::LogicalOperator* logicalOperator); std::unique_ptr mapCopyNodeFrom(planner::LogicalOperator* logicalOperator); @@ -92,10 +85,6 @@ class PlanMapper { std::unique_ptr mapPartitioner(planner::LogicalOperator* logicalOperator); std::unique_ptr mapDropTable(planner::LogicalOperator* logicalOperator); std::unique_ptr mapAlter(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapRenameTable(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapAddProperty(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapDropProperty(planner::LogicalOperator* logicalOperator); - std::unique_ptr mapRenameProperty(planner::LogicalOperator* logicalOperator); std::unique_ptr mapStandaloneCall(planner::LogicalOperator* logicalOperator); std::unique_ptr mapCommentOn(planner::LogicalOperator* logicalOperator); std::unique_ptr mapInQueryCall(planner::LogicalOperator* logicalOperator); @@ -106,65 +95,94 @@ class PlanMapper { std::unique_ptr mapExtension(planner::LogicalOperator* logicalOperator); std::unique_ptr mapExportDatabase(planner::LogicalOperator* logicalOperator); std::unique_ptr mapImportDatabase(planner::LogicalOperator* logicalOperator); + std::unique_ptr mapAttachDatabase(planner::LogicalOperator* logicalOperator); + std::unique_ptr mapDetachDatabase(planner::LogicalOperator* logicalOperator); std::unique_ptr createCopyRel( std::shared_ptr partitionerSharedState, std::shared_ptr sharedState, planner::LogicalCopyFrom* copyFrom, - common::RelDataDirection direction, - std::vector> columnTypes); + common::RelDataDirection direction, std::vector columnTypes); std::unique_ptr createResultCollector(common::AccumulateType accumulateType, const binder::expression_vector& expressions, planner::Schema* schema, std::unique_ptr prevOperator); - std::unique_ptr createFactorizedTableScan( - const binder::expression_vector& expressions, std::vector colIndices, - planner::Schema* schema, const std::shared_ptr& table, - uint64_t maxMorselSize, std::unique_ptr prevOperator); + // Scan fTable with row offset. + std::unique_ptr createFTableScan(const binder::expression_vector& exprs, + std::vector colIndices, std::shared_ptr offset, + planner::Schema* schema, std::shared_ptr table, uint64_t maxMorselSize, + std::unique_ptr child); + // Scan fTable without row offset. + std::unique_ptr createFTableScan(const binder::expression_vector& exprs, + std::vector colIndices, planner::Schema* schema, + std::shared_ptr table, uint64_t maxMorselSize, + std::unique_ptr child); + // Scan fTable without row offset. + // Scan is the leaf operator of physical plan. + std::unique_ptr createFTableScan(const binder::expression_vector& exprs, + std::vector colIndices, planner::Schema* schema, + std::shared_ptr table, uint64_t maxMorselSize); + // Do not scan anything from table. Serves as a control logic of pull model. + std::unique_ptr createEmptyFTableScan(std::shared_ptr table, + uint64_t maxMorselSize, std::unique_ptr child); + // Do not scan anything from table. Serves as a control logic of pull model. + // Scan is the leaf operator of physical plan. + std::unique_ptr createEmptyFTableScan(std::shared_ptr table, + uint64_t maxMorselSize); // Assume scans all columns of table in the same order as given expressions. - std::unique_ptr createFactorizedTableScanAligned( - const binder::expression_vector& expressions, planner::Schema* schema, - const std::shared_ptr& table, uint64_t maxMorselSize, - std::unique_ptr prevOperator); + // Scan fTable with row offset. + std::unique_ptr createFTableScanAligned( + const binder::expression_vector& exprs, planner::Schema* schema, + std::shared_ptr offset, std::shared_ptr table, + uint64_t maxMorselSize, std::unique_ptr child); + // Assume scans all columns of table in the same order as given expressions. + // Scan fTable without row offset. + std::unique_ptr createFTableScanAligned( + const binder::expression_vector& exprs, planner::Schema* schema, + std::shared_ptr table, uint64_t maxMorselSize, + std::unique_ptr child); + // Assume scans all columns of table in the same order as given expressions. + // Scan fTable without row offset. + // Scan is the leaf operator of physical plan. + std::unique_ptr createFTableScanAligned( + const binder::expression_vector& exprs, planner::Schema* schema, + std::shared_ptr table, uint64_t maxMorselSize); + std::unique_ptr createHashBuildInfo(const planner::Schema& buildSideSchema, const binder::expression_vector& keys, const binder::expression_vector& payloads); - std::unique_ptr createHashAggregate( - const binder::expression_vector& keyExpressions, - const binder::expression_vector& dependentKeyExpressions, + std::unique_ptr createHashAggregate(const binder::expression_vector& keys, + const binder::expression_vector& payloads, std::vector> aggregateFunctions, std::vector> aggregateInputInfos, std::vector aggregatesOutputPos, planner::Schema* inSchema, planner::Schema* outSchema, std::unique_ptr prevOperator, - const std::string& paramsString); + const std::string& paramsString, std::shared_ptr markExpression); std::unique_ptr getNodeInsertExecutor( const planner::LogicalInsertInfo* info, const planner::Schema& inSchema, const planner::Schema& outSchema) const; std::unique_ptr getRelInsertExecutor(const planner::LogicalInsertInfo* info, - const planner::Schema& inSchema, const planner::Schema& outSchema); - std::unique_ptr getNodeSetExecutor( - planner::LogicalSetPropertyInfo* info, const planner::Schema& inSchema) const; - std::unique_ptr getRelSetExecutor( - planner::LogicalSetPropertyInfo* info, const planner::Schema& inSchema) const; + const planner::Schema& inSchema, const planner::Schema& outSchema) const; + std::unique_ptr getNodeSetExecutor(planner::LogicalSetPropertyInfo* info, + const planner::Schema& inSchema) const; + std::unique_ptr getRelSetExecutor(planner::LogicalSetPropertyInfo* info, + const planner::Schema& inSchema) const; - std::shared_ptr getSingleStringColumnFTable(); + std::shared_ptr getSingleStringColumnFTable() const; inline uint32_t getOperatorID() { return physicalOperatorID++; } static void mapSIPJoin(PhysicalOperator* probe); - static std::vector getExpressionsDataPos( - const binder::expression_vector& expressions, const planner::Schema& schema); + static std::vector getExpressionsDataPos(const binder::expression_vector& expressions, + const planner::Schema& schema); - static inline DataPos getDataPos( - const binder::Expression& expression, const planner::Schema& schema) { + static inline DataPos getDataPos(const binder::Expression& expression, + const planner::Schema& schema) { return DataPos(schema.getExpressionPos(expression)); } public: - storage::StorageManager& storageManager; - storage::MemoryManager* memoryManager; ExpressionMapper expressionMapper; - catalog::Catalog* catalog; main::ClientContext* clientContext; private: diff --git a/src/include/processor/processor_task.h b/src/include/processor/processor_task.h index 9d8059c0360..c81a3ef6777 100644 --- a/src/include/processor/processor_task.h +++ b/src/include/processor/processor_task.h @@ -16,8 +16,8 @@ class ProcessorTask : public common::Task { void finalizeIfNecessary() override; private: - static std::unique_ptr populateResultSet( - Sink* op, storage::MemoryManager* memoryManager); + static std::unique_ptr populateResultSet(Sink* op, + storage::MemoryManager* memoryManager); private: bool sharedStateInitialized; diff --git a/src/include/processor/result/base_hash_table.h b/src/include/processor/result/base_hash_table.h new file mode 100644 index 00000000000..36fa78e0e10 --- /dev/null +++ b/src/include/processor/result/base_hash_table.h @@ -0,0 +1,48 @@ +#pragma once + +#include "common/types/types.h" +#include "processor/result/factorized_table.h" +#include "storage/buffer_manager/memory_manager.h" + +namespace kuzu { +namespace processor { + +using compare_function_t = std::function; + +class BaseHashTable { +public: + BaseHashTable(storage::MemoryManager& memoryManager, common::logical_type_vec_t keyTypes); + + virtual ~BaseHashTable() = default; + +protected: + uint64_t getSlotIdxForHash(common::hash_t hash) const { return hash & bitmask; } + void setMaxNumHashSlots(uint64_t newSize); + void computeAndCombineVecHash(const std::vector& unFlatKeyVectors, + uint32_t startVecIdx); + void computeVectorHashes(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors); + void initSlotConstant(uint64_t numSlotsPerBlock_); + +private: + void initCompareFuncs(); + void initTmpHashVector(); + +protected: + uint64_t maxNumHashSlots; + uint64_t bitmask; + uint64_t numSlotsPerBlock; + uint64_t numSlotsPerBlockLog2; + uint64_t slotIdxInBlockMask; + std::vector> hashSlotsBlocks; + storage::MemoryManager& memoryManager; + std::unique_ptr factorizedTable; + std::vector compareEntryFuncs; + common::logical_type_vec_t keyTypes; + // Temporary arrays to hold intermediate results for appending. + std::shared_ptr hashState; + std::unique_ptr hashVector; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/result/factorized_table.h b/src/include/processor/result/factorized_table.h index 6d454721387..c014b888349 100644 --- a/src/include/processor/result/factorized_table.h +++ b/src/include/processor/result/factorized_table.h @@ -94,8 +94,8 @@ class DataBlockCollection { class ColumnSchema { public: ColumnSchema(bool isUnflat, data_chunk_pos_t dataChunksPos, uint32_t numBytes) - : isUnflat{isUnflat}, dataChunkPos{dataChunksPos}, numBytes{numBytes}, mayContainNulls{ - false} {} + : isUnflat{isUnflat}, dataChunkPos{dataChunksPos}, numBytes{numBytes}, + mayContainNulls{false} {} ColumnSchema(const ColumnSchema& other); @@ -177,8 +177,8 @@ class FactorizedTable { friend class PathPropertyProbe; public: - FactorizedTable( - storage::MemoryManager* memoryManager, std::unique_ptr tableSchema); + FactorizedTable(storage::MemoryManager* memoryManager, + std::unique_ptr tableSchema); void append(const std::vector& vectors); @@ -232,15 +232,15 @@ class FactorizedTable { inline const FactorizedTableSchema* getTableSchema() const { return tableSchema.get(); } template - inline TYPE getData( - ft_block_idx_t blockIdx, ft_block_offset_t blockOffset, ft_col_offset_t colOffset) const { + inline TYPE getData(ft_block_idx_t blockIdx, ft_block_offset_t blockOffset, + ft_col_offset_t colOffset) const { return *((TYPE*)getCell(blockIdx, blockOffset, colOffset)); } uint8_t* getTuple(ft_tuple_idx_t tupleIdx) const; - void updateFlatCell( - uint8_t* tuplePtr, ft_col_idx_t colIdx, common::ValueVector* valueVector, uint32_t pos); + void updateFlatCell(uint8_t* tuplePtr, ft_col_idx_t colIdx, common::ValueVector* valueVector, + uint32_t pos); inline void updateFlatCellNoNull(uint8_t* ftTuplePtr, ft_col_idx_t colIdx, void* dataBuf) { memcpy(ftTuplePtr + tableSchema->getColOffset(colIdx), dataBuf, tableSchema->getColumn(colIdx)->getNumBytes()); @@ -252,8 +252,8 @@ class FactorizedTable { return tableSchema->getColumn(colIdx)->hasNoNullGuarantee(); } - bool isOverflowColNull( - const uint8_t* nullBuffer, ft_tuple_idx_t tupleIdx, ft_col_idx_t colIdx) const; + bool isOverflowColNull(const uint8_t* nullBuffer, ft_tuple_idx_t tupleIdx, + ft_col_idx_t colIdx) const; bool isNonOverflowColNull(const uint8_t* nullBuffer, ft_col_idx_t colIdx) const; void setNonOverflowColNull(uint8_t* nullBuffer, ft_col_idx_t colIdx); void clear(); @@ -264,8 +264,8 @@ class FactorizedTable { uint64_t computeNumTuplesToAppend( const std::vector& vectorsToAppend) const; - inline uint8_t* getCell( - ft_block_idx_t blockIdx, ft_block_offset_t blockOffset, ft_col_offset_t colOffset) const { + inline uint8_t* getCell(ft_block_idx_t blockIdx, ft_block_offset_t blockOffset, + ft_col_offset_t colOffset) const { return flatTupleBlockCollection->getBlock(blockIdx)->getData() + blockOffset * tableSchema->getNumBytesPerTuple() + colOffset; } @@ -291,12 +291,12 @@ class FactorizedTable { const BlockAppendingInfo& blockAppendInfo, ft_col_idx_t colIdx); void copyVectorToColumn(const common::ValueVector& vector, const BlockAppendingInfo& blockAppendInfo, uint64_t numAppendedTuples, ft_col_idx_t colIdx); - common::overflow_value_t appendVectorToUnflatTupleBlocks( - const common::ValueVector& vector, ft_col_idx_t colIdx); + common::overflow_value_t appendVectorToUnflatTupleBlocks(const common::ValueVector& vector, + ft_col_idx_t colIdx); // TODO(Guodong): Unify these two `readUnflatCol()` with a (possibly templated) copy executor. - void readUnflatCol( - uint8_t** tuplesToRead, ft_col_idx_t colIdx, common::ValueVector& vector) const; + void readUnflatCol(uint8_t** tuplesToRead, ft_col_idx_t colIdx, + common::ValueVector& vector) const; void readUnflatCol(const uint8_t* tupleToRead, const common::SelectionVector* selVector, ft_col_idx_t colIdx, common::ValueVector& vector) const; void readFlatColToFlatVector(uint8_t* tupleToRead, ft_col_idx_t colIdx, @@ -324,14 +324,14 @@ class FactorizedTableUtils { public: static void appendStringToTable(FactorizedTable* factorizedTable, std::string& outputMsg, storage::MemoryManager* memoryManager); - static std::shared_ptr getFactorizedTableForOutputMsg( - std::string& outputMsg, storage::MemoryManager* memoryManager); + static std::shared_ptr getFactorizedTableForOutputMsg(std::string& outputMsg, + storage::MemoryManager* memoryManager); }; class FlatTupleIterator { public: - explicit FlatTupleIterator( - FactorizedTable& factorizedTable, std::vector values); + explicit FlatTupleIterator(FactorizedTable& factorizedTable, + std::vector values); inline bool hasNextFlatTuple() { return nextTupleIdx < factorizedTable.getNumTuples() || nextFlatTupleIdx < numFlatTuples; diff --git a/src/include/processor/result/mark_hash_table.h b/src/include/processor/result/mark_hash_table.h new file mode 100644 index 00000000000..5f014ae9819 --- /dev/null +++ b/src/include/processor/result/mark_hash_table.h @@ -0,0 +1,32 @@ +#include "processor/operator/aggregate/aggregate_hash_table.h" + +#pragma once + +namespace kuzu { +namespace processor { + +class MarkHashTable : public AggregateHashTable { + +public: + MarkHashTable(storage::MemoryManager& memoryManager, + std::vector keyDataTypes, + std::vector dependentKeyDataTypes, + const std::vector>& aggregateFunctions, + uint64_t numEntriesToAllocate, std::unique_ptr tableSchema); + + uint64_t matchFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, uint64_t numMayMatches, + uint64_t numNoMatches) override; + + void initializeFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, + const std::vector& dependentKeyVectors, + uint64_t numFTEntriesToInitialize) override; + +private: + std::unordered_set onMatchSlotIdxes; + uint32_t distinctColIdxInFT; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/storage/buffer_manager/bm_file_handle.h b/src/include/storage/buffer_manager/bm_file_handle.h index 08baca066cb..e279982a289 100644 --- a/src/include/storage/buffer_manager/bm_file_handle.h +++ b/src/include/storage/buffer_manager/bm_file_handle.h @@ -36,12 +36,12 @@ class PageState { inline static uint64_t getVersion(uint64_t stateAndVersion) { return stateAndVersion & VERSION_MASK; } - inline static uint64_t updateStateWithSameVersion( - uint64_t oldStateAndVersion, uint64_t newState) { + inline static uint64_t updateStateWithSameVersion(uint64_t oldStateAndVersion, + uint64_t newState) { return ((oldStateAndVersion << 8) >> 8) | (newState << NUM_BITS_TO_SHIFT_FOR_STATE); } - inline static uint64_t updateStateAndIncrementVersion( - uint64_t oldStateAndVersion, uint64_t newState) { + inline static uint64_t updateStateAndIncrementVersion(uint64_t oldStateAndVersion, + uint64_t newState) { return (((oldStateAndVersion << 8) >> 8) + 1) | (newState << NUM_BITS_TO_SHIFT_FOR_STATE); } inline void spinLock(uint64_t oldStateAndVersion) { @@ -52,8 +52,8 @@ class PageState { } } inline bool tryLock(uint64_t oldStateAndVersion) { - return stateAndVersion.compare_exchange_strong( - oldStateAndVersion, updateStateWithSameVersion(oldStateAndVersion, LOCKED)); + return stateAndVersion.compare_exchange_strong(oldStateAndVersion, + updateStateWithSameVersion(oldStateAndVersion, LOCKED)); } inline void unlock() { // TODO(Keenan / Guodong): Track down this rare bug and re-enable the assert. Ref #2289. @@ -64,12 +64,12 @@ class PageState { // Change page state from Mark to Unlocked. inline bool tryClearMark(uint64_t oldStateAndVersion) { KU_ASSERT(getState(oldStateAndVersion) == MARKED); - return stateAndVersion.compare_exchange_strong( - oldStateAndVersion, updateStateWithSameVersion(oldStateAndVersion, UNLOCKED)); + return stateAndVersion.compare_exchange_strong(oldStateAndVersion, + updateStateWithSameVersion(oldStateAndVersion, UNLOCKED)); } inline bool tryMark(uint64_t oldStateAndVersion) { - return stateAndVersion.compare_exchange_strong( - oldStateAndVersion, updateStateWithSameVersion(oldStateAndVersion, MARKED)); + return stateAndVersion.compare_exchange_strong(oldStateAndVersion, + updateStateWithSameVersion(oldStateAndVersion, MARKED)); } inline void setDirty() { @@ -113,8 +113,8 @@ class WALPageIdxGroup { inline common::page_idx_t getWALVersionPageIdxNoLock(common::page_idx_t pageIdxInGroup) const { return walPageIdxes[pageIdxInGroup]; } - inline void setWALVersionPageIdxNoLock( - common::page_idx_t pageIdxInGroup, common::page_idx_t walVersionPageIdx) { + inline void setWALVersionPageIdxNoLock(common::page_idx_t pageIdxInGroup, + common::page_idx_t walVersionPageIdx) { walPageIdxes[pageIdxInGroup] = walVersionPageIdx; } diff --git a/src/include/storage/buffer_manager/buffer_manager.h b/src/include/storage/buffer_manager/buffer_manager.h index 0852042e57b..f74fb0cd187 100644 --- a/src/include/storage/buffer_manager/buffer_manager.h +++ b/src/include/storage/buffer_manager/buffer_manager.h @@ -177,16 +177,16 @@ class BufferManager { // Currently, these functions are specifically used only for WAL files. void removeFilePagesFromFrames(BMFileHandle& fileHandle); void flushAllDirtyPagesInFrames(BMFileHandle& fileHandle); - void updateFrameIfPageIsInFrameWithoutLock( - BMFileHandle& fileHandle, uint8_t* newPage, common::page_idx_t pageIdx); + void updateFrameIfPageIsInFrameWithoutLock(BMFileHandle& fileHandle, uint8_t* newPage, + common::page_idx_t pageIdx); void removePageFromFrameIfNecessary(BMFileHandle& fileHandle, common::page_idx_t pageIdx); // For files that are managed by BM, their FileHandles should be created through this function. inline std::unique_ptr getBMFileHandle(const std::string& filePath, uint8_t flags, BMFileHandle::FileVersionedType fileVersionedType, common::VirtualFileSystem* vfs, common::PageSizeClass pageSizeClass = common::PAGE_4KB) { - return std::make_unique( - filePath, flags, this, pageSizeClass, fileVersionedType, vfs); + return std::make_unique(filePath, flags, this, pageSizeClass, + fileVersionedType, vfs); } inline common::frame_group_idx_t addNewFrameGroup(common::PageSizeClass pageSizeClass) { return vmRegions[pageSizeClass]->addNewFrameGroup(); @@ -196,22 +196,25 @@ class BufferManager { private: static void verifySizeParams(uint64_t bufferPoolSize, uint64_t maxDBSize); - bool claimAFrame( - BMFileHandle& fileHandle, common::page_idx_t pageIdx, PageReadPolicy pageReadPolicy); + bool claimAFrame(BMFileHandle& fileHandle, common::page_idx_t pageIdx, + PageReadPolicy pageReadPolicy); // Return number of bytes freed. uint64_t tryEvictPage(EvictionCandidate& candidate); - void cachePageIntoFrame( - BMFileHandle& fileHandle, common::page_idx_t pageIdx, PageReadPolicy pageReadPolicy); + void cachePageIntoFrame(BMFileHandle& fileHandle, common::page_idx_t pageIdx, + PageReadPolicy pageReadPolicy); void flushIfDirtyWithoutLock(BMFileHandle& fileHandle, common::page_idx_t pageIdx); - void removePageFromFrame( - BMFileHandle& fileHandle, common::page_idx_t pageIdx, bool shouldFlush); + void removePageFromFrame(BMFileHandle& fileHandle, common::page_idx_t pageIdx, + bool shouldFlush); - void addToEvictionQueue( - BMFileHandle* fileHandle, common::page_idx_t pageIdx, PageState* pageState); + void addToEvictionQueue(BMFileHandle* fileHandle, common::page_idx_t pageIdx, + PageState* pageState); inline uint64_t reserveUsedMemory(uint64_t size) { return usedMemory.fetch_add(size); } - inline uint64_t freeUsedMemory(uint64_t size) { return usedMemory.fetch_sub(size); } + inline uint64_t freeUsedMemory(uint64_t size) { + KU_ASSERT(usedMemory.load() >= size); + return usedMemory.fetch_sub(size); + } inline uint8_t* getFrame(BMFileHandle& fileHandle, common::page_idx_t pageIdx) { return vmRegions[fileHandle.getPageSizeClass()]->getFrame(fileHandle.getFrameIdx(pageIdx)); diff --git a/src/include/storage/compression/compression.h b/src/include/storage/compression/compression.h index 56dd94c37e5..2ab574e8884 100644 --- a/src/include/storage/compression/compression.h +++ b/src/include/storage/compression/compression.h @@ -19,6 +19,7 @@ struct PageCursor; // Returns the size of the data type in bytes uint32_t getDataTypeSizeInChunk(const common::LogicalType& dataType); +uint32_t getDataTypeSizeInChunk(const common::PhysicalTypeID& dataType); // Compression type is written to the data header both so we can usually catch issues when we // decompress uncompressed data by mistake, and to allow for runtime-configurable compression. @@ -43,8 +44,8 @@ struct CompressionMetadata { uint64_t numValues(uint64_t dataSize, const common::LogicalType& dataType) const; // Returns true if and only if the provided value within the vector can be updated // in this chunk in-place. - bool canUpdateInPlace( - const uint8_t* data, uint32_t pos, common::PhysicalTypeID physicalType) const; + bool canUpdateInPlace(const uint8_t* data, uint32_t pos, + common::PhysicalTypeID physicalType) const; bool canAlwaysUpdateInPlace() const; inline bool isConstant() const { return compression == CompressionType::CONSTANT; } @@ -64,8 +65,8 @@ class CompressionAlg { // Returns compression metadata, including any relevant parameters specific to this dataset // which will need to be passed to compressNextPage. Since this may need to scan the entire // buffer, which is slow, it should only be called once for each set of data to compress. - virtual CompressionMetadata getCompressionMetadata( - const uint8_t* srcBuffer, uint64_t numValues) const = 0; + virtual CompressionMetadata getCompressionMetadata(const uint8_t* srcBuffer, + uint64_t numValues) const = 0; // Takes uncompressed data from the srcBuffer and compresses it into the dstBuffer // @@ -120,14 +121,14 @@ class ConstantCompression final : public CompressionAlg { uint64_t dstOffset, uint64_t numValues, const CompressionMetadata& metadata) const; // Shouldn't be used. No type exclusively uses constant compression - CompressionMetadata getCompressionMetadata( - const uint8_t* /*srcBuffer*/, uint64_t /*numValues*/) const override { + CompressionMetadata getCompressionMetadata(const uint8_t* /*srcBuffer*/, + uint64_t /*numValues*/) const override { KU_UNREACHABLE; } // Nothing to do; constant compressed data is only updated if the update is to the same value void setValuesFromUncompressed(const uint8_t*, common::offset_t, uint8_t*, common::offset_t, - common::offset_t, const CompressionMetadata&) const override{}; + common::offset_t, const CompressionMetadata&) const override {}; private: uint8_t numBytesPerValue; @@ -155,8 +156,8 @@ class Uncompressed : public CompressionAlg { return numBytesPerValue == 0 ? UINT64_MAX : dataSize / numBytesPerValue; } - inline CompressionMetadata getCompressionMetadata( - const uint8_t* /*srcBuffer*/, uint64_t /*numValues*/) const override { + inline CompressionMetadata getCompressionMetadata(const uint8_t* /*srcBuffer*/, + uint64_t /*numValues*/) const override { return CompressionMetadata(); } @@ -238,8 +239,8 @@ class IntegerBitpacking : public CompressionAlg { return numValues; } - CompressionMetadata getCompressionMetadata( - const uint8_t* srcBuffer, uint64_t numValues) const override { + CompressionMetadata getCompressionMetadata(const uint8_t* srcBuffer, + uint64_t numValues) const override { auto header = getBitWidth(srcBuffer, numValues); // Use uncompressed if the bitwidth is equal to the size of the type in bits if (header.bitWidth >= sizeof(T) * 8) { @@ -263,8 +264,8 @@ class IntegerBitpacking : public CompressionAlg { void getValues(const uint8_t* chunkStart, uint8_t pos, uint8_t* dst, uint8_t numValuesToRead, const BitpackHeader& header) const; - inline const uint8_t* getChunkStart( - const uint8_t* buffer, uint64_t pos, uint8_t bitWidth) const { + inline const uint8_t* getChunkStart(const uint8_t* buffer, uint64_t pos, + uint8_t bitWidth) const { // Order of operations is important so that pos is rounded down to a multiple of CHUNK_SIZE return buffer + (pos / CHUNK_SIZE) * bitWidth * CHUNK_SIZE / 8; } @@ -281,8 +282,8 @@ class BooleanBitpacking : public CompressionAlg { static inline uint64_t numValues(uint64_t dataSize) { return dataSize * 8; } - inline CompressionMetadata getCompressionMetadata( - const uint8_t* /*srcBuffer*/, uint64_t /*numValues*/) const override { + inline CompressionMetadata getCompressionMetadata(const uint8_t* /*srcBuffer*/, + uint64_t /*numValues*/) const override { return CompressionMetadata{CompressionType::BOOLEAN_BITPACKING}; } uint64_t compressNextPage(const uint8_t*& srcBuffer, uint64_t numValuesRemaining, @@ -302,8 +303,8 @@ class CompressedFunctor { protected: explicit CompressedFunctor(const common::LogicalType& logicalType) - : constant{logicalType}, uncompressed{logicalType}, physicalType{ - logicalType.getPhysicalType()} {} + : constant{logicalType}, uncompressed{logicalType}, + physicalType{logicalType.getPhysicalType()} {} const ConstantCompression constant; const Uncompressed uncompressed; const BooleanBitpacking booleanBitpacking; diff --git a/src/include/storage/index/hash_index.h b/src/include/storage/index/hash_index.h index 79b7f6366b4..74d245dca7f 100644 --- a/src/include/storage/index/hash_index.h +++ b/src/include/storage/index/hash_index.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "common/type_utils.h" #include "common/types/ku_string.h" #include "common/types/types.h" @@ -7,13 +9,13 @@ #include "hash_index_slot.h" #include "storage/index/hash_index_utils.h" #include "storage/storage_structure/disk_array.h" -#include "storage/storage_structure/disk_overflow_file.h" +#include "storage/storage_structure/overflow_file.h" #include "transaction/transaction.h" namespace kuzu { namespace storage { -template +template class HashIndexLocalStorage; class OnDiskHashIndex { @@ -46,21 +48,22 @@ class OnDiskHashIndex { // // T is the key type used to access values // S is the stored type, which is usually the same as T, with the exception of strings -template +template class HashIndex final : public OnDiskHashIndex { public: HashIndex(const DBFileIDAndName& dbFileIDAndName, - const std::shared_ptr& fileHandle, - const std::shared_ptr& overflowFile, uint64_t indexPos, - BufferManager& bufferManager, WAL* wal); + const std::shared_ptr& fileHandle, OverflowFileHandle* overflowFileHandle, + uint64_t indexPos, BufferManager& bufferManager, WAL* wal); ~HashIndex() override; public: - bool lookupInternal(transaction::Transaction* transaction, T key, common::offset_t& result); - void deleteInternal(T key) const; - bool insertInternal(T key, common::offset_t value); + using Key = + typename std::conditional, std::string_view, T>::type; + bool lookupInternal(transaction::Transaction* transaction, Key key, common::offset_t& result); + void deleteInternal(Key key) const; + bool insertInternal(Key key, common::offset_t value); void prepareCommit() override; void prepareRollback() override; @@ -69,28 +72,28 @@ class HashIndex final : public OnDiskHashIndex { inline BMFileHandle* getFileHandle() const { return fileHandle.get(); } private: - bool lookupInPersistentIndex( - transaction::TransactionType trxType, T key, common::offset_t& result); + bool lookupInPersistentIndex(transaction::TransactionType trxType, Key key, + common::offset_t& result); // The following two functions are only used in prepareCommit, and are not thread-safe. - void insertIntoPersistentIndex(T key, common::offset_t value); - void deleteFromPersistentIndex(T key); + void insertIntoPersistentIndex(Key key, common::offset_t value); + void deleteFromPersistentIndex(Key key); - entry_pos_t findMatchedEntryInSlot(transaction::TransactionType trxType, const Slot& slot, - T key, uint8_t fingerprint) const; + entry_pos_t findMatchedEntryInSlot(transaction::TransactionType trxType, const Slot& slot, + Key key, uint8_t fingerprint) const; - inline void updateSlot(const SlotInfo& slotInfo, const Slot& slot) { + inline void updateSlot(const SlotInfo& slotInfo, const Slot& slot) { slotInfo.slotType == SlotType::PRIMARY ? pSlots->update(slotInfo.slotId, slot) : oSlots->update(slotInfo.slotId, slot); } - inline Slot getSlot(transaction::TransactionType trxType, const SlotInfo& slotInfo) { + inline Slot getSlot(transaction::TransactionType trxType, const SlotInfo& slotInfo) { return slotInfo.slotType == SlotType::PRIMARY ? pSlots->get(slotInfo.slotId, trxType) : oSlots->get(slotInfo.slotId, trxType); } - inline uint32_t appendPSlot() { return pSlots->pushBack(Slot{}); } + inline uint32_t appendPSlot() { return pSlots->pushBack(Slot{}); } - inline uint64_t appendOverflowSlot(Slot&& newSlot) { return oSlots->pushBack(newSlot); } + inline uint64_t appendOverflowSlot(Slot&& newSlot) { return oSlots->pushBack(newSlot); } inline void splitSlot(HashIndexHeader& header) { appendPSlot(); @@ -99,33 +102,32 @@ class HashIndex final : public OnDiskHashIndex { } void rehashSlots(HashIndexHeader& header); - inline bool equals( - transaction::TransactionType /*trxType*/, T keyToLookup, const S& keyInEntry) const { + inline bool equals(transaction::TransactionType /*trxType*/, Key keyToLookup, + const T& keyInEntry) const { return keyToLookup == keyInEntry; } template - void copyAndUpdateSlotHeader( - Slot& slot, entry_pos_t entryPos, K key, common::offset_t value, uint8_t fingerprint) { + void copyAndUpdateSlotHeader(Slot& slot, entry_pos_t entryPos, K key, common::offset_t value, + uint8_t fingerprint) { if constexpr (isCopyEntry) { - memcpy( - slot.entries[entryPos].data, &key, this->indexHeaderForWriteTrx->numBytesPerEntry); + slot.entries[entryPos].copyFrom((uint8_t*)&key); } else { - insert(key, slot.entries[entryPos].data, value); + insert(key, slot.entries[entryPos], value); } slot.header.setEntryValid(entryPos, fingerprint); } - inline void insert(T key, uint8_t* entry, common::offset_t offset) { - memcpy(entry, &key, sizeof(T)); - memcpy(entry + sizeof(T), &offset, sizeof(common::offset_t)); + inline void insert(Key key, SlotEntry& entry, common::offset_t offset) { + entry.key = key; + entry.value = offset; } - inline common::hash_t hashStored(transaction::TransactionType /*trxType*/, const S& key) const { + inline common::hash_t hashStored(transaction::TransactionType /*trxType*/, const T& key) const { return HashIndexUtils::hash(key); } struct SlotIterator { SlotInfo slotInfo; - Slot slot; + Slot slot; }; SlotIterator getSlotIterator(slot_id_t slotId, transaction::TransactionType trxType) { @@ -143,23 +145,23 @@ class HashIndex final : public OnDiskHashIndex { return false; } - std::vector>> getChainedSlots(slot_id_t pSlotId); + std::vector>> getChainedSlots(slot_id_t pSlotId); template - void copyKVOrEntryToSlot(const SlotInfo& slotInfo, Slot& slot, K key, common::offset_t value, + void copyKVOrEntryToSlot(const SlotInfo& slotInfo, Slot& slot, K key, common::offset_t value, uint8_t fingerprint) { - if (slot.header.numEntries() == getSlotCapacity()) { + if (slot.header.numEntries() == getSlotCapacity()) { // Allocate a new oSlot, insert the entry to the new oSlot, and update slot's // nextOvfSlotId. - Slot newSlot; + Slot newSlot; auto entryPos = 0u; // Always insert to the first entry when there is a new slot. copyAndUpdateSlotHeader(newSlot, entryPos, key, value, fingerprint); slot.header.nextOvfSlotId = appendOverflowSlot(std::move(newSlot)); } else { - for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { + for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { if (!slot.header.isEntryValid(entryPos)) { - copyAndUpdateSlotHeader( - slot, entryPos, key, value, fingerprint); + copyAndUpdateSlotHeader(slot, entryPos, key, value, + fingerprint); break; } } @@ -167,34 +169,33 @@ class HashIndex final : public OnDiskHashIndex { updateSlot(slotInfo, slot); } - void copyEntryToSlot(slot_id_t slotId, const S& entry, uint8_t fingerprint); + void copyEntryToSlot(slot_id_t slotId, const T& entry, uint8_t fingerprint); private: // Local Storage for strings stores an std::string, but still takes std::string_view as keys to // avoid unnecessary copying - using LocalStorageType = - typename std::conditional::value, std::string, T>::type; + using LocalStorageType = typename std::conditional::value, + std::string, T>::type; DBFileIDAndName dbFileIDAndName; BufferManager& bm; WAL* wal; std::shared_ptr fileHandle; std::unique_ptr> headerArray; - std::unique_ptr>> pSlots; - std::unique_ptr>> oSlots; - std::shared_ptr diskOverflowFile; - std::unique_ptr> localStorage; + std::unique_ptr>> pSlots; + std::unique_ptr>> oSlots; + OverflowFileHandle* overflowFileHandle; + std::unique_ptr> localStorage; std::unique_ptr indexHeaderForReadTrx; std::unique_ptr indexHeaderForWriteTrx; }; template<> -common::hash_t HashIndex::hashStored( - transaction::TransactionType trxType, const common::ku_string_t& key) const; +common::hash_t HashIndex::hashStored(transaction::TransactionType trxType, + const common::ku_string_t& key) const; template<> -inline bool HashIndex::equals( - transaction::TransactionType trxType, std::string_view keyToLookup, - const common::ku_string_t& keyInEntry) const; +inline bool HashIndex::equals(transaction::TransactionType trxType, + std::string_view keyToLookup, const common::ku_string_t& keyInEntry) const; class PrimaryKeyIndex { public: @@ -204,23 +205,21 @@ class PrimaryKeyIndex { ~PrimaryKeyIndex(); - template - inline HashIndex* getTypedHashIndex(T key) { - return common::ku_dynamic_cast*>( + template + using HashIndexType = + typename std::conditional || std::same_as, + common::ku_string_t, T>::type; + template + inline HashIndex>* getTypedHashIndex(T key) { + return common::ku_dynamic_cast>*>( hashIndices[HashIndexUtils::getHashIndexPosition(key)].get()); } - inline bool lookup( - transaction::Transaction* trx, common::ku_string_t key, common::offset_t& result) { + inline bool lookup(transaction::Transaction* trx, common::ku_string_t key, + common::offset_t& result) { return lookup(trx, key.getAsStringView(), result); } - inline bool lookup( - transaction::Transaction* trx, std::string_view key, common::offset_t& result) { - KU_ASSERT(keyDataTypeID == common::PhysicalTypeID::STRING); - return getTypedHashIndex(key)->lookupInternal( - trx, key, result); - } - template + template inline bool lookup(transaction::Transaction* trx, T key, common::offset_t& result) { KU_ASSERT(keyDataTypeID == common::TypeUtils::getPhysicalTypeIDForType()); return getTypedHashIndex(key)->lookupInternal(trx, key, result); @@ -232,12 +231,7 @@ class PrimaryKeyIndex { inline bool insert(common::ku_string_t key, common::offset_t value) { return insert(key.getAsStringView(), value); } - inline bool insert(std::string_view key, common::offset_t value) { - KU_ASSERT(keyDataTypeID == common::PhysicalTypeID::STRING); - return getTypedHashIndex(key)->insertInternal( - key, value); - } - template + template inline bool insert(T key, common::offset_t value) { KU_ASSERT(keyDataTypeID == common::TypeUtils::getPhysicalTypeIDForType()); return getTypedHashIndex(key)->insertInternal(key, value); @@ -245,11 +239,7 @@ class PrimaryKeyIndex { bool insert(common::ValueVector* keyVector, uint64_t vectorPos, common::offset_t value); inline void delete_(common::ku_string_t key) { return delete_(key.getAsStringView()); } - inline void delete_(std::string_view key) { - KU_ASSERT(keyDataTypeID == common::PhysicalTypeID::STRING); - return getTypedHashIndex(key)->deleteInternal(key); - } - template + template inline void delete_(T key) { KU_ASSERT(keyDataTypeID == common::TypeUtils::getPhysicalTypeIDForType()); return getTypedHashIndex(key)->deleteInternal(key); @@ -262,12 +252,12 @@ class PrimaryKeyIndex { void prepareCommit(); void prepareRollback(); BMFileHandle* getFileHandle() { return fileHandle.get(); } - DiskOverflowFile* getDiskOverflowFile() { return overflowFile.get(); } + OverflowFile* getOverflowFile() { return overflowFile.get(); } private: common::PhysicalTypeID keyDataTypeID; std::shared_ptr fileHandle; - std::shared_ptr overflowFile; + std::unique_ptr overflowFile; std::vector> hashIndices; }; diff --git a/src/include/storage/index/hash_index_builder.h b/src/include/storage/index/hash_index_builder.h index aaf2e81bc48..9a7ca5195a9 100644 --- a/src/include/storage/index/hash_index_builder.h +++ b/src/include/storage/index/hash_index_builder.h @@ -1,12 +1,14 @@ #pragma once +#include "common/static_vector.h" #include "common/type_utils.h" +#include "common/types/ku_string.h" #include "common/types/types.h" #include "storage/index/hash_index_header.h" #include "storage/index/hash_index_slot.h" #include "storage/index/hash_index_utils.h" #include "storage/storage_structure/disk_array.h" -#include "storage/storage_structure/in_mem_file.h" +#include "storage/storage_structure/overflow_file.h" namespace kuzu { namespace storage { @@ -18,6 +20,10 @@ class InMemHashIndex { virtual void bulkReserve(uint32_t numEntries) = 0; }; +constexpr size_t BUFFER_SIZE = 1024; +template +using IndexBuffer = common::StaticVector, BUFFER_SIZE>; + /** * Basic index file consists of three disk arrays: indexHeader, primary slots (pSlots), and overflow * slots (oSlots). @@ -44,9 +50,10 @@ class InMemHashIndex { * * */ -// T is the key type used to access values -// S is the stored type, which is usually the same as T, with the exception of strings -template +// T is the key type stored in the slots. +// For strings this is different than the type used when inserting/searching +// (see BufferKeyType and Key) +template class HashIndexBuilder final : public InMemHashIndex { static_assert(getSlotCapacity() <= SlotHeader::FINGERPRINT_CAPACITY); // Size of the validity mask @@ -55,20 +62,28 @@ class HashIndexBuilder final : public InMemHashIndex { public: HashIndexBuilder(const std::shared_ptr& handle, - std::unique_ptr overflowFile, uint64_t indexPos, + OverflowFileHandle* overflowFileHandle, uint64_t indexPos, common::PhysicalTypeID keyDataType); public: // Reserves space for at least the specified number of elements. void bulkReserve(uint32_t numEntries) override; - bool append(T key, common::offset_t value); - bool lookup(T key, common::offset_t& result); + using BufferKeyType = + typename std::conditional, std::string, T>::type; + // Appends the buffer to the index. Returns the number of values successfully inserted. + // I.e. if a key fails to insert, its index will be the return value + size_t append(const IndexBuffer& buffer); + using Key = + typename std::conditional, std::string_view, T>::type; + bool lookup(Key key, common::offset_t& result); void flush() override; private: - Slot* getSlot(const SlotInfo& slotInfo); + // Assumes that space has already been allocated for the entry + bool appendInternal(Key key, common::offset_t value, common::hash_t hash); + Slot* getSlot(const SlotInfo& slotInfo); uint32_t allocatePSlots(uint32_t numSlotsToAllocate); uint32_t allocateAOSlot(); @@ -80,28 +95,28 @@ class HashIndexBuilder final : public InMemHashIndex { */ void splitSlot(HashIndexHeader& header); - inline bool equals(T keyToLookup, const S& keyInEntry) const { + inline bool equals(Key keyToLookup, const T& keyInEntry) const { return keyToLookup == keyInEntry; } - inline void insert( - T key, Slot* slot, uint8_t entryPos, common::offset_t value, uint8_t fingerprint) { - auto entry = slot->entries[entryPos].data; - memcpy(entry, &key, sizeof(T)); - memcpy(entry + sizeof(T), &value, sizeof(common::offset_t)); + inline void insert(Key key, Slot* slot, uint8_t entryPos, common::offset_t value, + uint8_t fingerprint) { + auto& entry = slot->entries[entryPos]; + entry.key = key; + entry.value = value; slot->header.setEntryValid(entryPos, fingerprint); KU_ASSERT(HashIndexUtils::getFingerprintForHash(HashIndexUtils::hash(key)) == fingerprint); } void copy(const uint8_t* oldEntry, slot_id_t newSlotId, uint8_t fingerprint); - void insertToNewOvfSlot( - T key, Slot* previousSlot, common::offset_t offset, uint8_t fingerprint); - common::hash_t hashStored(const S& key) const; + void insertToNewOvfSlot(Key key, Slot* previousSlot, common::offset_t offset, + uint8_t fingerprint); + common::hash_t hashStored(const T& key) const; struct SlotIterator { - explicit SlotIterator(slot_id_t newSlotId, HashIndexBuilder* builder) + explicit SlotIterator(slot_id_t newSlotId, HashIndexBuilder* builder) : slotInfo{newSlotId, SlotType::PRIMARY}, slot(builder->getSlot(slotInfo)) {} SlotInfo slotInfo; - Slot* slot; + Slot* slot; }; inline bool nextChainedSlot(SlotIterator& iter) { @@ -116,16 +131,16 @@ class HashIndexBuilder final : public InMemHashIndex { private: std::shared_ptr fileHandle; - std::unique_ptr inMemOverflowFile; + OverflowFileHandle* overflowFileHandle; std::unique_ptr> headerArray; - std::unique_ptr>> pSlots; - std::unique_ptr>> oSlots; + std::unique_ptr>> pSlots; + std::unique_ptr>> oSlots; std::unique_ptr indexHeader; }; template<> -bool HashIndexBuilder::equals( - std::string_view keyToLookup, const common::ku_string_t& keyInEntry) const; +bool HashIndexBuilder::equals(std::string_view keyToLookup, + const common::ku_string_t& keyInEntry) const; class PrimaryKeyIndexBuilder { public: @@ -134,26 +149,15 @@ class PrimaryKeyIndexBuilder { void bulkReserve(uint32_t numEntries); - // Note: append assumes that bulkRserve has been called before it and the index has reserved - // enough space already. - template - bool append(T key, common::offset_t value) { - return appendWithIndexPos(key, value, HashIndexUtils::getHashIndexPosition(key)); - } - bool append(std::string_view key, common::offset_t value) { - return appendWithIndexPos(key, value, HashIndexUtils::getHashIndexPosition(key)); - } - template - bool appendWithIndexPos(T key, common::offset_t value, uint64_t indexPos) { + // Appends the buffer to the index. Returns the number of values successfully inserted. + // I.e. if a key fails to insert, its index will be the return value + template + size_t appendWithIndexPos(const IndexBuffer& buffer, uint64_t indexPos) { KU_ASSERT(keyDataTypeID == common::TypeUtils::getPhysicalTypeIDForType()); - KU_ASSERT(HashIndexUtils::getHashIndexPosition(key) == indexPos); - return getTypedHashIndex(indexPos)->append(key, value); - } - bool appendWithIndexPos(std::string_view key, common::offset_t value, uint64_t indexPos) { - KU_ASSERT(keyDataTypeID == common::PhysicalTypeID::STRING); - KU_ASSERT(HashIndexUtils::getHashIndexPosition(key) == indexPos); - return getTypedHashIndex(indexPos)->append( - key, value); + KU_ASSERT(std::all_of(buffer.begin(), buffer.end(), [&](auto& elem) { + return HashIndexUtils::getHashIndexPosition(elem.first) == indexPos; + })); + return getTypedHashIndex(indexPos)->append(buffer); } template bool lookup(T key, common::offset_t& result) { @@ -162,8 +166,7 @@ class PrimaryKeyIndexBuilder { } bool lookup(std::string_view key, common::offset_t& result) { KU_ASSERT(keyDataTypeID == common::PhysicalTypeID::STRING); - return getTypedHashIndex( - HashIndexUtils::getHashIndexPosition(key)) + return getTypedHashIndex(HashIndexUtils::getHashIndexPosition(key)) ->lookup(key, result); } @@ -173,15 +176,24 @@ class PrimaryKeyIndexBuilder { common::PhysicalTypeID keyTypeID() const { return keyDataTypeID; } private: - template - inline HashIndexBuilder* getTypedHashIndex(uint64_t indexPos) { - return common::ku_dynamic_cast*>( - hashIndexBuilders[indexPos].get()); + template + using HashIndexType = + typename std::conditional || std::same_as, + common::ku_string_t, T>::type; + template + inline HashIndexBuilder>* getTypedHashIndex(uint64_t indexPos) { + if constexpr (std::same_as, common::ku_string_t>) { + return common::ku_dynamic_cast*>( + hashIndexBuilders[indexPos].get()); + } else { + return common::ku_dynamic_cast*>( + hashIndexBuilders[indexPos].get()); + } } private: common::PhysicalTypeID keyDataTypeID; - std::atomic overflowPageCounter; + std::unique_ptr overflowFile; std::vector> hashIndexBuilders; }; diff --git a/src/include/storage/index/hash_index_header.h b/src/include/storage/index/hash_index_header.h index 110aac62e0e..69d6f003db9 100644 --- a/src/include/storage/index/hash_index_header.h +++ b/src/include/storage/index/hash_index_header.h @@ -2,7 +2,6 @@ #include "common/types/types.h" #include "hash_index_slot.h" -#include "storage/storage_utils.h" namespace kuzu { namespace storage { @@ -11,9 +10,7 @@ class HashIndexHeader { public: explicit HashIndexHeader(common::PhysicalTypeID keyDataTypeID) : currentLevel{1}, levelHashMask{1}, higherLevelHashMask{3}, nextSplitSlotId{0}, - numEntries{0}, numBytesPerKey{storage::StorageUtils::getDataTypeSize(keyDataTypeID)}, - numBytesPerEntry{(uint32_t)(numBytesPerKey + sizeof(common::offset_t))}, - keyDataTypeID{keyDataTypeID} {} + numEntries{0}, keyDataTypeID{keyDataTypeID} {} // Used for element initialization in disk array only. HashIndexHeader() : HashIndexHeader(common::PhysicalTypeID::STRING) {} @@ -38,8 +35,6 @@ class HashIndexHeader { uint64_t higherLevelHashMask; slot_id_t nextSplitSlotId; uint64_t numEntries; - uint32_t numBytesPerKey; - uint32_t numBytesPerEntry; common::PhysicalTypeID keyDataTypeID; }; diff --git a/src/include/storage/index/hash_index_slot.h b/src/include/storage/index/hash_index_slot.h index 456520e6e75..313cde8671f 100644 --- a/src/include/storage/index/hash_index_slot.h +++ b/src/include/storage/index/hash_index_slot.h @@ -49,7 +49,15 @@ class SlotHeader { template struct SlotEntry { - uint8_t data[sizeof(T) + sizeof(common::offset_t)]; + T key; + common::offset_t value; + + inline uint8_t* data() const { return (uint8_t*)&key; } + + // otherEntry must be a pointer to the beginning of another slot's key field + inline void copyFrom(const uint8_t* otherEntry) { + memcpy(data(), otherEntry, sizeof(SlotEntry)); + } }; template diff --git a/src/include/storage/index/hash_index_utils.h b/src/include/storage/index/hash_index_utils.h index 24a1bd8f2c0..f36865b0708 100644 --- a/src/include/storage/index/hash_index_utils.h +++ b/src/include/storage/index/hash_index_utils.h @@ -1,22 +1,15 @@ #pragma once +#include + #include "common/types/ku_string.h" #include "common/types/types.h" #include "function/hash/hash_functions.h" #include "storage/index/hash_index_header.h" -#include "storage/storage_utils.h" namespace kuzu { namespace storage { -// NOLINTBEGIN(cert-err58-cpp): This is the best way to get the datatype size because it avoids -// refactoring. -static const uint32_t NUM_BYTES_FOR_INT64_KEY = - storage::StorageUtils::getDataTypeSize(common::LogicalType{common::LogicalTypeID::INT64}); -static const uint32_t NUM_BYTES_FOR_STRING_KEY = - storage::StorageUtils::getDataTypeSize(common::LogicalType{common::LogicalTypeID::STRING}); -// NOLINTEND(cert-err58-cpp) - const uint64_t NUM_HASH_INDEXES_LOG2 = 8; const uint64_t NUM_HASH_INDEXES = 1 << NUM_HASH_INDEXES_LOG2; @@ -36,10 +29,10 @@ struct SlotInfo { class HashIndexUtils { public: - inline static bool areStringPrefixAndLenEqual( - std::string_view keyToLookup, const common::ku_string_t& keyInEntry) { - auto prefixLen = std::min( - (uint64_t)keyInEntry.len, static_cast(common::ku_string_t::PREFIX_LENGTH)); + inline static bool areStringPrefixAndLenEqual(std::string_view keyToLookup, + const common::ku_string_t& keyInEntry) { + auto prefixLen = std::min((uint64_t)keyInEntry.len, + static_cast(common::ku_string_t::PREFIX_LENGTH)); return keyToLookup.length() == keyInEntry.len && memcmp(keyToLookup.data(), keyInEntry.prefix, prefixLen) == 0; } @@ -56,8 +49,8 @@ class HashIndexUtils { return (hash >> (64 - NUM_HASH_INDEXES_LOG2 - 8)) & 255; } - inline static slot_id_t getPrimarySlotIdForHash( - const HashIndexHeader& indexHeader, common::hash_t hash) { + inline static slot_id_t getPrimarySlotIdForHash(const HashIndexHeader& indexHeader, + common::hash_t hash) { auto slotId = hash & indexHeader.levelHashMask; if (slotId < indexHeader.nextSplitSlotId) { slotId = hash & indexHeader.higherLevelHashMask; @@ -69,8 +62,8 @@ class HashIndexUtils { return (HashIndexUtils::hash(key) >> (64 - NUM_HASH_INDEXES_LOG2)) & (NUM_HASH_INDEXES - 1); } - static inline uint64_t getNumRequiredEntries( - uint64_t numExistingEntries, uint64_t numNewEntries) { + static inline uint64_t getNumRequiredEntries(uint64_t numExistingEntries, + uint64_t numNewEntries) { return ceil((double)(numExistingEntries + numNewEntries) * common::DEFAULT_HT_LOAD_FACTOR); } }; diff --git a/src/include/storage/local_storage/local_node_table.h b/src/include/storage/local_storage/local_node_table.h index 8672e313c31..ed39c51db62 100644 --- a/src/include/storage/local_storage/local_node_table.h +++ b/src/include/storage/local_storage/local_node_table.h @@ -2,6 +2,7 @@ #include +#include "common/copy_constructors.h" #include "local_table.h" namespace kuzu { @@ -10,57 +11,62 @@ namespace storage { class LocalNodeNG final : public LocalNodeGroup { public: LocalNodeNG(common::offset_t nodeGroupStartOffset, - const std::vector& dataTypes, MemoryManager* mm) - : LocalNodeGroup{nodeGroupStartOffset, dataTypes, mm} { - insertInfo.resize(dataTypes.size()); - updateInfo.resize(dataTypes.size()); - } + const std::vector& dataTypes) + : LocalNodeGroup{nodeGroupStartOffset, dataTypes} {} + DELETE_COPY_DEFAULT_MOVE(LocalNodeNG); void scan(common::ValueVector* nodeIDVector, const std::vector& columnIDs, const std::vector& outputVectors); void lookup(common::offset_t nodeOffset, common::column_id_t columnID, common::ValueVector* outputVector, common::sel_t posInOutputVector); - void insert(common::ValueVector* nodeIDVector, - const std::vector& propertyVectors); - void update(common::ValueVector* nodeIDVector, common::column_id_t columnID, - common::ValueVector* propertyVector); - void delete_(common::ValueVector* nodeIDVector); - common::row_idx_t getRowIdx(common::column_id_t columnID, common::offset_t nodeOffset); + bool insert(std::vector nodeIDVectors, + std::vector propertyVectors) override; + bool update(std::vector nodeIDVectors, common::column_id_t columnID, + common::ValueVector* propertyVector) override; + bool delete_(common::ValueVector* nodeIDVector, + common::ValueVector* /*extraVector*/ = nullptr) override; - inline const offset_to_row_idx_t& getInsertInfoRef(common::column_id_t columnID) { - KU_ASSERT(columnID < insertInfo.size()); - return insertInfo[columnID]; + inline const offset_to_row_idx_t& getInsertInfoRef() const { + return insertChunks.getOffsetToRowIdx(); } - inline const offset_to_row_idx_t& getUpdateInfoRef(common::column_id_t columnID) { - KU_ASSERT(columnID < updateInfo.size()); - return updateInfo[columnID]; + inline const offset_to_row_idx_t& getUpdateInfoRef(common::column_id_t columnID) const { + return getUpdateChunks(columnID).getOffsetToRowIdx(); } - -private: - std::vector insertInfo; - std::vector updateInfo; }; class LocalNodeTableData final : public LocalTableData { public: - LocalNodeTableData(std::vector dataTypes, MemoryManager* mm) - : LocalTableData{std::move(dataTypes), mm} {} + explicit LocalNodeTableData(std::vector dataTypes) + : LocalTableData{std::move(dataTypes)} {} void scan(common::ValueVector* nodeIDVector, const std::vector& columnIDs, const std::vector& outputVectors); void lookup(common::ValueVector* nodeIDVector, const std::vector& columnIDs, const std::vector& outputVectors); - void insert(common::ValueVector* nodeIDVector, - const std::vector& propertyVectors); - void update(common::ValueVector* nodeIDVector, common::column_id_t columnID, - common::ValueVector* propertyVector); - void delete_(common::ValueVector* nodeIDVector); private: LocalNodeGroup* getOrCreateLocalNodeGroup(common::ValueVector* nodeIDVector) override; }; +class LocalNodeTable final : public LocalTable { +public: + explicit LocalNodeTable(Table& table); + + bool insert(TableInsertState& insertState) override; + bool update(TableUpdateState& updateState) override; + bool delete_(TableDeleteState& deleteState) override; + + void scan(TableReadState& state) override; + void lookup(TableReadState& state) override; + + LocalNodeTableData* getTableData() { + KU_ASSERT(localTableDataCollection.size() == 1); + return common::ku_dynamic_cast( + localTableDataCollection[0].get()); + } +}; + } // namespace storage } // namespace kuzu diff --git a/src/include/storage/local_storage/local_rel_table.h b/src/include/storage/local_storage/local_rel_table.h index 553b083ea8c..1b8b003e4ef 100644 --- a/src/include/storage/local_storage/local_rel_table.h +++ b/src/include/storage/local_storage/local_rel_table.h @@ -1,117 +1,80 @@ #pragma once -#include "common/enums/rel_multiplicity.h" +#include "common/copy_constructors.h" +#include "common/enums/rel_direction.h" #include "common/vector/value_vector.h" #include "storage/local_storage/local_table.h" namespace kuzu { namespace storage { -static constexpr common::column_id_t REL_ID_COLUMN_ID = 0; - -// Info of node groups with CSR chunks for rel tables. -// Note that srcNodeOffset here are the relative offset within each node group. -struct RelNGInfo { - update_insert_info_t adjInsertInfo; - std::vector insertInfoPerChunk; - std::vector updateInfoPerChunk; - delete_info_t deleteInfo; - common::RelMultiplicity multiplicity; - - RelNGInfo(common::RelMultiplicity multiplicity, common::column_id_t numChunks) - : multiplicity{multiplicity} { - insertInfoPerChunk.resize(numChunks); - updateInfoPerChunk.resize(numChunks); - } - - bool insert(common::offset_t srcOffsetInChunk, common::offset_t relOffset, - common::row_idx_t adjNodeRowIdx, const std::vector& propertyNodesRowIdx); - void update(common::offset_t srcOffsetInChunk, common::offset_t relOffset, - common::column_id_t columnID, common::row_idx_t rowIdx); - bool delete_(common::offset_t srcOffsetInChunk, common::offset_t relOffset); - - bool hasUpdates(); - - uint64_t getNumInsertedTuples(common::offset_t srcOffsetInChunk); - - const update_insert_info_t& getUpdateInfo(common::column_id_t columnID) { - KU_ASSERT(columnID == common::INVALID_COLUMN_ID || columnID < updateInfoPerChunk.size()); - return columnID == common::INVALID_COLUMN_ID ? getEmptyInfo() : - updateInfoPerChunk[columnID]; - } - const update_insert_info_t& getInsertInfo(common::column_id_t columnID) { - KU_ASSERT(columnID == common::INVALID_COLUMN_ID || columnID < insertInfoPerChunk.size()); - return columnID == common::INVALID_COLUMN_ID ? adjInsertInfo : insertInfoPerChunk[columnID]; - } - const delete_info_t& getDeleteInfo() const { return deleteInfo; } - - const update_insert_info_t& getEmptyInfo(); - -private: - inline static bool contains( - const std::unordered_set& set, common::offset_t value) { - return set.find(value) != set.end(); - } -}; +static constexpr common::column_id_t LOCAL_NBR_ID_COLUMN_ID = 0; +static constexpr common::column_id_t LOCAL_REL_ID_COLUMN_ID = 1; class LocalRelNG final : public LocalNodeGroup { + friend class RelTableData; + public: - LocalRelNG(common::offset_t nodeGroupStartOffset, std::vector dataTypes, - MemoryManager* mm, common::RelMultiplicity multiplicity); + LocalRelNG(common::offset_t nodeGroupStartOffset, std::vector dataTypes); + DELETE_COPY_DEFAULT_MOVE(LocalRelNG); - common::row_idx_t scanCSR(common::offset_t srcOffsetInChunk, - common::offset_t posToReadForOffset, const std::vector& columnIDs, + common::row_idx_t scanCSR(common::offset_t srcOffset, common::offset_t posToReadForOffset, + const std::vector& columnIDs, const std::vector& outputVector); // For CSR, we need to apply updates and deletions here, while insertions are handled by // `scanCSR`. - void applyLocalChangesForCSRColumns(common::offset_t srcOffsetInChunk, + void applyLocalChangesToScannedVectors(common::offset_t srcOffset, const std::vector& columnIDs, common::ValueVector* relIDVector, const std::vector& outputVectors); - bool insert(common::ValueVector* srcNodeIDVector, common::ValueVector* dstNodeIDVector, - const std::vector& propertyVectors); - void update(common::ValueVector* srcNodeIDVector, common::ValueVector* relIDVector, - common::column_id_t columnID, common::ValueVector* propertyVector); - bool delete_(common::ValueVector* srcNodeIDVector, common::ValueVector* relIDVector); + bool insert(std::vector nodeIDVectors, + std::vector vectors) override; + bool update(std::vector nodeIDVectors, common::column_id_t columnID, + common::ValueVector* propertyVector) override; + bool delete_(common::ValueVector* srcNodeVector, common::ValueVector* relIDVector) override; - inline LocalVectorCollection* getAdjChunk() { return adjChunk.get(); } - inline LocalVectorCollection* getPropertyChunk(common::column_id_t columnID) { - KU_ASSERT(columnID < chunks.size()); - return chunks[columnID].get(); - } - inline RelNGInfo* getRelNGInfo() { return relNGInfo.get(); } + common::offset_t getNumInsertedRels(common::offset_t srcOffset) const; + void getChangesPerCSRSegment(std::vector& sizeChangesPerSegment, + std::vector& hasChangesPerSegment); private: - void applyCSRUpdates(common::offset_t srcOffsetInChunk, common::column_id_t columnID, - common::ValueVector* relIDVector, common::ValueVector* outputVector); - void applyCSRDeletions(common::offset_t srcOffsetInChunk, const delete_info_t& deleteInfo, - common::ValueVector* relIDVector); + static common::vector_idx_t getSegmentIdx(common::offset_t offset) { + return offset >> common::StorageConstants::CSR_SEGMENT_SIZE_LOG2; + } -private: - std::unique_ptr adjChunk; - std::unique_ptr relNGInfo; + void applyCSRUpdates(common::column_id_t columnID, common::ValueVector* relIDVector, + common::ValueVector* outputVector); + void applyCSRDeletions(common::offset_t srcOffsetInChunk, common::ValueVector* relIDVector); }; class LocalRelTableData final : public LocalTableData { friend class RelTableData; public: - LocalRelTableData(common::RelMultiplicity multiplicity, - std::vector dataTypes, MemoryManager* mm) - : LocalTableData{std::move(dataTypes), mm}, multiplicity{multiplicity} {} - - bool insert(common::ValueVector* srcNodeIDVector, common::ValueVector* dstNodeIDVector, - const std::vector& propertyVectors); - void update(common::ValueVector* srcNodeIDVector, common::ValueVector* relIDVector, - common::column_id_t columnID, common::ValueVector* propertyVector); - bool delete_(common::ValueVector* srcNodeIDVector, common::ValueVector* dstNodeIDVector, - common::ValueVector* relIDVector); + explicit LocalRelTableData(std::vector dataTypes) + : LocalTableData{std::move(dataTypes)} {} private: LocalNodeGroup* getOrCreateLocalNodeGroup(common::ValueVector* nodeIDVector) override; +}; -private: - common::RelMultiplicity multiplicity; +class LocalRelTable final : public LocalTable { +public: + explicit LocalRelTable(Table& table); + + bool insert(TableInsertState& insertState) override; + bool update(TableUpdateState& updateState) override; + bool delete_(TableDeleteState& deleteState) override; + + void scan(TableReadState& state) override; + void lookup(TableReadState& state) override; + + LocalRelTableData* getTableData(common::RelDataDirection direction) { + KU_ASSERT(localTableDataCollection.size() == 2); + return common::ku_dynamic_cast( + direction == common::RelDataDirection::FWD ? localTableDataCollection[0].get() : + localTableDataCollection[1].get()); + } }; } // namespace storage diff --git a/src/include/storage/local_storage/local_storage.h b/src/include/storage/local_storage/local_storage.h index 26f8804a14a..c02c4809b27 100644 --- a/src/include/storage/local_storage/local_storage.h +++ b/src/include/storage/local_storage/local_storage.h @@ -2,37 +2,35 @@ #include +#include "common/copy_constructors.h" #include "storage/local_storage/local_table.h" namespace kuzu { -namespace catalog { -class TableCatalogEntry; -} +namespace main { +class ClientContext; +} // namespace main namespace storage { -class MemoryManager; - // Data structures in LocalStorage are not thread-safe. // For now, we only support single thread insertions and updates. Once we optimize them with // multiple threads, LocalStorage and its related data structures should be reworked to be // thread-safe. class LocalStorage { public: - explicit LocalStorage(storage::MemoryManager* mm); - - // This function will create the local table data if not exists. - LocalTableData* getOrCreateLocalTableData(common::table_id_t tableID, - const std::vector>& columns, - common::TableType tableType = common::TableType::NODE, common::vector_idx_t dataIdx = 0, - common::RelMultiplicity multiplicity = common::RelMultiplicity::MANY); - LocalTable* getLocalTable(common::table_id_t tableID); - // This function will return nullptr if the local table does not exist. - LocalTableData* getLocalTableData(common::table_id_t tableID, common::vector_idx_t dataIdx = 0); - std::unordered_set getTableIDsWithUpdates(); + enum class NotExistAction { CREATE, RETURN_NULL }; + + explicit LocalStorage(main::ClientContext& clientContext) : clientContext{clientContext} {} + DELETE_COPY_AND_MOVE(LocalStorage); + + LocalTable* getLocalTable(common::table_id_t tableID, + NotExistAction action = NotExistAction::RETURN_NULL); + + void prepareCommit(); + void prepareRollback(); private: + main::ClientContext& clientContext; std::unordered_map> tables; - storage::MemoryManager* mm; }; } // namespace storage diff --git a/src/include/storage/local_storage/local_table.h b/src/include/storage/local_storage/local_table.h index cb0f26a6150..1d0aa0f7611 100644 --- a/src/include/storage/local_storage/local_table.h +++ b/src/include/storage/local_storage/local_table.h @@ -1,130 +1,224 @@ #pragma once -#include +#include -#include "common/enums/rel_multiplicity.h" -#include "common/enums/table_type.h" #include "common/vector/value_vector.h" +#include "storage/store/chunked_node_group_collection.h" namespace kuzu { -namespace catalog { -class TableCatalogEntry; -} // namespace catalog namespace storage { -class TableData; -using offset_to_row_idx_t = std::map; +using offset_to_row_idx_t = std::unordered_map; +using offset_to_row_idx_vec_t = + std::unordered_map>; using offset_set_t = std::unordered_set; -using update_insert_info_t = std::map; -using delete_info_t = std::map>; -// TODO(Guodong): Instead of using ValueVector, we should switch to ColumnChunk. -// This class is used to store a chunk of local changes to a column in a node group. -// Values are stored inside `vector`. -class LocalVector { +static constexpr common::column_id_t NBR_ID_COLUMN_ID = 0; +static constexpr common::column_id_t REL_ID_COLUMN_ID = 1; + +using ChunkCollection = std::vector; + +class LocalChunkedGroupCollection { public: - LocalVector(const common::LogicalType& dataType, MemoryManager* mm) : numValues{0} { - vector = std::make_unique(dataType, mm); - vector->setState(std::make_shared()); - vector->state->selVector->resetSelectorToValuePosBufferWithSize(1); + explicit LocalChunkedGroupCollection(std::vector dataTypes) + : dataTypes{std::move(dataTypes)}, chunkedGroups{this->dataTypes}, numRows{0} {} + DELETE_COPY_DEFAULT_MOVE(LocalChunkedGroupCollection); + + static inline std::pair getChunkIdxAndOffsetInChunk( + common::row_idx_t rowIdx) { + return std::make_pair(rowIdx / ChunkedNodeGroupCollection::CHUNK_CAPACITY, + rowIdx % ChunkedNodeGroupCollection::CHUNK_CAPACITY); + } + + inline common::row_idx_t getRowIdxFromOffset(common::offset_t offset) const { + KU_ASSERT(offsetToRowIdx.contains(offset)); + return offsetToRowIdx.at(offset); + } + inline const std::vector& getRelOffsetsFromSrcOffset( + common::offset_t srcOffset) const { + KU_ASSERT(srcNodeOffsetToRelOffsets.contains(srcOffset)); + return srcNodeOffsetToRelOffsets.at(srcOffset); } + inline bool hasOffset(common::offset_t offset) const { return offsetToRowIdx.contains(offset); } + inline bool hasRelOffsetsFromSrcOffset(common::offset_t srcOffset) const { + return srcNodeOffsetToRelOffsets.contains(srcOffset); + } + inline uint64_t getNumRelsFromSrcOffset(common::offset_t srcOffset) const { + return srcNodeOffsetToRelOffsets.at(srcOffset).size(); + } + inline const offset_to_row_idx_vec_t& getSrcNodeOffsetToRelOffsets() const { + return srcNodeOffsetToRelOffsets; + } + inline const offset_to_row_idx_t& getOffsetToRowIdx() const { return offsetToRowIdx; } + + void appendChunkedGroup(ColumnChunk* srcOffsetChunk, + std::unique_ptr chunkedGroup); + + bool isEmpty() const { return offsetToRowIdx.empty() && srcNodeOffsetToRelOffsets.empty(); } + void readValueAtRowIdx(common::row_idx_t rowIdx, common::column_id_t columnID, + common::ValueVector* outputVector, common::sel_t posInOutputVector) const; + bool read(common::offset_t offset, common::column_id_t columnID, + common::ValueVector* outputVector, common::sel_t posInOutputVector); - void read(common::sel_t offsetInLocalVector, common::ValueVector* resultVector, - common::sel_t offsetInResultVector); - void append(common::ValueVector* valueVector); + inline void append(common::offset_t offset, std::vector vectors) { + offsetToRowIdx[offset] = append(vectors); + } + // Only used for rel tables. Should be moved out later. + inline void append(common::offset_t nodeOffset, common::offset_t relOffset, + std::vector vectors) { + append(relOffset, vectors); + srcNodeOffsetToRelOffsets[nodeOffset].push_back(relOffset); + } + void update(common::offset_t offset, common::column_id_t columnID, + common::ValueVector* propertyVector); + void remove(common::offset_t offset) { + if (offsetToRowIdx.contains(offset)) { + offsetToRowIdx.erase(offset); + } + } + // Only used for rel tables. Should be moved out later. + void remove(common::offset_t srcNodeOffset, common::offset_t relOffset); + + inline ChunkCollection getLocalChunk(common::column_id_t columnID) { + ChunkCollection localChunkCollection; + for (auto& chunkedGroup : chunkedGroups.getChunkedGroups()) { + localChunkCollection.push_back(&chunkedGroup->getColumnChunkUnsafe(columnID)); + } + return localChunkCollection; + } - inline common::ValueVector* getVector() { return vector.get(); } - inline bool isFull() const { return numValues == common::DEFAULT_VECTOR_CAPACITY; } +private: + common::row_idx_t append(std::vector vectors); private: - std::unique_ptr vector; - common::sel_t numValues; + std::vector dataTypes; + ChunkedNodeGroupCollection chunkedGroups; + // The offset here can either be nodeOffset ( for node table) or relOffset (for rel table). + offset_to_row_idx_t offsetToRowIdx; + common::row_idx_t numRows; + + // Only used for rel tables. Should be moved out later. + offset_to_row_idx_vec_t srcNodeOffsetToRelOffsets; }; -// This class is used to store local changes of a column in a node group. -// It consists of a collection of LocalVector, each of which is a chunk of the local changes. -// By default, the size of each vector (chunk) is DEFAULT_VECTOR_CAPACITY, and the collection -// contains 64 vectors (chunks). -class LocalVectorCollection { +class LocalDeletionInfo { public: - LocalVectorCollection(std::unique_ptr dataType, MemoryManager* mm) - : dataType{std::move(dataType)}, mm{mm}, numRows{0} {} - - void read(common::row_idx_t rowIdx, common::ValueVector* outputVector, - common::sel_t posInOutputVector); - inline uint64_t getNumRows() const { return numRows; } - inline LocalVector* getLocalVector(common::row_idx_t rowIdx) { - auto vectorIdx = rowIdx >> common::DEFAULT_VECTOR_CAPACITY_LOG_2; - KU_ASSERT(vectorIdx < vectors.size()); - return vectors[vectorIdx].get(); + bool isEmpty() const { return deletedOffsets.empty() && srcNodeOffsetToRelOffsetVec.empty(); } + bool isEmpty(common::offset_t srcOffset) const { + return !srcNodeOffsetToRelOffsetVec.contains(srcOffset) || + srcNodeOffsetToRelOffsetVec.at(srcOffset).empty(); + } + bool containsOffset(common::offset_t offset) { return deletedOffsets.contains(offset); } + bool deleteOffset(common::offset_t offset) { + if (deletedOffsets.contains(offset)) { + return false; + } + deletedOffsets.insert(offset); + return true; } - std::unique_ptr getStructChildVectorCollection( - common::struct_field_idx_t idx); - - // TODO(Guodong): Change this interface to take an extra `SelVector` or `DataChunkState`. - common::row_idx_t append(common::ValueVector* vector); + // For rel tables only. + void deleteRelAux(common::offset_t srcNodeOffset, common::offset_t relOffset) { + srcNodeOffsetToRelOffsetVec[srcNodeOffset].push_back(relOffset); + } + const offset_to_row_idx_vec_t& getSrcNodeOffsetToRelOffsetVec() const { + return srcNodeOffsetToRelOffsetVec; + } + uint64_t getNumDeletedRelsFromSrcOffset(common::offset_t srcOffset) const { + return srcNodeOffsetToRelOffsetVec.contains(srcOffset) ? + srcNodeOffsetToRelOffsetVec.at(srcOffset).size() : + 0; + } private: - void prepareAppend(); + // The offset here can either be nodeOffset ( for node table) or relOffset (for rel table). + offset_set_t deletedOffsets; -private: - std::unique_ptr dataType; - MemoryManager* mm; - std::vector> vectors; - common::row_idx_t numRows; + // Only used for rel tables. Should be moved out later. + offset_to_row_idx_vec_t srcNodeOffsetToRelOffsetVec; }; class LocalNodeGroup { - friend class NodeTableData; - public: LocalNodeGroup(common::offset_t nodeGroupStartOffset, - std::vector dataTypes, MemoryManager* mm); + const std::vector& dataTypes); + DELETE_COPY_DEFAULT_MOVE(LocalNodeGroup); virtual ~LocalNodeGroup() = default; - inline LocalVectorCollection* getLocalColumnChunk(common::column_id_t columnID) { - return chunks[columnID].get(); + virtual bool insert(std::vector nodeIDVectors, + std::vector propertyVectors) = 0; + virtual bool update(std::vector nodeIDVectors, + common::column_id_t columnID, common::ValueVector* propertyVector) = 0; + virtual bool delete_(common::ValueVector* IDVector, common::ValueVector* extraVector) = 0; + + const LocalChunkedGroupCollection& getUpdateChunks(common::column_id_t columnID) const { + KU_ASSERT(columnID < updateChunks.size()); + return updateChunks[columnID]; } + LocalChunkedGroupCollection& getUpdateChunks(common::column_id_t columnID) { + KU_ASSERT(columnID < updateChunks.size()); + return updateChunks[columnID]; + } + LocalChunkedGroupCollection& getInsesrtChunks() { return insertChunks; } + + bool hasUpdatesOrDeletions() const; protected: common::offset_t nodeGroupStartOffset; - std::vector> chunks; + + LocalChunkedGroupCollection insertChunks; + LocalDeletionInfo deleteInfo; + std::vector updateChunks; }; class LocalTableData { friend class NodeTableData; public: - LocalTableData(std::vector dataTypes, MemoryManager* mm) - : dataTypes{std::move(dataTypes)}, mm{mm} {} + explicit LocalTableData(std::vector dataTypes) + : dataTypes{std::move(dataTypes)} {} virtual ~LocalTableData() = default; inline void clear() { nodeGroups.clear(); } + bool insert(std::vector nodeIDVectors, + std::vector propertyVectors); + bool update(std::vector nodeIDVectors, common::column_id_t columnID, + common::ValueVector* propertyVector); + bool delete_(common::ValueVector* nodeIDVector, common::ValueVector* extraVector = nullptr); + protected: virtual LocalNodeGroup* getOrCreateLocalNodeGroup(common::ValueVector* nodeIDVector) = 0; protected: - std::vector dataTypes; - MemoryManager* mm; + std::vector dataTypes; + std::unordered_map> nodeGroups; }; -class Column; +struct TableInsertState; +struct TableUpdateState; +struct TableDeleteState; +struct TableReadState; +class Table; class LocalTable { public: - explicit LocalTable(common::TableType tableType) : tableType{tableType} {}; + virtual ~LocalTable() = default; - LocalTableData* getOrCreateLocalTableData(const std::vector>& columns, - MemoryManager* mm, common::vector_idx_t dataIdx, common::RelMultiplicity multiplicity); - inline LocalTableData* getLocalTableData(common::vector_idx_t dataIdx) { - KU_ASSERT(dataIdx < localTableDataCollection.size()); - return localTableDataCollection[dataIdx].get(); - } + virtual bool insert(TableInsertState& insertState) = 0; + virtual bool update(TableUpdateState& updateState) = 0; + virtual bool delete_(TableDeleteState& deleteState) = 0; -private: - common::TableType tableType; + virtual void scan(TableReadState& state) = 0; + virtual void lookup(TableReadState& state) = 0; + + inline void clear() { localTableDataCollection.clear(); } + +protected: + explicit LocalTable(Table& table) : table{table} {} + +protected: + Table& table; // For a node table, it should only contain one LocalTableData, while a rel table should contain // two, one for each direction. std::vector> localTableDataCollection; diff --git a/src/include/storage/stats/node_table_statistics.h b/src/include/storage/stats/node_table_statistics.h index 520e0a5c3d8..a50fa3d3fa4 100644 --- a/src/include/storage/stats/node_table_statistics.h +++ b/src/include/storage/stats/node_table_statistics.h @@ -36,11 +36,8 @@ class NodeTableStatsAndDeletedIDs : public TableStatistics { void deleteNode(common::offset_t nodeOffset); - // This function assumes that it is being called right after ScanNodeID has obtained a - // morsel and that the nodeID structs in nodeOffsetVector.values have consecutive node - // offsets and the same tableID. - void setDeletedNodeOffsetsForMorsel( - const std::shared_ptr& nodeOffsetVector); + // This function assumes nodeIDVector have consecutive node offsets and the same tableID. + void setDeletedNodeOffsetsForMorsel(common::ValueVector* nodeIDVector) const; void setNumTuples(uint64_t numTuples) override; diff --git a/src/include/storage/stats/nodes_store_statistics.h b/src/include/storage/stats/nodes_store_statistics.h index 5c01b3fd901..5e0cf9cd1f1 100644 --- a/src/include/storage/stats/nodes_store_statistics.h +++ b/src/include/storage/stats/nodes_store_statistics.h @@ -4,7 +4,6 @@ #include "storage/stats/node_table_statistics.h" #include "storage/stats/table_statistics_collection.h" #include "storage/storage_utils.h" -#include "transaction/transaction.h" namespace kuzu { namespace storage { @@ -16,8 +15,8 @@ class NodesStoreStatsAndDeletedIDs : public TablesStatistics { // Should only be used by saveInitialNodesStatisticsAndDeletedIDsToFile to start a database // from an empty directory. explicit NodesStoreStatsAndDeletedIDs(common::VirtualFileSystem* vfs) - : TablesStatistics{ - nullptr /* metadataFH */, nullptr /* bufferManager */, nullptr /* wal */, vfs} {}; + : TablesStatistics{nullptr /* metadataFH */, nullptr /* bufferManager */, nullptr /* wal */, + vfs} {}; // Should be used when an already loaded database is started from a directory. NodesStoreStatsAndDeletedIDs(BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, common::VirtualFileSystem* vfs, @@ -27,25 +26,20 @@ class NodesStoreStatsAndDeletedIDs : public TablesStatistics { } inline NodeTableStatsAndDeletedIDs* getNodeStatisticsAndDeletedIDs( - common::table_id_t tableID) const { - return getNodeTableStats(transaction::TransactionType::READ_ONLY, tableID); + transaction::Transaction* transaction, common::table_id_t tableID) const { + return getNodeTableStats(transaction->getType(), tableID); } - static inline void saveInitialNodesStatisticsAndDeletedIDsToFile( - common::VirtualFileSystem* vfs, const std::string& directory) { - std::make_unique(vfs)->saveToFile( - directory, common::FileVersionType::ORIGINAL, transaction::TransactionType::READ_ONLY); + static inline void saveInitialNodesStatisticsAndDeletedIDsToFile(common::VirtualFileSystem* vfs, + const std::string& directory) { + std::make_unique(vfs)->saveToFile(directory, + common::FileVersionType::ORIGINAL, transaction::TransactionType::READ_ONLY); } - inline void setNumTuplesForTable(common::table_id_t tableID, uint64_t numTuples) override { - initTableStatisticsForWriteTrx(); - KU_ASSERT(readWriteVersion && readWriteVersion->tableStatisticPerTable.contains(tableID)); - setToUpdated(); - getNodeTableStats(transaction::TransactionType::WRITE, tableID)->setNumTuples(numTuples); - } + void updateNumTuplesByValue(common::table_id_t tableID, int64_t value) override; - common::offset_t getMaxNodeOffset( - transaction::Transaction* transaction, common::table_id_t tableID); + common::offset_t getMaxNodeOffset(transaction::Transaction* transaction, + common::table_id_t tableID); // This function is only used for testing purpose. inline uint32_t getNumNodeStatisticsAndDeleteIDsPerTable() const { @@ -71,12 +65,8 @@ class NodesStoreStatsAndDeletedIDs : public TablesStatistics { getNodeTableStats(transaction::TransactionType::WRITE, tableID)->deleteNode(nodeOffset); } - // This function is only used by storageManager to construct relsStore during start-up, so - // we can just safely return the maxNodeOffsetPerTable for readOnlyVersion. - std::map getMaxNodeOffsetPerTable() const; - - void setDeletedNodeOffsetsForMorsel(transaction::Transaction* transaction, - const std::shared_ptr& nodeOffsetVector, common::table_id_t tableID); + void setDeletedNodeOffsetsForMorsel(transaction::Transaction* tx, + common::ValueVector* nodeIDVector, common::table_id_t tableID); void addNodeStatisticsAndDeletedIDs(catalog::NodeTableCatalogEntry* nodeTableEntry); @@ -88,8 +78,8 @@ class NodesStoreStatsAndDeletedIDs : public TablesStatistics { protected: inline std::unique_ptr constructTableStatistic( catalog::TableCatalogEntry* tableEntry) override { - return std::make_unique( - metadataFH, *tableEntry, bufferManager, wal); + return std::make_unique(metadataFH, *tableEntry, bufferManager, + wal); } inline std::unique_ptr constructTableStatistic( @@ -98,8 +88,8 @@ class NodesStoreStatsAndDeletedIDs : public TablesStatistics { *(NodeTableStatsAndDeletedIDs*)tableStatistics); } - inline std::string getTableStatisticsFilePath( - const std::string& directory, common::FileVersionType dbFileType) override { + inline std::string getTableStatisticsFilePath(const std::string& directory, + common::FileVersionType dbFileType) override { return StorageUtils::getNodesStatisticsAndDeletedIDsFilePath(vfs, directory, dbFileType); } diff --git a/src/include/storage/stats/rel_table_statistics.h b/src/include/storage/stats/rel_table_statistics.h index 2a9348630e3..561b37b35fd 100644 --- a/src/include/storage/stats/rel_table_statistics.h +++ b/src/include/storage/stats/rel_table_statistics.h @@ -14,8 +14,8 @@ class RelTableStats : public TableStatistics { RelTableStats(BMFileHandle* metadataFH, const catalog::TableCatalogEntry& tableEntry, BufferManager* bufferManager, WAL* wal); RelTableStats(uint64_t numRels, common::table_id_t tableID, common::offset_t nextRelOffset) - : TableStatistics{common::TableType::REL, numRels, tableID, {}}, nextRelOffset{ - nextRelOffset} {} + : TableStatistics{common::TableType::REL, numRels, tableID, {}}, + nextRelOffset{nextRelOffset} {} RelTableStats(uint64_t numRels, common::table_id_t tableID, std::unordered_map>&& propertyStats, @@ -28,14 +28,14 @@ class RelTableStats : public TableStatistics { inline common::offset_t getNextRelOffset() const { return nextRelOffset; } inline void incrementNextRelOffset(uint64_t numTuples) { nextRelOffset += numTuples; } - inline void addMetadataDAHInfoForColumn( - std::unique_ptr metadataDAHInfo, common::RelDataDirection direction) { - auto& metadataDAHInfos = getDirectedPropertyMetadataDAHInfosRef(direction); + inline void addMetadataDAHInfoForColumn(std::unique_ptr metadataDAHInfo, + common::RelDataDirection direction) { + auto& metadataDAHInfos = getDirectedMetadataDAHInfosRef(direction); metadataDAHInfos.push_back(std::move(metadataDAHInfo)); } - inline void removeMetadataDAHInfoForColumn( - common::column_id_t columnID, common::RelDataDirection direction) { - auto& metadataDAHInfos = getDirectedPropertyMetadataDAHInfosRef(direction); + inline void removeMetadataDAHInfoForColumn(common::column_id_t columnID, + common::RelDataDirection direction) { + auto& metadataDAHInfos = getDirectedMetadataDAHInfosRef(direction); KU_ASSERT(columnID < metadataDAHInfos.size()); metadataDAHInfos.erase(metadataDAHInfos.begin() + columnID); } @@ -47,30 +47,26 @@ class RelTableStats : public TableStatistics { return direction == common::RelDataDirection::FWD ? fwdCSRLengthMetadataDAHInfo.get() : bwdCSRLengthMetadataDAHInfo.get(); } - inline MetadataDAHInfo* getAdjMetadataDAHInfo(common::RelDataDirection direction) { - return direction == common::RelDataDirection::FWD ? fwdAdjMetadataDAHInfo.get() : - bwdAdjMetadataDAHInfo.get(); - } - inline MetadataDAHInfo* getPropertyMetadataDAHInfo( - common::column_id_t columnID, common::RelDataDirection direction) { - auto& metadataDAHInfos = getDirectedPropertyMetadataDAHInfosRef(direction); + inline MetadataDAHInfo* getColumnMetadataDAHInfo(common::column_id_t columnID, + common::RelDataDirection direction) { + auto& metadataDAHInfos = getDirectedMetadataDAHInfosRef(direction); KU_ASSERT(columnID < metadataDAHInfos.size()); return metadataDAHInfos[columnID].get(); } void serializeInternal(common::Serializer& serializer) final; - static std::unique_ptr deserialize( - uint64_t numRels, common::table_id_t tableID, common::Deserializer& deserializer); + static std::unique_ptr deserialize(uint64_t numRels, common::table_id_t tableID, + common::Deserializer& deserializer); inline std::unique_ptr copy() final { return std::make_unique(*this); } private: - inline std::vector>& getDirectedPropertyMetadataDAHInfosRef( + inline std::vector>& getDirectedMetadataDAHInfosRef( common::RelDataDirection direction) { - return direction == common::RelDataDirection::FWD ? fwdPropertyMetadataDAHInfos : - bwdPropertyMetadataDAHInfos; + return direction == common::RelDataDirection::FWD ? fwdMetadataDAHInfos : + bwdMetadataDAHInfos; } private: @@ -80,10 +76,8 @@ class RelTableStats : public TableStatistics { std::unique_ptr bwdCSROffsetMetadataDAHInfo; std::unique_ptr fwdCSRLengthMetadataDAHInfo; std::unique_ptr bwdCSRLengthMetadataDAHInfo; - std::unique_ptr fwdAdjMetadataDAHInfo; - std::unique_ptr bwdAdjMetadataDAHInfo; - std::vector> fwdPropertyMetadataDAHInfos; - std::vector> bwdPropertyMetadataDAHInfos; + std::vector> fwdMetadataDAHInfos; + std::vector> bwdMetadataDAHInfos; }; } // namespace storage diff --git a/src/include/storage/stats/rels_store_statistics.h b/src/include/storage/stats/rels_store_statistics.h index 48c79f4dcc7..2012b9c2a54 100644 --- a/src/include/storage/stats/rels_store_statistics.h +++ b/src/include/storage/stats/rels_store_statistics.h @@ -13,20 +13,20 @@ class RelsStoreStats : public TablesStatistics { // Should only be used by saveInitialRelsStatisticsToFile to start a database from an empty // directory. explicit RelsStoreStats(common::VirtualFileSystem* vfs) - : TablesStatistics{ - nullptr /* metadataFH */, nullptr /* bufferManager */, nullptr /* wal */, vfs} {}; + : TablesStatistics{nullptr /* metadataFH */, nullptr /* bufferManager */, nullptr /* wal */, + vfs} {}; // Should be used when an already loaded database is started from a directory. RelsStoreStats(BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, common::VirtualFileSystem* vfs); - static inline void saveInitialRelsStatisticsToFile( - common::VirtualFileSystem* vfs, const std::string& directory) { - std::make_unique(vfs)->saveToFile( - directory, common::FileVersionType::ORIGINAL, transaction::TransactionType::READ_ONLY); + static inline void saveInitialRelsStatisticsToFile(common::VirtualFileSystem* vfs, + const std::string& directory) { + std::make_unique(vfs)->saveToFile(directory, + common::FileVersionType::ORIGINAL, transaction::TransactionType::READ_ONLY); } - inline RelTableStats* getRelStatistics( - common::table_id_t tableID, transaction::Transaction* transaction) const { + inline RelTableStats* getRelStatistics(common::table_id_t tableID, + transaction::Transaction* transaction) const { auto& tableStatisticPerTable = transaction->getType() == transaction::TransactionType::READ_ONLY ? readOnlyVersion->tableStatisticPerTable : @@ -35,12 +35,10 @@ class RelsStoreStats : public TablesStatistics { return (RelTableStats*)tableStatisticPerTable[tableID].get(); } - void setNumTuplesForTable(common::table_id_t relTableID, uint64_t numRels) override; + void updateNumTuplesByValue(common::table_id_t relTableID, int64_t value) override; - void updateNumRelsByValue(common::table_id_t relTableID, int64_t value); - - common::offset_t getNextRelOffset( - transaction::Transaction* transaction, common::table_id_t tableID); + common::offset_t getNextRelOffset(transaction::Transaction* transaction, + common::table_id_t tableID); void addMetadataDAHInfo(common::table_id_t tableID, const common::LogicalType& dataType); void removeMetadataDAHInfo(common::table_id_t tableID, common::column_id_t columnID); @@ -48,9 +46,7 @@ class RelsStoreStats : public TablesStatistics { common::table_id_t tableID, common::RelDataDirection direction); MetadataDAHInfo* getCSRLengthMetadataDAHInfo(transaction::Transaction* transaction, common::table_id_t tableID, common::RelDataDirection direction); - MetadataDAHInfo* getAdjMetadataDAHInfo(transaction::Transaction* transaction, - common::table_id_t tableID, common::RelDataDirection direction); - MetadataDAHInfo* getPropertyMetadataDAHInfo(transaction::Transaction* transaction, + MetadataDAHInfo* getColumnMetadataDAHInfo(transaction::Transaction* transaction, common::table_id_t tableID, common::column_id_t columnID, common::RelDataDirection direction); @@ -65,8 +61,8 @@ class RelsStoreStats : public TablesStatistics { return std::make_unique(*(RelTableStats*)tableStatistics); } - inline std::string getTableStatisticsFilePath( - const std::string& directory, common::FileVersionType dbFileType) override { + inline std::string getTableStatisticsFilePath(const std::string& directory, + common::FileVersionType dbFileType) override { return StorageUtils::getRelsStatisticsFilePath(vfs, directory, dbFileType); } diff --git a/src/include/storage/stats/table_statistics.h b/src/include/storage/stats/table_statistics.h index 9ba30f56e2b..319a01d13c2 100644 --- a/src/include/storage/stats/table_statistics.h +++ b/src/include/storage/stats/table_statistics.h @@ -35,8 +35,8 @@ class TableStatistics { KU_ASSERT(propertyStatistics.contains(propertyID)); return *(propertyStatistics.at(propertyID)); } - inline void setPropertyStatistics( - common::property_id_t propertyID, PropertyStatistics newStats) { + inline void setPropertyStatistics(common::property_id_t propertyID, + PropertyStatistics newStats) { propertyStatistics[propertyID] = std::make_unique(newStats); } diff --git a/src/include/storage/stats/table_statistics_collection.h b/src/include/storage/stats/table_statistics_collection.h index d2c3d0dd8d7..6e834ef5df6 100644 --- a/src/include/storage/stats/table_statistics_collection.h +++ b/src/include/storage/stats/table_statistics_collection.h @@ -11,6 +11,11 @@ namespace storage { struct TablesStatisticsContent { std::unordered_map> tableStatisticPerTable; + + const TableStatistics* getTableStat(common::table_id_t tableID) const { + KU_ASSERT(tableStatisticPerTable.contains(tableID)); + return tableStatisticPerTable.at(tableID).get(); + } }; class WAL; @@ -21,11 +26,12 @@ class TablesStatistics { virtual ~TablesStatistics() = default; - virtual void setNumTuplesForTable(common::table_id_t tableID, uint64_t numTuples) = 0; + // Return the num of tuples before update. + virtual void updateNumTuplesByValue(common::table_id_t tableID, int64_t value) = 0; inline void writeTablesStatisticsFileForWALRecord(const std::string& directory) { - saveToFile( - directory, common::FileVersionType::WAL_VERSION, transaction::TransactionType::WRITE); + saveToFile(directory, common::FileVersionType::WAL_VERSION, + transaction::TransactionType::WRITE); } inline bool hasUpdates() const { return isUpdated; } @@ -54,15 +60,22 @@ class TablesStatistics { readOnlyVersion->tableStatisticPerTable.erase(tableID); } - inline uint64_t getNumTuplesForTable(common::table_id_t tableID) { - return readOnlyVersion->tableStatisticPerTable[tableID]->getNumTuples(); + inline uint64_t getNumTuplesForTable(transaction::Transaction* transaction, + common::table_id_t tableID) { + if (transaction->isWriteTransaction()) { + initTableStatisticsForWriteTrx(); + KU_ASSERT(readWriteVersion->tableStatisticPerTable.contains(tableID)); + return readWriteVersion->tableStatisticPerTable.at(tableID)->getNumTuples(); + } + KU_ASSERT(readOnlyVersion->tableStatisticPerTable.contains(tableID)); + return readOnlyVersion->tableStatisticPerTable.at(tableID)->getNumTuples(); } PropertyStatistics& getPropertyStatisticsForTable(const transaction::Transaction& transaction, common::table_id_t tableID, common::property_id_t propertyID); - void setPropertyStatisticsForTable( - common::table_id_t tableID, common::property_id_t propertyID, PropertyStatistics stats); + void setPropertyStatisticsForTable(common::table_id_t tableID, common::property_id_t propertyID, + PropertyStatistics stats); static std::unique_ptr createMetadataDAHInfo( const common::LogicalType& dataType, BMFileHandle& metadataFH, BufferManager* bm, WAL* wal); @@ -76,8 +89,13 @@ class TablesStatistics { virtual std::unique_ptr constructTableStatistic( TableStatistics* tableStatistics) = 0; - virtual std::string getTableStatisticsFilePath( - const std::string& directory, common::FileVersionType dbFileType) = 0; + virtual std::string getTableStatisticsFilePath(const std::string& directory, + common::FileVersionType dbFileType) = 0; + + const TablesStatisticsContent* getVersion(transaction::TransactionType type) const { + return type == transaction::TransactionType::READ_ONLY ? readOnlyVersion.get() : + readWriteVersion.get(); + } void readFromFile(); void readFromFile(common::FileVersionType dbFileType); diff --git a/src/include/storage/storage_extension.h b/src/include/storage/storage_extension.h new file mode 100644 index 00000000000..9502e85ac01 --- /dev/null +++ b/src/include/storage/storage_extension.h @@ -0,0 +1,29 @@ +#pragma once + +#include "main/attached_database.h" + +namespace kuzu { +namespace storage { + +using attach_function_t = std::unique_ptr (*)(std::string dbPath, + std::string dbName, main::ClientContext* clientContext); + +class StorageExtension { +public: + explicit StorageExtension(attach_function_t attachFunction) + : attachFunction{std::move(attachFunction)} {} + virtual bool canHandleDB(std::string /*dbType*/) const { return false; } + + std::unique_ptr attach(std::string dbPath, std::string dbName, + main::ClientContext* clientContext) const { + return attachFunction(dbPath, dbName, clientContext); + } + + virtual ~StorageExtension() = default; + +private: + attach_function_t attachFunction; +}; + +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/storage_manager.h b/src/include/storage/storage_manager.h index 1e912987ea4..dc3888cdbfe 100644 --- a/src/include/storage/storage_manager.h +++ b/src/include/storage/storage_manager.h @@ -4,7 +4,6 @@ #include "storage/index/hash_index.h" #include "storage/stats/nodes_store_statistics.h" #include "storage/stats/rels_store_statistics.h" -#include "storage/store/node_table.h" #include "storage/store/rel_table.h" #include "storage/wal/wal.h" @@ -27,17 +26,9 @@ class StorageManager { PrimaryKeyIndex* getPKIndex(common::table_id_t tableID); - inline NodeTable* getNodeTable(common::table_id_t tableID) const { - KU_ASSERT(tables.contains(tableID) && - tables.at(tableID)->getTableType() == common::TableType::NODE); - auto table = common::ku_dynamic_cast(tables.at(tableID).get()); - return table; - } - inline RelTable* getRelTable(common::table_id_t tableID) const { - KU_ASSERT(tables.contains(tableID) && - tables.at(tableID)->getTableType() == common::TableType::REL); - auto table = common::ku_dynamic_cast(tables.at(tableID).get()); - return table; + inline Table* getTable(common::table_id_t tableID) const { + KU_ASSERT(tables.contains(tableID)); + return tables.at(tableID).get(); } inline WAL* getWAL() const { return wal; } @@ -58,6 +49,10 @@ class StorageManager { void createNodeTable(common::table_id_t tableID, catalog::NodeTableCatalogEntry* tableSchema); void createRelTable(common::table_id_t tableID, catalog::RelTableCatalogEntry* tableSchema, catalog::Catalog* catalog, transaction::Transaction* transaction); + void createRelTableGroup(common::table_id_t tableID, catalog::RelGroupCatalogEntry* tableSchema, + catalog::Catalog* catalog, transaction::Transaction* transaction); + void createRdfGraph(common::table_id_t tableID, catalog::RDFGraphCatalogEntry* tableSchema, + catalog::Catalog* catalog, transaction::Transaction* transaction); private: std::unique_ptr dataFH; diff --git a/src/include/storage/storage_structure/disk_array.h b/src/include/storage/storage_structure/disk_array.h index 8b32e8b48c2..5770f89bb1c 100644 --- a/src/include/storage/storage_structure/disk_array.h +++ b/src/include/storage/storage_structure/disk_array.h @@ -33,6 +33,8 @@ struct DiskArrayHeader { void readFromFile(FileHandle& fileHandle, uint64_t headerPageIdx); + bool operator==(const DiskArrayHeader& other) const = default; + // We do not need to store numElementsPerPageLog2, elementPageOffsetMask, and numArrayPages or // save them on disk as they are functions of elementSize and numElements but we // nonetheless store them (and save them to disk) for simplicity. @@ -100,8 +102,8 @@ struct PIPUpdates { class BaseDiskArrayInternal { public: // Used by copiers. - BaseDiskArrayInternal( - FileHandle& fileHandle, common::page_idx_t headerPageIdx, uint64_t elementSize); + BaseDiskArrayInternal(FileHandle& fileHandle, common::page_idx_t headerPageIdx, + uint64_t elementSize); // Used when loading from file BaseDiskArrayInternal(FileHandle& fileHandle, DBFileID dbFileID, common::page_idx_t headerPageIdx, BufferManager* bufferManager, WAL* wal, @@ -133,12 +135,18 @@ class BaseDiskArrayInternal { checkpointOrRollbackInMemoryIfNecessaryNoLock(false /* is rollback */); } + virtual void prepareCommit(); + protected: uint64_t pushBackNoLock(std::span val); - uint64_t getNumElementsNoLock(transaction::TransactionType trxType); + inline uint64_t getNumElementsNoLock(transaction::TransactionType trxType) { + return getDiskArrayHeader(trxType).numElements; + } - uint64_t getNumAPsNoLock(transaction::TransactionType trxType); + inline uint64_t getNumAPsNoLock(transaction::TransactionType trxType) { + return getDiskArrayHeader(trxType).numAPs; + } void setNextPIPPageIDxOfPIPNoLock(DiskArrayHeader* updatedDiskArrayHeader, uint64_t pipIdxOfPreviousPIP, common::page_idx_t nextPIPPageIdx); @@ -169,8 +177,13 @@ class BaseDiskArrayInternal { bool checkOutOfBoundAccess(transaction::TransactionType trxType, uint64_t idx); bool hasPIPUpdatesNoLock(uint64_t pipIdx); - uint64_t readUInt64HeaderFieldNoLock( - transaction::TransactionType trxType, std::function readOp); + inline const DiskArrayHeader& getDiskArrayHeader(transaction::TransactionType trxType) { + if (trxType == transaction::TransactionType::READ_ONLY) { + return header; + } else { + return headerForWriteTrx; + } + } // Returns the apPageIdx of the AP with idx apIdx and a bool indicating whether the apPageIdx is // a newly inserted page. @@ -184,6 +197,7 @@ class BaseDiskArrayInternal { FileHandle& fileHandle; DBFileID dbFileID; common::page_idx_t headerPageIdx; + DiskArrayHeader headerForWriteTrx; bool hasTransactionalUpdates; BufferManager* bufferManager; WAL* wal; @@ -234,6 +248,7 @@ class BaseDiskArray { inline void checkpointInMemoryIfNecessary() { diskArray.checkpointInMemoryIfNecessary(); } inline void rollbackInMemoryIfNecessary() { diskArray.rollbackInMemoryIfNecessary(); } + inline void prepareCommit() { diskArray.prepareCommit(); } private: BaseDiskArrayInternal diskArray; @@ -241,8 +256,8 @@ class BaseDiskArray { class BaseInMemDiskArray : public BaseDiskArrayInternal { protected: - BaseInMemDiskArray( - FileHandle& fileHandle, common::page_idx_t headerPageIdx, uint64_t elementSize); + BaseInMemDiskArray(FileHandle& fileHandle, common::page_idx_t headerPageIdx, + uint64_t elementSize); BaseInMemDiskArray(FileHandle& fileHandle, DBFileID dbFileID, common::page_idx_t headerPageIdx, BufferManager* bufferManager, WAL* wal, transaction::Transaction* transaction); @@ -271,77 +286,20 @@ class BaseInMemDiskArray : public BaseDiskArrayInternal { std::vector> inMemArrayPages; }; -/** - * Stores an array of type U's page by page in memory, using OS memory and not the buffer manager. - * Designed currently to be used by lists headers and metadata, where we want to avoid using - * pins/unpins when accessing data through the buffer manager. - */ -class InMemDiskArrayInternal : public BaseInMemDiskArray { -public: - InMemDiskArrayInternal(FileHandle& fileHandle, DBFileID dbFileID, - common::page_idx_t headerPageIdx, BufferManager* bufferManager, WAL* wal, - transaction::Transaction* transaction); - - static inline common::page_idx_t addDAHPageToFile( - BMFileHandle& fileHandle, BufferManager* bufferManager, WAL* wal, size_t size) { - DiskArrayHeader daHeader(size); - return DBFileUtils::insertNewPage(fileHandle, DBFileID{DBFileType::METADATA}, - *bufferManager, *wal, - [&](uint8_t* frame) -> void { memcpy(frame, &daHeader, sizeof(DiskArrayHeader)); }); - } - - inline void checkpointInMemoryIfNecessary() override { - std::unique_lock xlock{this->diskArraySharedMtx}; - checkpointOrRollbackInMemoryIfNecessaryNoLock(true /* is checkpoint */); - } - inline void rollbackInMemoryIfNecessary() override { - std::unique_lock xlock{this->diskArraySharedMtx}; - checkpointOrRollbackInMemoryIfNecessaryNoLock(false /* is rollback */); - } - -private: - void checkpointOrRollbackInMemoryIfNecessaryNoLock(bool isCheckpoint) override; -}; - template -class InMemDiskArray { +class InMemDiskArray : public BaseDiskArray { public: + // Used when loading from file InMemDiskArray(FileHandle& fileHandle, DBFileID dbFileID, common::page_idx_t headerPageIdx, BufferManager* bufferManager, WAL* wal, transaction::Transaction* transaction) - : diskArray(fileHandle, dbFileID, headerPageIdx, bufferManager, wal, transaction) {} - - inline U& operator[](uint64_t idx) { return *(U*)diskArray[idx]; } - - static inline common::page_idx_t addDAHPageToFile( - BMFileHandle& fileHandle, BufferManager* bufferManager, WAL* wal) { - return InMemDiskArrayInternal::addDAHPageToFile(fileHandle, bufferManager, wal, sizeof(U)); - } - - // Note: This function is to be used only by the WRITE trx. - inline void update(uint64_t idx, U val) { diskArray.update(idx, getSpan(val)); } - - inline U get(uint64_t idx, transaction::TransactionType trxType) { - U val; - diskArray.get(idx, trxType, getSpan(val)); - return val; - } - - // Note: Currently, this function doesn't support shrinking the size of the array. - inline uint64_t resize(uint64_t newNumElements) { - U defaultVal; - return diskArray.resize(newNumElements, getSpan(defaultVal)); - } - - inline uint64_t getNumElements( - transaction::TransactionType trxType = transaction::TransactionType::READ_ONLY) { - return diskArray.getNumElements(trxType); + : BaseDiskArray(fileHandle, dbFileID, headerPageIdx, bufferManager, wal, transaction) {} + static inline common::page_idx_t addDAHPageToFile(BMFileHandle& fileHandle, + BufferManager* bufferManager, WAL* wal) { + DiskArrayHeader daHeader(sizeof(U)); + return DBFileUtils::insertNewPage(fileHandle, DBFileID{DBFileType::METADATA}, + *bufferManager, *wal, + [&](uint8_t* frame) -> void { memcpy(frame, &daHeader, sizeof(DiskArrayHeader)); }); } - - inline void checkpointInMemoryIfNecessary() { diskArray.checkpointInMemoryIfNecessary(); } - inline void rollbackInMemoryIfNecessary() { diskArray.rollbackInMemoryIfNecessary(); } - -private: - InMemDiskArrayInternal diskArray; }; class InMemDiskArrayBuilderInternal : public BaseInMemDiskArray { diff --git a/src/include/storage/storage_structure/disk_overflow_file.h b/src/include/storage/storage_structure/disk_overflow_file.h deleted file mode 100644 index 39e1be23de2..00000000000 --- a/src/include/storage/storage_structure/disk_overflow_file.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include - -#include "common/constants.h" -#include "common/types/types.h" -#include "storage/buffer_manager/buffer_manager.h" -#include "storage/storage_utils.h" -#include "storage/wal/wal.h" -#include "transaction/transaction.h" - -namespace kuzu { -namespace storage { - -class DiskOverflowFile { - -public: - DiskOverflowFile(const DBFileIDAndName& dbFileIdAndName, BufferManager* bufferManager, WAL* wal, - bool readOnly, common::VirtualFileSystem* vfs) - : bufferManager{bufferManager}, wal{wal}, loggedNewOverflowFileNextBytePosRecord{false} { - auto overflowFileIDAndName = constructDBFileIDAndName(dbFileIdAndName); - dbFileID = overflowFileIDAndName.dbFileID; - fileHandle = bufferManager->getBMFileHandle(overflowFileIDAndName.fName, - readOnly ? FileHandle::O_PERSISTENT_FILE_READ_ONLY : - FileHandle::O_PERSISTENT_FILE_NO_CREATE, - BMFileHandle::FileVersionedType::VERSIONED_FILE, vfs); - nextPosToWriteTo.elemPosInPage = 0; - nextPosToWriteTo.pageIdx = fileHandle->getNumPages(); - } - - std::string readString(transaction::TransactionType trxType, const common::ku_string_t& str); - - common::ku_string_t writeString(std::string_view rawString); - inline common::ku_string_t writeString(const char* rawString) { - return writeString(std::string_view(rawString)); - } - - inline BMFileHandle* getFileHandle() { return fileHandle.get(); } - inline void resetNextBytePosToWriteTo(uint64_t nextBytePosToWriteTo_) { - nextPosToWriteTo.elemPosInPage = - nextBytePosToWriteTo_ % common::BufferPoolConstants::PAGE_4KB_SIZE; - nextPosToWriteTo.pageIdx = - nextBytePosToWriteTo_ / common::BufferPoolConstants::PAGE_4KB_SIZE; - } - void resetLoggedNewOverflowFileNextBytePosRecord() { - loggedNewOverflowFileNextBytePosRecord = false; - } - -private: - static inline DBFileIDAndName constructDBFileIDAndName( - const DBFileIDAndName& dbFileIdAndNameForMainDBFile) { - DBFileIDAndName copy = dbFileIdAndNameForMainDBFile; - copy.dbFileID.isOverflow = true; - copy.fName = StorageUtils::getOverflowFileName(dbFileIdAndNameForMainDBFile.fName); - return copy; - } - -private: - bool addNewPageIfNecessaryWithoutLock(uint32_t numBytesToAppend); - void setStringOverflowWithoutLock( - const char* inMemSrcStr, uint64_t len, common::ku_string_t& diskDstString); - void logNewOverflowFileNextBytePosRecordIfNecessaryWithoutLock(); - -private: - static const common::page_idx_t END_OF_PAGE = - common::BufferPoolConstants::PAGE_4KB_SIZE - sizeof(common::page_idx_t); - DBFileID dbFileID; - std::unique_ptr fileHandle; - BufferManager* bufferManager; - WAL* wal; - // This is the index of the last free byte to which we can write. - PageCursor nextPosToWriteTo; - // Mtx is obtained if multiple threads want to write to the overflows to coordinate them. - // We cannot directly coordinate using the locks of the pages in the overflow fileHandle. - // This is because multiple threads will be trying to edit the nextBytePosToWriteTo. - // For simplicity, currently only a single thread can update overflow pages at ant time. See the - // note in writeStringOverflowAndUpdateOverflowPtr for more details. - std::mutex mtx; - bool loggedNewOverflowFileNextBytePosRecord; -}; - -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/storage_structure/in_mem_file.h b/src/include/storage/storage_structure/in_mem_file.h deleted file mode 100644 index e6945c1bfc1..00000000000 --- a/src/include/storage/storage_structure/in_mem_file.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -#include "common/constants.h" -#include "common/types/ku_string.h" -#include "common/types/types.h" -#include "storage/storage_structure/in_mem_page.h" -#include "storage/storage_utils.h" - -namespace kuzu { -namespace common { -class VirtualFileSystem; -} - -namespace storage { - -// InMemFile holds a collection of in-memory page in the memory. -class InMemFile { -public: - explicit InMemFile( - std::shared_ptr fileInfo, std::atomic& pageCounter); - - void addANewPage(); - - inline InMemPage* getPage(common::page_idx_t pageIdx) const { return pages.at(pageIdx).get(); } - - // This function appends a string if the length of the string is larger than SHORT_STR_LENGTH, - // otherwise, construct the ku_string for the rawString and return it. - // Note that this function is not thread safe. - void appendString(std::string_view rawString, common::ku_string_t& result); - inline void appendString(const char* rawString, common::ku_string_t& result) { - appendString(std::string_view(rawString), result); - } - - std::string readString(common::ku_string_t* strInInMemOvfFile) const; - bool equals(std::string_view keyToLookup, const common::ku_string_t& keyInEntry) const; - - void flush(); - - inline common::page_idx_t getNextPageIndex(common::page_idx_t currentPageIndex) const { - return *(common::page_idx_t*)(getPage(currentPageIndex)->data + END_OF_PAGE); - } - -private: - static const uint64_t END_OF_PAGE = - common::BufferPoolConstants::PAGE_4KB_SIZE - sizeof(common::page_idx_t); - std::shared_ptr fileInfo; - std::unordered_map> pages; - PageCursor nextPosToAppend; - std::atomic& pageCounter; -}; - -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/storage_structure/overflow_file.h b/src/include/storage/storage_structure/overflow_file.h new file mode 100644 index 00000000000..10c9666a014 --- /dev/null +++ b/src/include/storage/storage_structure/overflow_file.h @@ -0,0 +1,149 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include "common/cast.h" +#include "common/constants.h" +#include "common/types/types.h" +#include "storage/buffer_manager/bm_file_handle.h" +#include "storage/buffer_manager/buffer_manager.h" +#include "storage/file_handle.h" +#include "storage/index/hash_index_utils.h" +#include "storage/storage_structure/in_mem_page.h" +#include "storage/storage_utils.h" +#include "storage/wal/wal.h" +#include "storage/wal/wal_record.h" +#include "transaction/transaction.h" + +namespace kuzu { +namespace storage { + +class OverflowFile; + +class OverflowFileHandle { + +public: + OverflowFileHandle(OverflowFile& overflowFile, PageCursor& nextPosToWriteTo) + : nextPosToWriteTo(nextPosToWriteTo), overflowFile{overflowFile} {} + // The OverflowFile stores the handles and returns pointers to them. + // Moving the handle would invalidate those pointers + OverflowFileHandle(OverflowFileHandle&& other) = delete; + + std::string readString(transaction::TransactionType trxType, const common::ku_string_t& str); + + bool equals(transaction::TransactionType trxType, std::string_view keyToLookup, + const common::ku_string_t& keyInEntry) const; + + common::ku_string_t writeString(std::string_view rawString); + inline common::ku_string_t writeString(const char* rawString) { + return writeString(std::string_view(rawString)); + } + + void prepareCommit(); + inline void checkpointInMemory() { pageWriteCache.clear(); } + inline void rollbackInMemory(PageCursor nextPosToWriteTo_) { + pageWriteCache.clear(); + this->nextPosToWriteTo = nextPosToWriteTo_; + } + +private: + uint8_t* addANewPage(); + void setStringOverflow(const char* inMemSrcStr, uint64_t len, + common::ku_string_t& diskDstString); + + inline void read(transaction::TransactionType trxType, common::page_idx_t pageIdx, + const std::function& func) const; + +private: + static const common::page_idx_t END_OF_PAGE = + common::BufferPoolConstants::PAGE_4KB_SIZE - sizeof(common::page_idx_t); + // This is the index of the last free byte to which we can write. + PageCursor& nextPosToWriteTo; + OverflowFile& overflowFile; + // Cached pages which have been written in the current transaction + std::unordered_map> pageWriteCache; +}; + +// Stores the current state of the overflow file +// The number of pages in use are stored here so that we can write new pages directly +// to the overflow file, and in the case of an interruption and rollback the header will +// still record the correct place in the file to allocate new pages +struct StringOverflowFileHeader { + common::page_idx_t pages; + PageCursor cursors[NUM_HASH_INDEXES]; + + // pages starts at one to reserve space for this header + StringOverflowFileHeader() : pages{1} { + std::fill(cursors, cursors + NUM_HASH_INDEXES, PageCursor()); + } +}; + +class OverflowFile { + friend class OverflowFileHandle; + +public: + // For reading an existing overflow file + OverflowFile(const DBFileIDAndName& dbFileIdAndName, BufferManager* bufferManager, WAL* wal, + bool readOnly, common::VirtualFileSystem* vfs); + + // For creating an overflow file from scratch + OverflowFile(const std::string& fName, common::VirtualFileSystem* vfs) + : numPagesOnDisk{0}, fileHandle{std::make_unique(fName, + FileHandle::O_PERSISTENT_FILE_CREATE_NOT_EXISTS, vfs)}, + bufferManager{nullptr}, wal{nullptr}, pageCounter{0}, headerChanged{true} { + // Reserve a page for the header + getNewPageIdx(); + } + + // Handles contain a reference to the overflow file + OverflowFile(OverflowFile&& other) = delete; + + void rollbackInMemory(); + void prepareCommit(); + void checkpointInMemory(); + + inline OverflowFileHandle* addHandle() { + KU_ASSERT(handles.size() < NUM_HASH_INDEXES); + handles.emplace_back( + std::make_unique(*this, header.cursors[handles.size()])); + return handles.back().get(); + } + + inline BMFileHandle* getBMFileHandle() const { + return common::ku_dynamic_cast(fileHandle.get()); + } + +private: + void readFromDisk(transaction::TransactionType trxType, common::page_idx_t pageIdx, + const std::function& func) const; + + // Writes new pages directly to the file and existing pages to the WAL + void writePageToDisk(common::page_idx_t pageIdx, uint8_t* data) const; + + inline common::page_idx_t getNewPageIdx() { + // If this isn't the first call reserving the page header, then the header flag must be set + // prior to this + KU_ASSERT(pageCounter == HEADER_PAGE_IDX || headerChanged); + return pageCounter.fetch_add(1); + } + +private: + static const uint64_t HEADER_PAGE_IDX = 0; + + std::vector> handles; + StringOverflowFileHeader header; + common::page_idx_t numPagesOnDisk; + DBFileID dbFileID; + std::unique_ptr fileHandle; + BufferManager* bufferManager; + WAL* wal; + std::atomic pageCounter; + std::atomic headerChanged; +}; +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/storage_utils.h b/src/include/storage/storage_utils.h index 7d55457cf6b..5fe68a7a6fe 100644 --- a/src/include/storage/storage_utils.h +++ b/src/include/storage/storage_utils.h @@ -65,13 +65,12 @@ class StorageUtils { enum class ColumnType { DEFAULT = 0, INDEX = 1, // This is used for index columns in STRING columns. - OFFSET = 2, // This is used for offset columns in VAR_LIST and STRING columns. - DATA = 3, // This is used for data columns in VAR_LIST and STRING columns. + OFFSET = 2, // This is used for offset columns in LIST and STRING columns. + DATA = 3, // This is used for data columns in LIST and STRING columns. CSR_OFFSET = 4, CSR_LENGTH = 5, - ADJ = 6, - STRUCT_CHILD = 7, - NULL_MASK = 8, + STRUCT_CHILD = 6, + NULL_MASK = 7, }; // TODO: Constrain T1 and T2 to numerics. @@ -80,8 +79,8 @@ class StorageUtils { return std::ceil((double)v1 / (double)v2); } - static std::string getColumnName( - const std::string& propertyName, ColumnType type, const std::string& prefix); + static std::string getColumnName(const std::string& propertyName, ColumnType type, + const std::string& prefix); static inline common::offset_t getStartOffsetOfNodeGroup( common::node_group_idx_t nodeGroupIdx) { @@ -101,42 +100,42 @@ class StorageUtils { const std::string& directory, const common::table_id_t& tableID, common::FileVersionType dbFileType); - static inline std::string getDataFName( - common::VirtualFileSystem* vfs, const std::string& directory) { + static inline std::string getDataFName(common::VirtualFileSystem* vfs, + const std::string& directory) { return vfs->joinPath(directory, common::StorageConstants::DATA_FILE_NAME); } - static inline std::string getMetadataFName( - common::VirtualFileSystem* vfs, const std::string& directory) { + static inline std::string getMetadataFName(common::VirtualFileSystem* vfs, + const std::string& directory) { return vfs->joinPath(directory, common::StorageConstants::METADATA_FILE_NAME); } - static inline DBFileIDAndName getNodeIndexIDAndFName( - common::VirtualFileSystem* vfs, const std::string& directory, common::table_id_t tableID) { + static inline DBFileIDAndName getNodeIndexIDAndFName(common::VirtualFileSystem* vfs, + const std::string& directory, common::table_id_t tableID) { auto fName = getNodeIndexFName(vfs, directory, tableID, common::FileVersionType::ORIGINAL); return {DBFileID::newPKIndexFileID(tableID), fName}; } static inline std::string getOverflowFileName(const std::string& fName) { - return appendSuffixOrInsertBeforeWALSuffix( - fName, common::StorageConstants::OVERFLOW_FILE_SUFFIX); + return appendSuffixOrInsertBeforeWALSuffix(fName, + common::StorageConstants::OVERFLOW_FILE_SUFFIX); } static inline std::string getNodesStatisticsAndDeletedIDsFilePath( common::VirtualFileSystem* vfs, const std::string& directory, common::FileVersionType dbFileType) { - return vfs->joinPath( - directory, dbFileType == common::FileVersionType::ORIGINAL ? - common::StorageConstants::NODES_STATISTICS_AND_DELETED_IDS_FILE_NAME : - common::StorageConstants::NODES_STATISTICS_FILE_NAME_FOR_WAL); + return vfs->joinPath(directory, + dbFileType == common::FileVersionType::ORIGINAL ? + common::StorageConstants::NODES_STATISTICS_AND_DELETED_IDS_FILE_NAME : + common::StorageConstants::NODES_STATISTICS_FILE_NAME_FOR_WAL); } static inline std::string getRelsStatisticsFilePath(common::VirtualFileSystem* vfs, const std::string& directory, common::FileVersionType dbFileType) { - return vfs->joinPath( - directory, dbFileType == common::FileVersionType::ORIGINAL ? - common::StorageConstants::RELS_METADATA_FILE_NAME : - common::StorageConstants::RELS_METADATA_FILE_NAME_FOR_WAL); + return vfs->joinPath(directory, + dbFileType == common::FileVersionType::ORIGINAL ? + common::StorageConstants::RELS_METADATA_FILE_NAME : + common::StorageConstants::RELS_METADATA_FILE_NAME_FOR_WAL); } static inline std::string getCatalogFilePath(common::VirtualFileSystem* vfs, @@ -146,8 +145,8 @@ class StorageUtils { common::StorageConstants::CATALOG_FILE_NAME_FOR_WAL); } - static inline std::string getLockFilePath( - common::VirtualFileSystem* vfs, const std::string& directory) { + static inline std::string getLockFilePath(common::VirtualFileSystem* vfs, + const std::string& directory) { return vfs->joinPath(directory, common::StorageConstants::LOCK_FILE_NAME); } @@ -165,8 +164,8 @@ class StorageUtils { } } - static inline std::string appendWALFileSuffixIfNecessary( - const std::string& fileName, common::FileVersionType fileVersionType) { + static inline std::string appendWALFileSuffixIfNecessary(const std::string& fileName, + common::FileVersionType fileVersionType) { return fileVersionType == common::FileVersionType::WAL_VERSION ? appendWALFileSuffix(fileName) : fileName; @@ -177,15 +176,15 @@ class StorageUtils { return fileName + common::StorageConstants::WAL_FILE_SUFFIX; } - static std::unique_ptr getFileInfoForReadWrite( - const std::string& directory, DBFileID dbFileID, common::VirtualFileSystem* vfs); + static std::unique_ptr getFileInfoForReadWrite(const std::string& directory, + DBFileID dbFileID, common::VirtualFileSystem* vfs); static uint32_t getDataTypeSize(const common::LogicalType& type); static uint32_t getDataTypeSize(common::PhysicalTypeID type); private: - static std::string appendSuffixOrInsertBeforeWALSuffix( - const std::string& fileName, const std::string& suffix); + static std::string appendSuffixOrInsertBeforeWALSuffix(const std::string& fileName, + const std::string& suffix); }; } // namespace storage diff --git a/src/include/storage/storage_info.h b/src/include/storage/storage_version_info.h similarity index 55% rename from src/include/storage/storage_info.h rename to src/include/storage/storage_version_info.h index 59c1aa12d33..c6b2ec6cf45 100644 --- a/src/include/storage/storage_info.h +++ b/src/include/storage/storage_version_info.h @@ -11,10 +11,10 @@ using storage_version_t = uint64_t; struct StorageVersionInfo { static std::unordered_map getStorageVersionInfo() { - return {{"0.3.1", 26}, {"0.3.0", 26}, {"0.2.1", 25}, {"0.2.0", 25}, {"0.1.0", 24}, - {"0.0.12.3", 24}, {"0.0.12.2", 24}, {"0.0.12.1", 24}, {"0.0.12", 23}, {"0.0.11", 23}, - {"0.0.10", 23}, {"0.0.9", 23}, {"0.0.8", 17}, {"0.0.7", 15}, {"0.0.6", 9}, {"0.0.5", 8}, - {"0.0.4", 7}, {"0.0.3", 1}}; + return {{"0.3.2", 26}, {"0.3.1", 26}, {"0.3.0", 26}, {"0.2.1", 25}, {"0.2.0", 25}, + {"0.1.0", 24}, {"0.0.12.3", 24}, {"0.0.12.2", 24}, {"0.0.12.1", 24}, {"0.0.12", 23}, + {"0.0.11", 23}, {"0.0.10", 23}, {"0.0.9", 23}, {"0.0.8", 17}, {"0.0.7", 15}, + {"0.0.6", 9}, {"0.0.5", 8}, {"0.0.4", 7}, {"0.0.3", 1}}; } static storage_version_t getStorageVersion(); diff --git a/src/include/storage/store/chunked_node_group.h b/src/include/storage/store/chunked_node_group.h new file mode 100644 index 00000000000..3ce4e8c6fcc --- /dev/null +++ b/src/include/storage/store/chunked_node_group.h @@ -0,0 +1,115 @@ +#pragma once + +#include "common/column_data_format.h" +#include "common/copy_constructors.h" +#include "storage/store/column_chunk.h" + +namespace kuzu { +namespace storage { + +class Column; + +class ChunkedNodeGroup { +public: + explicit ChunkedNodeGroup(std::vector> chunks) + : chunks{std::move(chunks)} {} + ChunkedNodeGroup(const std::vector& columnTypes, bool enableCompression, + uint64_t capacity); + ChunkedNodeGroup(const std::vector>& columns, bool enableCompression); + DELETE_COPY_DEFAULT_MOVE(ChunkedNodeGroup); + virtual ~ChunkedNodeGroup() = default; + + inline uint64_t getNodeGroupIdx() const { return nodeGroupIdx; } + inline common::vector_idx_t getNumColumns() const { return chunks.size(); } + inline const ColumnChunk& getColumnChunk(common::column_id_t columnID) const { + KU_ASSERT(columnID < chunks.size()); + return *chunks[columnID]; + } + inline ColumnChunk& getColumnChunkUnsafe(common::column_id_t columnID) { + KU_ASSERT(columnID < chunks.size()); + return *chunks[columnID]; + } + inline std::vector>& getColumnChunksUnsafe() { return chunks; } + inline bool isFull() const { return numRows == common::StorageConstants::NODE_GROUP_SIZE; } + + void resetToEmpty(); + void setAllNull(); + void setNumRows(common::offset_t numRows); + inline common::row_idx_t getNumRows() const { return numRows; } + void resizeChunks(uint64_t newSize); + + uint64_t append(const std::vector& columnVectors, + common::SelectionVector& selVector, uint64_t numValuesToAppend); + common::offset_t append(ChunkedNodeGroup* other, common::offset_t offsetInOtherNodeGroup); + void write(const std::vector>& data, + common::column_id_t offsetColumnID); + void write(const ChunkedNodeGroup& data, common::column_id_t offsetColumnID); + + void finalize(uint64_t nodeGroupIdx_); + + virtual inline void writeToColumnChunk(common::vector_idx_t chunkIdx, + common::vector_idx_t vectorIdx, const std::vector>& data, + ColumnChunk& offsetChunk) { + chunks[chunkIdx]->write(data[vectorIdx].get(), &offsetChunk, common::RelMultiplicity::ONE); + } + +protected: + std::vector> chunks; + +private: + uint64_t nodeGroupIdx; + common::row_idx_t numRows; +}; + +struct ChunkedCSRHeader { + std::unique_ptr offset; + std::unique_ptr length; + + ChunkedCSRHeader() {} + explicit ChunkedCSRHeader(bool enableCompression, + uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE); + DELETE_COPY_DEFAULT_MOVE(ChunkedCSRHeader); + + common::offset_t getStartCSROffset(common::offset_t nodeOffset) const; + common::offset_t getEndCSROffset(common::offset_t nodeOffset) const; + common::length_t getCSRLength(common::offset_t nodeOffset) const; + + bool sanityCheck() const; + void copyFrom(const ChunkedCSRHeader& other) const; + void fillDefaultValues(common::offset_t newNumValues) const; + inline void setNumValues(common::offset_t numValues) const { + offset->setNumValues(numValues); + length->setNumValues(numValues); + } +}; + +class ChunkedCSRNodeGroup : public ChunkedNodeGroup { +public: + ChunkedCSRNodeGroup(const std::vector& columnTypes, + bool enableCompression); + DELETE_COPY_DEFAULT_MOVE(ChunkedCSRNodeGroup); + + ChunkedCSRHeader& getCSRHeader() { return csrHeader; } + const ChunkedCSRHeader& getCSRHeader() const { return csrHeader; } + + inline void writeToColumnChunk(common::vector_idx_t chunkIdx, common::vector_idx_t vectorIdx, + const std::vector>& data, ColumnChunk& offsetChunk) override { + chunks[chunkIdx]->write(data[vectorIdx].get(), &offsetChunk, common::RelMultiplicity::MANY); + } + +private: + ChunkedCSRHeader csrHeader; +}; + +struct NodeGroupFactory { + static inline std::unique_ptr createNodeGroup( + common::ColumnDataFormat dataFormat, const std::vector& columnTypes, + bool enableCompression, uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE) { + return dataFormat == common::ColumnDataFormat::REGULAR ? + std::make_unique(columnTypes, enableCompression, capacity) : + std::make_unique(columnTypes, enableCompression); + } +}; + +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/store/chunked_node_group_collection.h b/src/include/storage/store/chunked_node_group_collection.h new file mode 100644 index 00000000000..6a2a8180b29 --- /dev/null +++ b/src/include/storage/store/chunked_node_group_collection.h @@ -0,0 +1,48 @@ +#pragma once + +#include "storage/store/chunked_node_group.h" + +namespace kuzu { +namespace storage { + +class ChunkedNodeGroupCollection { +public: + static constexpr uint64_t CHUNK_CAPACITY = 2048; + + explicit ChunkedNodeGroupCollection(std::vector types) + : types{std::move(types)} {} + DELETE_COPY_DEFAULT_MOVE(ChunkedNodeGroupCollection); + + static std::pair getChunkIdxAndOffsetInChunk( + common::row_idx_t rowIdx) { + return std::make_pair(rowIdx / CHUNK_CAPACITY, rowIdx % CHUNK_CAPACITY); + } + + inline const std::vector>& getChunkedGroups() const { + return chunkedGroups; + } + inline const ChunkedNodeGroup* getChunkedGroup(common::node_group_idx_t groupIdx) const { + KU_ASSERT(groupIdx < chunkedGroups.size()); + return chunkedGroups[groupIdx].get(); + } + inline ChunkedNodeGroup* getChunkedGroupUnsafe(common::node_group_idx_t groupIdx) { + KU_ASSERT(groupIdx < chunkedGroups.size()); + return chunkedGroups[groupIdx].get(); + } + + void append(const std::vector& vectors, + const common::SelectionVector& selVector); + + void merge(std::unique_ptr chunkedGroup); + void merge(ChunkedNodeGroupCollection& other); + + inline uint64_t getNumChunkedGroups() const { return chunkedGroups.size(); } + inline void clear() { chunkedGroups.clear(); } + +private: + std::vector types; + std::vector> chunkedGroups; +}; + +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/store/column.h b/src/include/storage/store/column.h index f691db1e477..80b751074e5 100644 --- a/src/include/storage/store/column.h +++ b/src/include/storage/store/column.h @@ -28,11 +28,11 @@ using batch_lookup_func_t = read_values_to_page_func_t; class NullColumn; class StructColumn; -class LocalVectorCollection; class Column { friend class StringColumn; - friend class VarListLocalColumn; + friend class ListLocalColumn; friend class StructColumn; + friend class ListColumn; public: struct ReadState { @@ -63,7 +63,8 @@ class Column { virtual void lookup(transaction::Transaction* transaction, common::ValueVector* nodeIDVector, common::ValueVector* resultVector); - virtual void append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx); + // Append column chunk in a new node group. + virtual void append(ColumnChunk* columnChunk, common::node_group_idx_t nodeGroupIdx); inline common::LogicalType& getDataType() { return dataType; } inline const common::LogicalType& getDataType() const { return dataType; } @@ -74,10 +75,11 @@ class Column { Column* getNullColumn(); + virtual void prepareCommit(); virtual void prepareCommitForChunk(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localColumnChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo, - const offset_set_t& deleteInfo); + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, + const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo); virtual void prepareCommitForChunk(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, common::offset_t startSrcOffset); @@ -88,8 +90,8 @@ class Column { void populateWithDefaultVal(transaction::Transaction* transaction, InMemDiskArray* metadataDA, common::ValueVector* defaultValueVector); - inline ColumnChunkMetadata getMetadata( - common::node_group_idx_t nodeGroupIdx, transaction::TransactionType transaction) const { + inline ColumnChunkMetadata getMetadata(common::node_group_idx_t nodeGroupIdx, + transaction::TransactionType transaction) const { return metadataDA->get(nodeGroupIdx, transaction); } inline InMemDiskArray* getMetadataDA() const { return metadataDA.get(); } @@ -107,13 +109,14 @@ class Column { ColumnChunk* data, common::offset_t dataOffset, common::length_t numValues); // Append values to the end of the node group, resizing it if necessary - common::offset_t appendValues( - common::node_group_idx_t nodeGroupIdx, const uint8_t* data, common::offset_t numValues); + common::offset_t appendValues(common::node_group_idx_t nodeGroupIdx, const uint8_t* data, + common::offset_t numValues); - ReadState getReadState( - transaction::TransactionType transactionType, common::node_group_idx_t nodeGroupIdx) const; + ReadState getReadState(transaction::TransactionType transactionType, + common::node_group_idx_t nodeGroupIdx) const; - static void applyLocalChunkToColumnChunk(LocalVectorCollection* localChunk, + virtual std::unique_ptr getEmptyChunkForCommit(uint64_t capacity); + static void applyLocalChunkToColumnChunk(const ChunkCollection& localChunks, ColumnChunk* columnChunk, const offset_to_row_idx_t& info); protected: @@ -140,15 +143,13 @@ class Column { common::offset_t dataOffset = 0, common::offset_t numValues = 1); // Produces a page cursor for the offset relative to the given node group - PageCursor getPageCursorForOffsetInGroup( - common::offset_t offsetInChunk, const ReadState& state); + PageCursor getPageCursorForOffsetInGroup(common::offset_t offsetInChunk, + const ReadState& state); // Produces a page cursor for the absolute node offset PageCursor getPageCursorForOffset(transaction::TransactionType transactionType, common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInChunk); - void updatePageWithCursor( - PageCursor cursor, const std::function& writeOp); - - virtual std::unique_ptr getEmptyChunkForCommit(uint64_t capacity); + void updatePageWithCursor(PageCursor cursor, + const std::function& writeOp); inline common::offset_t getMaxOffset(const std::vector& offsets) { common::offset_t maxOffset = 0u; @@ -158,27 +159,31 @@ class Column { return maxOffset; } + static ChunkCollection getNullChunkCollection(const ChunkCollection& chunkCollection); + private: - bool isInsertionsOutOfPagesCapacity( - const ColumnChunkMetadata& metadata, const offset_to_row_idx_t& insertInfo); - bool isMaxOffsetOutOfPagesCapacity( - const ColumnChunkMetadata& metadata, common::offset_t maxOffset); - bool checkUpdateInPlace(const ColumnChunkMetadata& metadata, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo); + bool isInsertionsOutOfPagesCapacity(const ColumnChunkMetadata& metadata, + const offset_to_row_idx_t& insertInfo); + bool isMaxOffsetOutOfPagesCapacity(const ColumnChunkMetadata& metadata, + common::offset_t maxOffset); + bool checkUpdateInPlace(const ColumnChunkMetadata& metadata, const ChunkCollection& localChunks, + const offset_to_row_idx_t& writeInfo); virtual bool canCommitInPlace(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo); + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, + const offset_to_row_idx_t& updateInfo); virtual bool canCommitInPlace(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, common::offset_t srcOffset); virtual void commitLocalChunkInPlace(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo, - const offset_set_t& deleteInfo); - virtual void commitLocalChunkOutOfPlace(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - bool isNewNodeGroup, const offset_to_row_idx_t& insertInfo, + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo); + virtual void commitLocalChunkOutOfPlace(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, bool isNewNodeGroup, + const ChunkCollection& localInsertChunks, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo, + const offset_set_t& deleteInfo); virtual void commitColumnChunkInPlace(common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, common::offset_t srcOffset); @@ -188,7 +193,7 @@ class Column { common::offset_t srcOffset); void applyLocalChunkToColumn(common::node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& info); + const ChunkCollection& localChunks, const offset_to_row_idx_t& info); // check if val is in range [start, end) static inline bool isInRange(uint64_t val, uint64_t start, uint64_t end) { @@ -199,8 +204,8 @@ class Column { std::string name; DBFileID dbFileID; common::LogicalType dataType; - // TODO(bmwinger): Remove. Only used by var_list_column_chunk for something which should be - // rewritten + // TODO(bmwinger): Remove. Only used by StorageDriver, which should be rewritten to not use this + // field. uint32_t numBytesPerFixedSizedValue; BMFileHandle* dataFH; BMFileHandle* metadataFH; @@ -221,7 +226,7 @@ class InternalIDColumn : public Column { public: InternalIDColumn(std::string name, const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, - transaction::Transaction* transaction, RWPropertyStats stats); + transaction::Transaction* transaction, RWPropertyStats stats, bool enableCompression); inline void scan(transaction::Transaction* transaction, common::ValueVector* nodeIDVector, common::ValueVector* resultVector) override { @@ -243,7 +248,7 @@ class InternalIDColumn : public Column { populateCommonTableID(resultVector); } - // TODO(Guodong): Should figure out a better way to set tableID, and remove this function. + // TODO(Guodong): This function should be removed through rewritting INTERNAL_ID as STRUCT. inline void setCommonTableID(common::table_id_t tableID) { commonTableID = tableID; } private: diff --git a/src/include/storage/store/column_chunk.h b/src/include/storage/store/column_chunk.h index 14070e1bb72..19370792dbd 100644 --- a/src/include/storage/store/column_chunk.h +++ b/src/include/storage/store/column_chunk.h @@ -3,6 +3,8 @@ #include #include "common/constants.h" +#include "common/data_chunk/sel_vector.h" +#include "common/enums/rel_multiplicity.h" #include "common/types/types.h" #include "common/vector/value_vector.h" #include "storage/buffer_manager/bm_file_handle.h" @@ -30,7 +32,7 @@ struct ColumnChunkMetadata { class ColumnChunk { public: friend struct ColumnChunkFactory; - friend struct VarListDataColumnChunk; + friend struct ListDataColumnChunk; // ColumnChunks must be initialized after construction, so this constructor should only be used // through the ColumnChunkFactory @@ -46,6 +48,7 @@ class ColumnChunk { } inline NullColumnChunk* getNullChunk() { return nullChunk.get(); } + inline const NullColumnChunk& getNullChunk() const { return *nullChunk; } inline common::LogicalType& getDataType() { return dataType; } inline const common::LogicalType& getDataType() const { return dataType; } @@ -54,12 +57,12 @@ class ColumnChunk { // Note that the startPageIdx is not known, so it will always be common::INVALID_PAGE_IDX virtual ColumnChunkMetadata getMetadataToFlush() const; - virtual void append(common::ValueVector* vector); - virtual void append( - ColumnChunk* other, common::offset_t startPosInOtherChunk, uint32_t numValuesToAppend); + virtual void append(common::ValueVector* vector, const common::SelectionVector& selVector); + virtual void append(ColumnChunk* other, common::offset_t startPosInOtherChunk, + uint32_t numValuesToAppend); - ColumnChunkMetadata flushBuffer( - BMFileHandle* dataFH, common::page_idx_t startPageIdx, const ColumnChunkMetadata& metadata); + ColumnChunkMetadata flushBuffer(BMFileHandle* dataFH, common::page_idx_t startPageIdx, + const ColumnChunkMetadata& metadata); static inline common::page_idx_t getNumPagesForBytes(uint64_t numBytes) { return (numBytes + common::BufferPoolConstants::PAGE_4KB_SIZE - 1) / @@ -69,14 +72,18 @@ class ColumnChunk { inline uint64_t getNumBytesPerValue() const { return numBytesPerValue; } inline uint8_t* getData() const { return buffer.get(); } + virtual void lookup(common::offset_t offsetInChunk, common::ValueVector& output, + common::sel_t posInOutputVector) const; + // TODO(Guodong): In general, this is not a good interface. Instead of passing in // `offsetInVector`, we should flatten the vector to pos at `offsetInVector`. virtual void write(common::ValueVector* vector, common::offset_t offsetInVector, common::offset_t offsetInChunk); - virtual void write( - common::ValueVector* vector, common::ValueVector* offsetsInChunk, bool isCSR); + virtual void write(ColumnChunk* chunk, ColumnChunk* offsetsInChunk, + common::RelMultiplicity multiplicity); virtual void write(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy); + // TODO(Guodong): Used in `applyDeletionsToChunk`. Should unify with `write`. virtual void copy(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy); @@ -86,6 +93,7 @@ class ColumnChunk { template void setValue(T val, common::offset_t pos) { + KU_ASSERT(pos < capacity); ((T*)buffer.get())[pos] = val; if (pos >= numValues) { numValues = pos + 1; @@ -98,10 +106,12 @@ class ColumnChunk { inline uint64_t getCapacity() const { return capacity; } inline uint64_t getNumValues() const { return numValues; } - void setNumValues(uint64_t numValues_); + virtual void setNumValues(uint64_t numValues_); virtual bool numValuesSanityCheck() const; bool isCompressionEnabled() const { return enableCompression; } + virtual bool sanityCheck(); + protected: // Initializes the data buffer. Is (and should be) only called in constructor. void initializeBuffer(common::offset_t capacity); @@ -109,10 +119,11 @@ class ColumnChunk { common::offset_t getOffsetInBuffer(common::offset_t pos) const; - virtual void copyVectorToBuffer(common::ValueVector* vector, common::offset_t startPosInChunk); + virtual void copyVectorToBuffer(common::ValueVector* vector, common::offset_t startPosInChunk, + const common::SelectionVector& selVector); private: - uint64_t getBufferSize() const; + uint64_t getBufferSize(uint64_t capacity_) const; protected: common::LogicalType dataType; @@ -122,8 +133,8 @@ class ColumnChunk { std::unique_ptr buffer; std::unique_ptr nullChunk; uint64_t numValues; - std::function + std::function flushBufferFunction; std::function getMetadataFunction; @@ -150,13 +161,17 @@ class BoolColumnChunk : public ColumnChunk { // Booleans are always bitpacked, but this can also enable constant compression enableCompression, hasNullChunk) {} - void append(common::ValueVector* vector) final; + void append(common::ValueVector* vector, const common::SelectionVector& sel) final; void append(ColumnChunk* other, common::offset_t startPosInOtherChunk, uint32_t numValuesToAppend) override; + + void lookup(common::offset_t offsetInChunk, common::ValueVector& output, + common::sel_t posInOutputVector) const override; + void write(common::ValueVector* vector, common::offset_t offsetInVector, common::offset_t offsetInChunk) override; - void write(common::ValueVector* valueVector, common::ValueVector* offsetInChunkVector, - bool isCSR) final; + void write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + common::RelMultiplicity multiplicity) final; void write(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; }; @@ -164,8 +179,8 @@ class BoolColumnChunk : public ColumnChunk { class NullColumnChunk final : public BoolColumnChunk { public: explicit NullColumnChunk(uint64_t capacity, bool enableCompression) - : BoolColumnChunk(capacity, enableCompression, false /*hasNullChunk*/), mayHaveNullValue{ - false} {} + : BoolColumnChunk(capacity, enableCompression, false /*hasNullChunk*/), + mayHaveNullValue{false} {} // Maybe this should be combined with BoolColumnChunk if the only difference is these functions? inline bool isNull(common::offset_t pos) const { return getValue(pos); } void setNull(common::offset_t pos, bool isNull); @@ -187,8 +202,8 @@ class NullColumnChunk final : public BoolColumnChunk { inline void copyFromBuffer(uint64_t* srcBuffer, uint64_t srcOffset, uint64_t dstOffset, uint64_t numBits, bool invert = false) { - if (common::NullMask::copyNullMask( - srcBuffer, srcOffset, (uint64_t*)buffer.get(), dstOffset, numBits, invert)) { + if (common::NullMask::copyNullMask(srcBuffer, srcOffset, (uint64_t*)buffer.get(), dstOffset, + numBits, invert)) { mayHaveNullValue = true; } } @@ -206,11 +221,14 @@ class NullColumnChunk final : public BoolColumnChunk { }; struct ColumnChunkFactory { + // inMemory starts string column chunk dictionaries at zero instead of reserving space for + // values to grow static std::unique_ptr createColumnChunk(common::LogicalType dataType, - bool enableCompression, uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE); + bool enableCompression, uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE, + bool inMemory = false); - static std::unique_ptr createNullColumnChunk( - bool enableCompression, uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE) { + static std::unique_ptr createNullColumnChunk(bool enableCompression, + uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE) { return std::make_unique(capacity, enableCompression); } }; diff --git a/src/include/storage/store/dictionary_chunk.h b/src/include/storage/store/dictionary_chunk.h index 24d59db74cd..42693964747 100644 --- a/src/include/storage/store/dictionary_chunk.h +++ b/src/include/storage/store/dictionary_chunk.h @@ -1,6 +1,5 @@ #pragma once -#include "common/string_utils.h" #include "storage/store/column_chunk.h" namespace kuzu { @@ -12,6 +11,9 @@ class DictionaryChunk { using string_index_t = uint32_t; DictionaryChunk(uint64_t capacity, bool enableCompression); + // A pointer to the dictionary chunk is stored in the StringOps for the indexTable + // and can't be modified easily. Moving would invalidate that pointer + DictionaryChunk(DictionaryChunk&& other) = delete; void resetToEmpty(); @@ -32,9 +34,38 @@ class DictionaryChunk { // of characters stored. std::unique_ptr stringDataChunk; std::unique_ptr offsetChunk; - std::unordered_map> - indexTable; + + struct DictionaryEntry { + string_index_t index; + + std::string_view get(const DictionaryChunk& dict) const { return dict.getString(index); } + }; + + struct StringOps { + explicit StringOps(const DictionaryChunk* dict) : dict(dict) {} + const DictionaryChunk* dict; + using hash_type = std::hash; + using is_transparent = void; + + std::size_t operator()(const DictionaryEntry& entry) const { + return std::hash()(entry.get(*dict)); + } + std::size_t operator()(const char* str) const { return hash_type{}(str); } + std::size_t operator()(std::string_view str) const { return hash_type{}(str); } + std::size_t operator()(std::string const& str) const { return hash_type{}(str); } + + bool operator()(const DictionaryEntry& lhs, const DictionaryEntry& rhs) const { + return lhs.get(*dict) == rhs.get(*dict); + } + bool operator()(const DictionaryEntry& lhs, std::string_view rhs) const { + return lhs.get(*dict) == rhs; + } + bool operator()(std::string_view lhs, const DictionaryEntry& rhs) const { + return lhs == rhs.get(*dict); + } + }; + + std::unordered_set indexTable; }; } // namespace storage } // namespace kuzu diff --git a/src/include/storage/store/dictionary_column.h b/src/include/storage/store/dictionary_column.h index a9bc94386cb..446de039eca 100644 --- a/src/include/storage/store/dictionary_column.h +++ b/src/include/storage/store/dictionary_column.h @@ -22,16 +22,17 @@ class DictionaryColumn { std::vector>& offsetsToScan, common::ValueVector* resultVector, const ColumnChunkMetadata& indexMeta); - DictionaryChunk::string_index_t append( - common::node_group_idx_t nodeGroupIdx, std::string_view val); + DictionaryChunk::string_index_t append(common::node_group_idx_t nodeGroupIdx, + std::string_view val); bool canCommitInPlace(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, uint64_t numNewStrings, uint64_t totalStringLengthToAdd); - uint64_t getNumValuesInOffsets( - transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx); + uint64_t getNumValuesInOffsets(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx); + void prepareCommit(); void checkpointInMemory(); void rollbackInMemory(); diff --git a/src/include/storage/store/list_column.h b/src/include/storage/store/list_column.h new file mode 100644 index 00000000000..b98e95571a1 --- /dev/null +++ b/src/include/storage/store/list_column.h @@ -0,0 +1,107 @@ +#pragma once + +#include "column.h" + +// List is a nested data type which is stored as three chunks: +// 1. Offset column (type: INT64). Using offset to partition the data column into multiple lists. +// 2. Size column. Stores the size of each list. +// 3. Data column. Stores the actual data of the list. +// Similar to other data types, nulls are stored in the null column. +// Example layout for list of INT64: +// Four lists: [4,7,8,12], null, [2, 3], [] +// Offset column: [4, 4, 6, 6] +// Size column: [4, 0, 2, 0] +// data column: [4, 7, 8, 12, 2, 3] +// When updating the data, we first append the data to the data column, and then update the offset +// and size accordingly. Besides offset column, we introduce an extra size column here to enable +// in-place updates of a list column. In a list column chunk, offsets of lists are not always sorted +// after updates. This is good for writes, but it introduces extra overheads for scans, as lists can +// be scattered, and scans have to be broken into multiple small reads. To achieve a balance between +// reads and writes, during updates, we rewrite the whole list column chunk in ascending order +// when the offsets are not sorted in ascending order and the size of data column chunk is larger +// than half of its capacity. + +namespace kuzu { +namespace storage { + +struct ListOffsetSizeInfo { + common::offset_t numTotal; + std::unique_ptr offsetColumnChunk; + std::unique_ptr sizeColumnChunk; + + ListOffsetSizeInfo(common::offset_t numTotal, std::unique_ptr offsetColumnChunk, + std::unique_ptr sizeColumnChunk) + : numTotal{numTotal}, offsetColumnChunk{std::move(offsetColumnChunk)}, + sizeColumnChunk{std::move(sizeColumnChunk)} {} + + common::list_size_t getListSize(uint64_t pos) const; + common::offset_t getListEndOffset(uint64_t pos) const; + common::offset_t getListStartOffset(uint64_t pos) const; + + bool isOffsetSortedAscending(uint64_t startPos, uint64_t endPos) const; +}; + +class ListColumn : public Column { + friend class ListLocalColumn; + +public: + ListColumn(std::string name, common::LogicalType dataType, + const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, + BufferManager* bufferManager, WAL* wal, transaction::Transaction* transaction, + RWPropertyStats propertyStatistics, bool enableCompression); + + void scan(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, + common::offset_t startOffsetInGroup, common::offset_t endOffsetInGroup, + common::ValueVector* resultVector, uint64_t offsetInVector = 0) final; + + void scan(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, + ColumnChunk* columnChunk, common::offset_t startOffset = 0, + common::offset_t endOffset = common::INVALID_OFFSET) final; + + inline Column* getDataColumn() { return dataColumn.get(); } + +protected: + void scanInternal(transaction::Transaction* transaction, common::ValueVector* nodeIDVector, + common::ValueVector* resultVector) final; + + void lookupValue(transaction::Transaction* transaction, common::offset_t nodeOffset, + common::ValueVector* resultVector, uint32_t posInVector) final; + + void append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) override; + +private: + void scanUnfiltered(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, common::ValueVector* resultVector, + const ListOffsetSizeInfo& listOffsetInfoInStorage); + void scanFiltered(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, + common::ValueVector* offsetVector, const ListOffsetSizeInfo& listOffsetInfoInStorage); + + void prepareCommit() final; + void checkpointInMemory() final; + void rollbackInMemory() final; + + common::offset_t readOffset(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInNodeGroup); + + common::list_size_t readSize(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInNodeGroup); + + ListOffsetSizeInfo getListOffsetSizeInfo(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, common::offset_t startOffsetInNodeGroup, + common::offset_t endOffsetInNodeGroup); + + void prepareCommitForChunk(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, + const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) override; + void prepareCommitForChunk(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, + ColumnChunk* chunk, common::offset_t startSrcOffset) override; + +private: + std::unique_ptr sizeColumn; + std::unique_ptr dataColumn; +}; + +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/store/list_column_chunk.h b/src/include/storage/store/list_column_chunk.h new file mode 100644 index 00000000000..c721f67089f --- /dev/null +++ b/src/include/storage/store/list_column_chunk.h @@ -0,0 +1,100 @@ +#pragma once + +#include "common/data_chunk/sel_vector.h" +#include "storage/store/column_chunk.h" + +namespace kuzu { +namespace storage { + +// TODO(Guodong): Let's simplify the data structure here by getting rid of this class. +struct ListDataColumnChunk { + std::unique_ptr dataColumnChunk; + uint64_t capacity; + + explicit ListDataColumnChunk(std::unique_ptr dataChunk) + : dataColumnChunk{std::move(dataChunk)}, capacity{this->dataColumnChunk->capacity} {} + + void reset() const; + + void resizeBuffer(uint64_t numValues); + + inline void append(common::ValueVector* dataVector, common::SelectionVector& selVector) const { + dataColumnChunk->append(dataVector, selVector); + } + + inline uint64_t getNumValues() const { return dataColumnChunk->getNumValues(); } +}; + +class ListColumnChunk final : public ColumnChunk { + +public: + ListColumnChunk(common::LogicalType dataType, uint64_t capacity, bool enableCompression, + bool inMemory); + + inline ColumnChunk* getDataColumnChunk() const { + return listDataColumnChunk->dataColumnChunk.get(); + } + + inline ColumnChunk* getSizeColumnChunk() const { return sizeColumnChunk.get(); } + + void resetToEmpty() override; + + inline void setNumValues(uint64_t numValues_) override { + ColumnChunk::setNumValues(numValues_); + sizeColumnChunk->setNumValues(numValues_); + } + + void append(common::ValueVector* vector, const common::SelectionVector& selVector) final; + + void lookup(common::offset_t offsetInChunk, common::ValueVector& output, + common::sel_t posInOutputVector) const override; + + // Note: `write` assumes that no `append` will be called afterward. + void write(common::ValueVector* vector, common::offset_t offsetInVector, + common::offset_t offsetInChunk) override; + void write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + common::RelMultiplicity multiplicity) override; + void write(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, + common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; + void copy(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, + common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; + + inline void resizeDataColumnChunk(uint64_t numValues) { + listDataColumnChunk->resizeBuffer(numValues); + } + + inline void resize(uint64_t newCapacity) override { + ColumnChunk::resize(newCapacity); + sizeColumnChunk->resize(newCapacity); + } + + common::offset_t getListStartOffset(common::offset_t offset) const; + + common::offset_t getListEndOffset(common::offset_t offset) const; + + common::list_size_t getListSize(common::offset_t offset) const; + + void resetOffset(); + void resetFromOtherChunk(ListColumnChunk* other); + void finalize() override; + bool isOffsetsConsecutiveAndSortedAscending(uint64_t startPos, uint64_t endPos) const; + bool sanityCheck() override; + +protected: + void copyListValues(const common::list_entry_t& entry, common::ValueVector* dataVector); + +private: + void append(ColumnChunk* other, common::offset_t startPosInOtherChunk, + uint32_t numValuesToAppend) override; + + void appendNullList(); + +protected: + std::unique_ptr sizeColumnChunk; + std::unique_ptr listDataColumnChunk; + // we use checkOffsetSortedAsc flag to indicate that we do not trigger random write + bool checkOffsetSortedAsc; +}; + +} // namespace storage +} // namespace kuzu diff --git a/src/include/storage/store/node_group.h b/src/include/storage/store/node_group.h deleted file mode 100644 index 1343b10a6fd..00000000000 --- a/src/include/storage/store/node_group.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include "common/column_data_format.h" -#include "common/data_chunk/data_chunk.h" -#include "storage/store/column_chunk.h" - -namespace kuzu { -namespace storage { - -class Column; - -class NodeGroup { -public: - NodeGroup(const std::vector>& columnTypes, - bool enableCompression, uint64_t capacity); - NodeGroup(const std::vector>& columns, bool enableCompression); - virtual ~NodeGroup() = default; - - inline uint64_t getNodeGroupIdx() const { return nodeGroupIdx; } - inline common::row_idx_t getNumRows() const { return numRows; } - inline ColumnChunk* getColumnChunk(common::column_id_t columnID) { - KU_ASSERT(columnID < chunks.size()); - return chunks[columnID].get(); - } - inline bool isFull() const { return numRows == common::StorageConstants::NODE_GROUP_SIZE; } - - void resetToEmpty(); - void setAllNull(); - void setNumValues(common::offset_t numValues); - void resizeChunks(uint64_t newSize); - - uint64_t append(const std::vector& columnVectors, - common::DataChunkState* columnState, uint64_t numValuesToAppend); - common::offset_t append(NodeGroup* other, common::offset_t offsetInOtherNodeGroup); - void write(common::DataChunk* dataChunk, common::vector_idx_t offsetVector); - - void finalize(uint64_t nodeGroupIdx_); - - virtual inline void writeToColumnChunk(common::vector_idx_t chunkIdx, - common::vector_idx_t vectorIdx, common::DataChunk* dataChunk, - common::ValueVector* offsetVector) { - chunks[chunkIdx]->write( - dataChunk->getValueVector(vectorIdx).get(), offsetVector, false /* isCSR */); - } - -protected: - std::vector> chunks; - -private: - uint64_t nodeGroupIdx; - common::row_idx_t numRows; -}; - -struct CSRHeaderChunks { - std::unique_ptr offset; - std::unique_ptr length; - - CSRHeaderChunks() {} - explicit CSRHeaderChunks( - bool enableCompression, uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE); - - common::offset_t getStartCSROffset(common::offset_t nodeOffset) const; - common::offset_t getEndCSROffset(common::offset_t nodeOffset) const; - common::length_t getCSRLength(common::offset_t nodeOffset) const; - - bool sanityCheck() const; - void copyFrom(const CSRHeaderChunks& other) const; - void fillDefaultValues(common::offset_t newNumValues) const; - inline void setNumValues(common::offset_t numValues) const { - offset->setNumValues(numValues); - length->setNumValues(numValues); - } -}; - -class CSRNodeGroup : public NodeGroup { -public: - CSRNodeGroup(const std::vector>& columnTypes, - bool enableCompression); - - CSRHeaderChunks& getCSRHeader() { return csrHeaderChunks; } - const CSRHeaderChunks& getCSRHeader() const { return csrHeaderChunks; } - - inline void writeToColumnChunk(common::vector_idx_t chunkIdx, common::vector_idx_t vectorIdx, - common::DataChunk* dataChunk, common::ValueVector* offsetVector) override { - chunks[chunkIdx]->write( - dataChunk->getValueVector(vectorIdx).get(), offsetVector, true /* isCSR */); - } - -private: - CSRHeaderChunks csrHeaderChunks; -}; - -struct NodeGroupFactory { - static inline std::unique_ptr createNodeGroup(common::ColumnDataFormat dataFormat, - const std::vector>& columnTypes, - bool enableCompression, uint64_t capacity = common::StorageConstants::NODE_GROUP_SIZE) { - return dataFormat == common::ColumnDataFormat::REGULAR ? - std::make_unique(columnTypes, enableCompression, capacity) : - std::make_unique(columnTypes, enableCompression); - } -}; - -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/store/node_table.h b/src/include/storage/store/node_table.h index 8b232ba94dc..b3a16110634 100644 --- a/src/include/storage/store/node_table.h +++ b/src/include/storage/store/node_table.h @@ -6,16 +6,40 @@ #include "common/cast.h" #include "storage/index/hash_index.h" #include "storage/stats/nodes_store_statistics.h" -#include "storage/store/node_group.h" +#include "storage/store/chunked_node_group.h" #include "storage/store/node_table_data.h" #include "storage/store/table.h" namespace kuzu { -namespace catalog { -class NodeTableSchema; -} namespace storage { +struct NodeTableInsertState : public TableInsertState { + common::ValueVector& nodeIDVector; + const common::ValueVector& pkVector; + + NodeTableInsertState(common::ValueVector& nodeIDVector, const common::ValueVector& pkVector, + const std::vector& propertyVectors) + : TableInsertState{std::move(propertyVectors)}, nodeIDVector{nodeIDVector}, + pkVector{pkVector} {} +}; + +struct NodeTableUpdateState : public TableUpdateState { + const common::ValueVector& nodeIDVector; + + NodeTableUpdateState(common::column_id_t columnID, const common::ValueVector& nodeIDVector, + const common::ValueVector& propertyVector) + : TableUpdateState{columnID, propertyVector}, nodeIDVector{nodeIDVector} {} +}; + +struct NodeTableDeleteState : public TableDeleteState { + const common::ValueVector& nodeIDVector; + common::ValueVector& pkVector; + + explicit NodeTableDeleteState(const common::ValueVector& nodeIDVector, + common::ValueVector& pkVector) + : nodeIDVector{nodeIDVector}, pkVector{pkVector} {} +}; + class NodeTable final : public Table { public: NodeTable(BMFileHandle* dataFH, BMFileHandle* metadataFH, @@ -31,60 +55,64 @@ class NodeTable final : public Table { tablesStatistics); return nodesStats->getMaxNodeOffset(transaction, tableID); } - inline void setSelVectorForDeletedOffsets( - transaction::Transaction* trx, std::shared_ptr& vector) const { + void setSelVectorForDeletedOffsets(transaction::Transaction* trx, + common::ValueVector* vector) const { KU_ASSERT(vector->isSequential()); - common::ku_dynamic_cast(tablesStatistics) - ->setDeletedNodeOffsetsForMorsel(trx, vector, tableID); + auto nodeStateCollection = + common::ku_dynamic_cast( + tablesStatistics); + nodeStateCollection->setDeletedNodeOffsetsForMorsel(trx, vector, tableID); } inline void initializeReadState(transaction::Transaction* transaction, - std::vector columnIDs, common::ValueVector* inNodeIDVector, - TableReadState* readState) { - tableData->initializeReadState( - transaction, std::move(columnIDs), inNodeIDVector, readState); + std::vector columnIDs, const common::ValueVector& inNodeIDVector, + TableReadState& readState) { + tableData->initializeReadState(transaction, std::move(columnIDs), inNodeIDVector, + *readState.dataReadState); } - void read(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* nodeIDVector, - const std::vector& outputVectors) override; + void read(transaction::Transaction* transaction, TableReadState& readState) override; // Return the max node offset during insertions. - common::offset_t validateUniquenessConstraint( - transaction::Transaction* tx, const std::vector& propertyVectors); - common::offset_t insert(transaction::Transaction* tx, common::ValueVector* nodeIDVector, + common::offset_t validateUniquenessConstraint(transaction::Transaction* transaction, const std::vector& propertyVectors); - void update(transaction::Transaction* transaction, common::column_id_t columnID, - common::ValueVector* nodeIDVector, common::ValueVector* propertyVector); - void delete_(transaction::Transaction* transaction, common::ValueVector* nodeIDVector, - common::ValueVector* pkVector); - inline void append(NodeGroup* nodeGroup) { tableData->append(nodeGroup); } - inline common::column_id_t getNumColumns() const { return tableData->getNumColumns(); } - inline Column* getColumn(common::column_id_t columnID) { - return tableData->getColumn(columnID); + void insert(transaction::Transaction* transaction, TableInsertState& insertState) override; + void update(transaction::Transaction* transaction, TableUpdateState& updateState) override; + void delete_(transaction::Transaction* transaction, TableDeleteState& deleteState) override; + + void addColumn(transaction::Transaction* transaction, const catalog::Property& property, + common::ValueVector* defaultValueVector) override; + inline void dropColumn(common::column_id_t columnID) override { + tableData->dropColumn(columnID); } + inline common::column_id_t getPKColumnID() const { return pkColumnID; } inline PrimaryKeyIndex* getPKIndex() const { return pkIndex.get(); } inline NodesStoreStatsAndDeletedIDs* getNodeStatisticsAndDeletedIDs() const { return common::ku_dynamic_cast( tablesStatistics); } - - void addColumn(transaction::Transaction* transaction, const catalog::Property& property, - common::ValueVector* defaultValueVector) override; - inline void dropColumn(common::column_id_t columnID) override { - tableData->dropColumn(columnID); + inline common::column_id_t getNumColumns() const { return tableData->getNumColumns(); } + inline Column* getColumn(common::column_id_t columnID) { + return tableData->getColumn(columnID); } + inline void append(ChunkedNodeGroup* nodeGroup) { tableData->append(nodeGroup); } + void prepareCommit(transaction::Transaction* transaction, LocalTable* localTable) override; - void prepareRollback(LocalTableData* localTable) override; + void prepareCommit() override; + void prepareRollback(LocalTable* localTable) override; void checkpointInMemory() override; void rollbackInMemory() override; private: void updatePK(transaction::Transaction* transaction, common::column_id_t columnID, - common::ValueVector* nodeIDVector, common::ValueVector* pkVector); - void insertPK(common::ValueVector* nodeIDVector, common::ValueVector* primaryKeyVector); + const common::ValueVector& nodeIDVector, const common::ValueVector& pkVector); + void insertPK(const common::ValueVector& nodeIDVector, + const common::ValueVector& primaryKeyVector); + + void scan(transaction::Transaction* transaction, TableReadState& readState); + void lookup(transaction::Transaction* transaction, TableReadState& readState); private: std::unique_ptr tableData; diff --git a/src/include/storage/store/node_table_data.h b/src/include/storage/store/node_table_data.h index 75617ae8e4a..218b5673a10 100644 --- a/src/include/storage/store/node_table_data.h +++ b/src/include/storage/store/node_table_data.h @@ -16,33 +16,34 @@ class NodeTableData final : public TableData { // This interface is node table specific, as rel table requires also relDataDirection. inline virtual void initializeReadState(transaction::Transaction* /*transaction*/, - std::vector columnIDs, common::ValueVector* /*inNodeIDVector*/, - TableReadState* readState) { - readState->columnIDs = std::move(columnIDs); + std::vector columnIDs, const common::ValueVector& /*inNodeIDVector*/, + TableDataReadState& readState) { + readState.columnIDs = columnIDs; } - void scan(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* nodeIDVector, + + void scan(transaction::Transaction* transaction, TableDataReadState& readState, + const common::ValueVector& nodeIDVector, const std::vector& outputVectors) override; - void lookup(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* nodeIDVector, + void lookup(transaction::Transaction* transaction, TableDataReadState& readState, + const common::ValueVector& nodeIDVector, const std::vector& outputVectors) override; - // These two interfaces are node table specific, as rel table requires also relIDVector. - void insert(transaction::Transaction* transaction, common::ValueVector* nodeIDVector, - const std::vector& propertyVectors); - void update(transaction::Transaction* transaction, common::column_id_t columnID, - common::ValueVector* nodeIDVector, common::ValueVector* propertyVector); - void delete_(transaction::Transaction* transaction, common::ValueVector* nodeIDVector); - - void append(NodeGroup* nodeGroup) override; + // Flush the nodeGroup to disk and update metadataDAs. + void append(ChunkedNodeGroup* nodeGroup) override; - void prepareLocalTableToCommit( - transaction::Transaction* transaction, LocalTableData* localTable) override; + void prepareLocalTableToCommit(transaction::Transaction* transaction, + LocalTableData* localTable) override; inline common::node_group_idx_t getNumNodeGroups( transaction::Transaction* transaction) const override { return columns[0]->getNumNodeGroups(transaction); } + +private: + void append(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, + LocalNodeGroup* localNodeGroup); + void merge(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, + LocalNodeGroup* nodeGroup); }; } // namespace storage diff --git a/src/include/storage/store/null_column.h b/src/include/storage/store/null_column.h index 4a1a71ef184..11c6ccd5121 100644 --- a/src/include/storage/store/null_column.h +++ b/src/include/storage/store/null_column.h @@ -20,8 +20,8 @@ class NullColumn final : public Column { BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, Transaction* transaction, RWPropertyStats propertyStatistics, bool enableCompression); - void scan( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) override; + void scan(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) override; void scan(transaction::Transaction* transaction, node_group_idx_t nodeGroupIdx, offset_t startOffsetInGroup, offset_t endOffsetInGroup, ValueVector* resultVector, uint64_t offsetInVector) override; @@ -29,8 +29,8 @@ class NullColumn final : public Column { ColumnChunk* columnChunk, common::offset_t startOffset = 0, common::offset_t endOffset = common::INVALID_OFFSET) override; - void lookup( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) override; + void lookup(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) override; void append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) override; @@ -43,15 +43,10 @@ class NullColumn final : public Column { void write(common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInChunk, ColumnChunk* data, common::offset_t dataOffset, common::length_t numValues) override; - bool canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo) override; - bool canCommitInPlace(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, - ColumnChunk* chunk, common::offset_t srcOffset) override; - void commitLocalChunkInPlace(Transaction* /*transaction*/, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) override; + void commitLocalChunkInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, + const ChunkCollection& localInsertChunk, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunk, const offset_to_row_idx_t& updateInfo, + const offset_set_t& deleteInfo) override; private: std::unique_ptr getEmptyChunkForCommit(uint64_t capacity) override { diff --git a/src/include/storage/store/rel_table.h b/src/include/storage/store/rel_table.h index 27f8c517728..5eb40b28b7f 100644 --- a/src/include/storage/store/rel_table.h +++ b/src/include/storage/store/rel_table.h @@ -1,13 +1,64 @@ #pragma once #include "catalog/catalog_entry/rel_table_catalog_entry.h" -#include "storage/stats/rel_table_statistics.h" #include "storage/store/rel_table_data.h" #include "storage/store/table.h" namespace kuzu { namespace storage { +struct RelTableReadState : public TableReadState { + common::RelDataDirection direction; + + RelTableReadState(const common::ValueVector& nodeIDVector, + const std::vector& columnIDs, + const std::vector& outputVectors, common::RelDataDirection direction) + : TableReadState{nodeIDVector, columnIDs, outputVectors}, direction{direction} { + dataReadState = std::make_unique(); + } + + bool hasMoreToRead(transaction::Transaction* transaction) const { + auto relDataReadState = + common::ku_dynamic_cast(dataReadState.get()); + return relDataReadState->hasMoreToRead(transaction); + } +}; + +struct RelTableInsertState : public TableInsertState { + const common::ValueVector& srcNodeIDVector; + const common::ValueVector& dstNodeIDVector; + + RelTableInsertState(const common::ValueVector& srcNodeIDVector, + const common::ValueVector& dstNodeIDVector, + const std::vector& propertyVectors) + : TableInsertState{std::move(propertyVectors)}, srcNodeIDVector{srcNodeIDVector}, + dstNodeIDVector{dstNodeIDVector} {} +}; + +struct RelTableUpdateState : public TableUpdateState { + const common::ValueVector& srcNodeIDVector; + const common::ValueVector& dstNodeIDVector; + const common::ValueVector& relIDVector; + + RelTableUpdateState(common::column_id_t columnID, const common::ValueVector& srcNodeIDVector, + const common::ValueVector& dstNodeIDVector, const common::ValueVector& relIDVector, + const common::ValueVector& propertyVector) + : TableUpdateState{columnID, propertyVector}, srcNodeIDVector{srcNodeIDVector}, + dstNodeIDVector{dstNodeIDVector}, relIDVector{relIDVector} {} +}; + +struct RelTableDeleteState : public TableDeleteState { + const common::ValueVector& srcNodeIDVector; + const common::ValueVector& dstNodeIDVector; + const common::ValueVector& relIDVector; + + RelTableDeleteState(const common::ValueVector& srcNodeIDVector, + const common::ValueVector& dstNodeIDVector, const common::ValueVector& relIDVector) + : srcNodeIDVector{srcNodeIDVector}, dstNodeIDVector{dstNodeIDVector}, + relIDVector{relIDVector} {} +}; + +// TODO(Guodong): Should move inside RelTableDeleteState. struct RelDetachDeleteState { std::unique_ptr dstNodeIDVector; std::unique_ptr relIDVector; @@ -24,25 +75,24 @@ class RelTable final : public Table { inline void initializeReadState(transaction::Transaction* transaction, common::RelDataDirection direction, const std::vector& columnIDs, - common::ValueVector* inNodeIDVector, RelDataReadState* readState) { + const common::ValueVector& inNodeIDVector, RelTableReadState& readState) { + if (!readState.dataReadState) { + readState.dataReadState = std::make_unique(); + } return direction == common::RelDataDirection::FWD ? - fwdRelTableData->initializeReadState( - transaction, columnIDs, inNodeIDVector, readState) : - bwdRelTableData->initializeReadState( - transaction, columnIDs, inNodeIDVector, readState); + fwdRelTableData->initializeReadState(transaction, columnIDs, inNodeIDVector, + common::ku_dynamic_cast( + *readState.dataReadState)) : + bwdRelTableData->initializeReadState(transaction, columnIDs, inNodeIDVector, + common::ku_dynamic_cast( + *readState.dataReadState)); } - void read(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* inNodeIDVector, - const std::vector& outputVectors) override; - - void insert(transaction::Transaction* transaction, common::ValueVector* srcNodeIDVector, - common::ValueVector* dstNodeIDVector, - const std::vector& propertyVectors); - void update(transaction::Transaction* transaction, common::column_id_t columnID, - common::ValueVector* srcNodeIDVector, common::ValueVector* dstNodeIDVector, - common::ValueVector* relIDVector, common::ValueVector* propertyVector); - void delete_(transaction::Transaction* transaction, common::ValueVector* srcNodeIDVector, - common::ValueVector* dstNodeIDVector, common::ValueVector* relIDVector); + void read(transaction::Transaction* transaction, TableReadState& readState) override; + + void insert(transaction::Transaction* transaction, TableInsertState& insertState) override; + void update(transaction::Transaction* transaction, TableUpdateState& updateState) override; + void delete_(transaction::Transaction* transaction, TableDeleteState& deleteState) override; + void detachDelete(transaction::Transaction* transaction, common::RelDataDirection direction, common::ValueVector* srcNodeIDVector, RelDetachDeleteState* deleteState); void checkIfNodeHasRels(transaction::Transaction* transaction, @@ -54,10 +104,6 @@ class RelTable final : public Table { fwdRelTableData->dropColumn(columnID); bwdRelTableData->dropColumn(columnID); } - inline Column* getAdjColumn(common::RelDataDirection direction) { - return direction == common::RelDataDirection::FWD ? fwdRelTableData->getAdjColumn() : - bwdRelTableData->getAdjColumn(); - } inline Column* getCSROffsetColumn(common::RelDataDirection direction) { return direction == common::RelDataDirection::FWD ? fwdRelTableData->getCSROffsetColumn() : bwdRelTableData->getCSROffsetColumn(); @@ -74,14 +120,27 @@ class RelTable final : public Table { return direction == common::RelDataDirection::FWD ? fwdRelTableData->getColumn(columnID) : bwdRelTableData->getColumn(columnID); } + inline const std::vector>& getColumns( + common::RelDataDirection direction) const { + return direction == common::RelDataDirection::FWD ? fwdRelTableData->getColumns() : + bwdRelTableData->getColumns(); + } - inline void append(NodeGroup* nodeGroup, common::RelDataDirection direction) { + inline void append(ChunkedNodeGroup* nodeGroup, common::RelDataDirection direction) { direction == common::RelDataDirection::FWD ? fwdRelTableData->append(nodeGroup) : bwdRelTableData->append(nodeGroup); } + inline bool isNewNodeGroup(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, common::RelDataDirection direction) { + return direction == common::RelDataDirection::FWD ? + fwdRelTableData->isNewNodeGroup(transaction, nodeGroupIdx) : + bwdRelTableData->isNewNodeGroup(transaction, nodeGroupIdx); + } + void prepareCommit(transaction::Transaction* transaction, LocalTable* localTable) override; - void prepareRollback(LocalTableData* localTable) override; + void prepareCommit() override; + void prepareRollback(LocalTable* localTable) override; void checkpointInMemory() override; void rollbackInMemory() override; @@ -91,13 +150,11 @@ class RelTable final : public Table { } private: - void scan(transaction::Transaction* transaction, RelDataReadState& scanState, - common::ValueVector* inNodeIDVector, - const std::vector& outputVectors); + void scan(transaction::Transaction* transaction, RelTableReadState& scanState); common::row_idx_t detachDeleteForCSRRels(transaction::Transaction* transaction, RelTableData* tableData, RelTableData* reverseTableData, - common::ValueVector* srcNodeIDVector, RelDataReadState* relDataReadState, + common::ValueVector* srcNodeIDVector, RelTableReadState* relDataReadState, RelDetachDeleteState* deleteState); private: diff --git a/src/include/storage/store/rel_table_data.h b/src/include/storage/store/rel_table_data.h index ab9a7fca0c4..a3a254e3988 100644 --- a/src/include/storage/store/rel_table_data.h +++ b/src/include/storage/store/rel_table_data.h @@ -1,7 +1,7 @@ #pragma once #include "common/enums/rel_direction.h" -#include "storage/store/node_group.h" +#include "storage/store/chunked_node_group.h" #include "storage/store/table_data.h" namespace kuzu { @@ -10,7 +10,7 @@ namespace storage { using density_range_t = std::pair; class LocalRelNG; -struct RelDataReadState : public TableReadState { +struct RelDataReadState : public TableDataReadState { common::RelDataDirection direction; common::offset_t startNodeOffset; common::offset_t numNodes; @@ -18,7 +18,7 @@ struct RelDataReadState : public TableReadState { common::offset_t posInCurrentCSR; std::vector csrListEntries; // Temp auxiliary data structure to scan the offset of each CSR node in the offset column chunk. - CSRHeaderChunks csrHeaderChunks = CSRHeaderChunks(false /*enableCompression*/); + ChunkedCSRHeader csrHeaderChunks = ChunkedCSRHeader(false /*enableCompression*/); // Following fields are used for local storage. bool readFromLocalStorage; @@ -44,18 +44,18 @@ struct CSRHeaderColumns { std::unique_ptr length; inline void scan(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, - CSRHeaderChunks& chunks) const { + ChunkedCSRHeader& chunks) const { offset->scan(transaction, nodeGroupIdx, chunks.offset.get()); length->scan(transaction, nodeGroupIdx, chunks.length.get()); } - inline void append( - const CSRHeaderChunks& headerChunks, common::node_group_idx_t nodeGroupIdx) const { + inline void append(const ChunkedCSRHeader& headerChunks, + common::node_group_idx_t nodeGroupIdx) const { offset->append(headerChunks.offset.get(), nodeGroupIdx); length->append(headerChunks.length.get(), nodeGroupIdx); } - common::offset_t getNumNodes( - transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx) const; + common::offset_t getNumNodes(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx) const; }; // TODO(Guodong): Serialize the info to disk. This should be a config per node group. @@ -98,20 +98,20 @@ class RelsStoreStats; class RelTableData final : public TableData { public: struct PersistentState { - CSRHeaderChunks header; + ChunkedCSRHeader header; std::unique_ptr relIDChunk; common::offset_t leftCSROffset = common::INVALID_OFFSET; common::offset_t rightCSROffset = common::INVALID_OFFSET; explicit PersistentState(common::offset_t numNodes) { - header = CSRHeaderChunks(false /*enableCompression*/, numNodes); + header = ChunkedCSRHeader(false /*enableCompression*/, numNodes); } }; struct LocalState { public: LocalRelNG* localNG; - CSRHeaderChunks header; + ChunkedCSRHeader header; PackedCSRRegion region; std::vector sizeChangesPerSegment; std::vector hasChangesPerSegment; @@ -123,12 +123,9 @@ class RelTableData final : public TableData { common::offset_t rightCSROffset = common::INVALID_OFFSET; bool needSliding = false; - explicit LocalState(LocalRelNG* localNG) : localNG{localNG} { initChangesPerSegment(); } + explicit LocalState(LocalRelNG* localNG); inline void setRegion(PackedCSRRegion& region_) { region = region_; } - - private: - void initChangesPerSegment(); }; RelTableData(BMFileHandle* dataFH, BMFileHandle* metadataFH, BufferManager* bufferManager, @@ -136,62 +133,63 @@ class RelTableData final : public TableData { common::RelDataDirection direction, bool enableCompression); void initializeReadState(transaction::Transaction* transaction, - std::vector columnIDs, common::ValueVector* inNodeIDVector, - RelDataReadState* readState); - void scan(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* inNodeIDVector, + std::vector columnIDs, const common::ValueVector& inNodeIDVector, + RelDataReadState& readState); + void scan(transaction::Transaction* transaction, TableDataReadState& readState, + const common::ValueVector& inNodeIDVector, const std::vector& outputVectors) override; - void lookup(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* inNodeIDVector, + void lookup(transaction::Transaction* transaction, TableDataReadState& readState, + const common::ValueVector& inNodeIDVector, const std::vector& outputVectors) override; - void insert(transaction::Transaction* transaction, common::ValueVector* srcNodeIDVector, - common::ValueVector* dstNodeIDVector, - const std::vector& propertyVectors); - void update(transaction::Transaction* transaction, common::column_id_t columnID, - common::ValueVector* srcNodeIDVector, common::ValueVector* relIDVector, - common::ValueVector* propertyVector); + // TODO: Should be removed. This is used by detachDelete for now. bool delete_(transaction::Transaction* transaction, common::ValueVector* srcNodeIDVector, - common::ValueVector* dstNodeIDVector, common::ValueVector* relIDVector); + common::ValueVector* relIDVector); - void checkRelMultiplicityConstraint( - transaction::Transaction* transaction, common::ValueVector* srcNodeIDVector) const; - bool checkIfNodeHasRels( - transaction::Transaction* transaction, common::offset_t nodeOffset) const; - void append(NodeGroup* nodeGroup) override; + void checkRelMultiplicityConstraint(transaction::Transaction* transaction, + common::ValueVector* srcNodeIDVector) const; + bool checkIfNodeHasRels(transaction::Transaction* transaction, + common::offset_t nodeOffset) const; + void append(ChunkedNodeGroup* nodeGroup) override; - inline Column* getAdjColumn() const { return adjColumn.get(); } + inline Column* getNbrIDColumn() const { return columns[NBR_ID_COLUMN_ID].get(); } inline Column* getCSROffsetColumn() const { return csrHeaderColumns.offset.get(); } inline Column* getCSRLengthColumn() const { return csrHeaderColumns.length.get(); } - Column* getColumn(common::column_id_t columnID) override; - void prepareLocalTableToCommit( - transaction::Transaction* transaction, LocalTableData* localTable) override; + bool isNewNodeGroup(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx) const; + + void prepareLocalTableToCommit(transaction::Transaction* transaction, + LocalTableData* localTable) override; + + void prepareCommitNodeGroup(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, LocalRelNG* localRelNG); + void prepareCommit() override; void checkpointInMemory() override; void rollbackInMemory() override; inline common::node_group_idx_t getNumNodeGroups( transaction::Transaction* transaction) const override { - return adjColumn->getNumNodeGroups(transaction); + return columns[NBR_ID_COLUMN_ID]->getNumNodeGroups(transaction); } private: - std::vector findRegions( - const CSRHeaderChunks& headerChunks, LocalState& localState); - common::length_t getNewRegionSize(const CSRHeaderChunks& header, + static common::offset_t getMaxNumNodesInRegion(const ChunkedCSRHeader& header, + const PackedCSRRegion& region, const LocalRelNG* localNG); + + std::vector findRegions(const ChunkedCSRHeader& headerChunks, + LocalState& localState); + common::length_t getNewRegionSize(const ChunkedCSRHeader& header, const std::vector& sizeChangesPerSegment, PackedCSRRegion& region); - bool isWithinDensityBound(const CSRHeaderChunks& headerChunks, + bool isWithinDensityBound(const ChunkedCSRHeader& headerChunks, const std::vector& sizeChangesPerSegment, PackedCSRRegion& region); double getHighDensity(uint64_t level) const; - void prepareCommitNodeGroup(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalRelNG* localRelNG); - void updateCSRHeader(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, PersistentState& persistentState, LocalState& localState); - void distributeOffsets(const CSRHeaderChunks& header, LocalState& localState, + void distributeOffsets(const ChunkedCSRHeader& header, LocalState& localState, common::offset_t leftBoundary, common::offset_t rightBoundary); void updateRegion(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, PersistentState& persistentState, LocalState& localState); @@ -202,23 +200,21 @@ class RelTableData final : public TableData { common::node_group_idx_t nodeGroupIdx, common::column_id_t columnID, const PersistentState& persistentState, LocalState& localState); - void findPositionsForInsertions( - common::offset_t nodeOffset, common::length_t numInsertions, LocalState& localState); - void slideForInsertions( - common::offset_t nodeOffset, common::length_t numInsertions, LocalState& localState); + void findPositionsForInsertions(common::offset_t nodeOffset, common::length_t numInsertions, + LocalState& localState); + void slideForInsertions(common::offset_t nodeOffset, common::length_t numInsertions, + LocalState& localState); void slideLeftForInsertions(common::offset_t nodeOffset, common::offset_t leftBoundary, LocalState& localState, uint64_t numValuesToInsert); void slideRightForInsertions(common::offset_t nodeOffset, common::offset_t rightBoundary, LocalState& localState, uint64_t numValuesToInsert); - void applyUpdatesToChunk(const PersistentState& persistentState, const PackedCSRRegion& region, - LocalVectorCollection* localChunk, const update_insert_info_t& updateInfo, - ColumnChunk* chunk); + void applyUpdatesToChunk(const PersistentState& persistentState, LocalState& localState, + const ChunkCollection& localChunk, ColumnChunk* chunk, common::column_id_t columnID); void applyInsertionsToChunk(const PersistentState& persistentState, - const LocalState& localState, LocalVectorCollection* localChunk, - const update_insert_info_t& insertInfo, ColumnChunk* chunk); + const LocalState& localState, const ChunkCollection& localChunk, ColumnChunk* chunk); void applyDeletionsToChunk(const PersistentState& persistentState, const LocalState& localState, - const delete_info_t& deleteInfo, ColumnChunk* chunk); + ColumnChunk* chunk); void applyUpdatesToColumn(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, common::column_id_t columnID, @@ -233,25 +229,22 @@ class RelTableData final : public TableData { LocalState& localState, const PersistentState& persistentState, Column* column); std::vector> getSlidesForDeletions( - const PersistentState& persistentState, const LocalState& localState, - const delete_info_t& deleteInfo); + const PersistentState& persistentState, const LocalState& localState); - LocalRelNG* getLocalNodeGroup( - transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx); + LocalRelNG* getLocalNodeGroup(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx); - // TODO: Constrain T1 and T2 to numerics. template static double divideNoRoundUp(T1 v1, T2 v2) { + static_assert(std::is_arithmetic::value && std::is_arithmetic::value); return (double)v1 / (double)v2; } template static uint64_t multiplyAndRoundUpTo(T1 v1, T2 v2) { + static_assert(std::is_arithmetic::value && std::is_arithmetic::value); return std::ceil((double)v1 * (double)v2); } - LocalVectorCollection* getLocalChunk( - const LocalState& localState, common::column_id_t columnID); - inline void fillSequence(std::span offsets, common::offset_t startOffset) { for (auto i = 0u; i < offsets.size(); i++) { offsets[i] = i + startOffset; @@ -268,7 +261,6 @@ class RelTableData final : public TableData { private: PackedCSRInfo packedCSRInfo; CSRHeaderColumns csrHeaderColumns; - std::unique_ptr adjColumn; common::RelDataDirection direction; common::RelMultiplicity multiplicity; }; diff --git a/src/include/storage/store/string_column.h b/src/include/storage/store/string_column.h index fac763194cc..986cdc92bb3 100644 --- a/src/include/storage/store/string_column.h +++ b/src/include/storage/store/string_column.h @@ -28,6 +28,7 @@ class StringColumn final : public Column { void write(common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInChunk, ColumnChunk* data, common::offset_t dataOffset, common::length_t numValues) override; + void prepareCommit() override; void checkpointInMemory() override; void rollbackInMemory() override; @@ -49,8 +50,9 @@ class StringColumn final : public Column { private: bool canCommitInPlace(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo) override; + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunk, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunk, + const offset_to_row_idx_t& updateInfo) override; bool canCommitInPlace(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, common::offset_t srcOffset) override; @@ -58,6 +60,10 @@ class StringColumn final : public Column { bool canIndexCommitInPlace(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, uint64_t numStrings, common::offset_t maxOffset); + bool checkUpdateInPlace(transaction::Transaction* transaction, + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localChunk, + const offset_to_row_idx_t& writeInfo); + private: // Main column stores indices of values in the dictionary DictionaryColumn dictionary; diff --git a/src/include/storage/store/string_column_chunk.h b/src/include/storage/store/string_column_chunk.h index 9a54337d8cb..1ffb3bcb346 100644 --- a/src/include/storage/store/string_column_chunk.h +++ b/src/include/storage/store/string_column_chunk.h @@ -1,28 +1,35 @@ #pragma once #include "common/assert.h" +#include "common/data_chunk/sel_vector.h" +#include "common/types/types.h" +#include "storage/store/column_chunk.h" #include "storage/store/dictionary_chunk.h" namespace kuzu { namespace storage { -class StringColumnChunk : public ColumnChunk { +class StringColumnChunk final : public ColumnChunk { public: - StringColumnChunk(common::LogicalType dataType, uint64_t capacity, bool enableCompression); + StringColumnChunk(common::LogicalType dataType, uint64_t capacity, bool enableCompression, + bool inMemory); void resetToEmpty() final; - void append(common::ValueVector* vector) final; + void append(common::ValueVector* vector, const common::SelectionVector& selVector) final; void append(ColumnChunk* other, common::offset_t startPosInOtherChunk, - uint32_t numValuesToAppend) final; + uint32_t numValuesToAppend) override; + + void lookup(common::offset_t offsetInChunk, common::ValueVector& output, + common::sel_t posInOutputVector) const override; void write(common::ValueVector* vector, common::offset_t offsetInVector, - common::offset_t offsetInChunk) final; - void write(common::ValueVector* valueVector, common::ValueVector* offsetInChunkVector, - bool isCSR) final; + common::offset_t offsetInChunk) override; + void write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + common::RelMultiplicity multiplicity) override; void write(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; void copy(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, - common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) final; + common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; template T getValue(common::offset_t /*pos*/) const { @@ -31,22 +38,22 @@ class StringColumnChunk : public ColumnChunk { uint64_t getStringLength(common::offset_t pos) const { auto index = ColumnChunk::getValue(pos); - return dictionaryChunk.getStringLength(index); + return dictionaryChunk->getStringLength(index); } - inline DictionaryChunk& getDictionaryChunk() { return dictionaryChunk; } - inline const DictionaryChunk& getDictionaryChunk() const { return dictionaryChunk; } + inline DictionaryChunk& getDictionaryChunk() { return *dictionaryChunk; } + inline const DictionaryChunk& getDictionaryChunk() const { return *dictionaryChunk; } - void finalize() final; + void finalize() override; private: void appendStringColumnChunk(StringColumnChunk* other, common::offset_t startPosInOtherChunk, uint32_t numValuesToAppend); - void setValueFromString(const char* value, uint64_t length, uint64_t pos); + void setValueFromString(std::string_view value, uint64_t pos); private: - DictionaryChunk dictionaryChunk; + std::unique_ptr dictionaryChunk; // If we never update a value, we don't need to prune unused strings in finalize bool needFinalize; }; diff --git a/src/include/storage/store/struct_column.h b/src/include/storage/store/struct_column.h index 696e1002b0a..758d2bb66e2 100644 --- a/src/include/storage/store/struct_column.h +++ b/src/include/storage/store/struct_column.h @@ -23,6 +23,7 @@ class StructColumn final : public Column { void checkpointInMemory() override; void rollbackInMemory() override; + void prepareCommit() override; inline Column* getChild(common::vector_idx_t childIdx) { KU_ASSERT(childIdx < childColumns.size()); @@ -34,9 +35,9 @@ class StructColumn final : public Column { ColumnChunk* data, common::offset_t dataOffset, common::length_t numValues) override; void prepareCommitForChunk(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localColumnChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo, - const offset_set_t& deleteInfo) override; + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunk, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunk, + const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) override; void prepareCommitForChunk(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, common::offset_t startSrcOffset) override; @@ -48,12 +49,17 @@ class StructColumn final : public Column { common::ValueVector* resultVector) override; bool canCommitInPlace(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo) override; + common::node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunk, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunk, + const offset_to_row_idx_t& updateInfo) override; bool canCommitInPlace(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, common::offset_t dataOffset) override; +private: + static ChunkCollection getStructChildChunkCollection(const ChunkCollection& chunkCollection, + common::vector_idx_t childIdx); + private: std::vector> childColumns; }; diff --git a/src/include/storage/store/struct_column_chunk.h b/src/include/storage/store/struct_column_chunk.h index f24628f1abc..30e7513c527 100644 --- a/src/include/storage/store/struct_column_chunk.h +++ b/src/include/storage/store/struct_column_chunk.h @@ -1,41 +1,55 @@ #pragma once +#include "common/data_chunk/sel_vector.h" +#include "common/types/internal_id_t.h" +#include "common/types/types.h" #include "storage/store/column_chunk.h" namespace kuzu { namespace storage { -class StructColumnChunk : public ColumnChunk { +class StructColumnChunk final : public ColumnChunk { public: - StructColumnChunk(common::LogicalType dataType, uint64_t capacity, bool enableCompression); + StructColumnChunk(common::LogicalType dataType, uint64_t capacity, bool enableCompression, + bool inMemory); inline ColumnChunk* getChild(common::vector_idx_t childIdx) { KU_ASSERT(childIdx < childChunks.size()); return childChunks[childIdx].get(); } - void finalize() final; + void finalize() override; protected: void append(ColumnChunk* other, common::offset_t startPosInOtherChunk, uint32_t numValuesToAppend) final; - void append(common::ValueVector* vector) final; + void append(common::ValueVector* vector, const common::SelectionVector& selVector) final; + + void lookup(common::offset_t offsetInChunk, common::ValueVector& output, + common::sel_t posInOutputVector) const override; void write(common::ValueVector* vector, common::offset_t offsetInVector, - common::offset_t offsetInChunk) final; - void write(common::ValueVector* valueVector, common::ValueVector* offsetInChunkVector, - bool isCSR) final; + common::offset_t offsetInChunk) override; + void write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + common::RelMultiplicity multiplicity) override; void write(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; void copy(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; - void resize(uint64_t newCapacity) final; + void resize(uint64_t newCapacity) override; - void resetToEmpty() final; + void resetToEmpty() override; bool numValuesSanityCheck() const override; + void setNumValues(uint64_t numValues) override { + ColumnChunk::setNumValues(numValues); + for (auto& childChunk : childChunks) { + childChunk->setNumValues(numValues); + } + } + private: std::vector> childChunks; }; diff --git a/src/include/storage/store/table.h b/src/include/storage/store/table.h index be35656ad5c..b3717080583 100644 --- a/src/include/storage/store/table.h +++ b/src/include/storage/store/table.h @@ -7,8 +7,44 @@ namespace kuzu { namespace storage { -class LocalTable; +struct TableReadState { + const common::ValueVector& nodeIDVector; + std::vector columnIDs; + const std::vector& outputVectors; + std::unique_ptr dataReadState; + + TableReadState(const common::ValueVector& nodeIDVector, + const std::vector& columnIDs, + const std::vector& outputVectors) + : nodeIDVector{nodeIDVector}, columnIDs{std::move(columnIDs)}, + outputVectors{outputVectors} { + dataReadState = std::make_unique(); + } + virtual ~TableReadState() = default; +}; + +struct TableInsertState { + const std::vector& propertyVectors; + + explicit TableInsertState(const std::vector& propertyVectors) + : propertyVectors{propertyVectors} {} + virtual ~TableInsertState() = default; +}; +struct TableUpdateState { + common::column_id_t columnID; + const common::ValueVector& propertyVector; + + TableUpdateState(common::column_id_t columnID, const common::ValueVector& propertyVector) + : columnID{columnID}, propertyVector{propertyVector} {} + virtual ~TableUpdateState() = default; +}; + +struct TableDeleteState { + virtual ~TableDeleteState() = default; +}; + +class LocalTable; class Table { public: Table(catalog::TableCatalogEntry* tableEntry, TablesStatistics* tablesStatistics, @@ -21,23 +57,27 @@ class Table { inline common::TableType getTableType() const { return tableType; } inline common::table_id_t getTableID() const { return tableID; } - inline common::row_idx_t getNumTuples() const { - return tablesStatistics->getNumTuplesForTable(tableID); + inline common::row_idx_t getNumTuples(transaction::Transaction* transaction) const { + return tablesStatistics->getNumTuplesForTable(transaction, tableID); } - inline void setNumTuples(uint64_t numTuples) { - tablesStatistics->setNumTuplesForTable(tableID, numTuples); + inline void updateNumTuplesByValue(uint64_t numTuples) { + tablesStatistics->updateNumTuplesByValue(tableID, numTuples); } - virtual void read(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* inNodeIDVector, - const std::vector& outputVectors) = 0; + virtual void read(transaction::Transaction* transaction, TableReadState& readState) = 0; + + virtual void insert(transaction::Transaction* transaction, TableInsertState& insertState) = 0; + virtual void update(transaction::Transaction* transaction, TableUpdateState& updateState) = 0; + virtual void delete_(transaction::Transaction* transaction, TableDeleteState& deleteState) = 0; virtual void addColumn(transaction::Transaction* transaction, const catalog::Property& property, common::ValueVector* defaultValueVector) = 0; virtual void dropColumn(common::column_id_t columnID) = 0; virtual void prepareCommit(transaction::Transaction* transaction, LocalTable* localTable) = 0; - virtual void prepareRollback(LocalTableData* localTable) = 0; + // For metadata-only updates + virtual void prepareCommit() = 0; + virtual void prepareRollback(LocalTable* localTable) = 0; virtual void checkpointInMemory() = 0; virtual void rollbackInMemory() = 0; diff --git a/src/include/storage/store/table_data.h b/src/include/storage/store/table_data.h index 13f3cc80b65..3d1cb9c1893 100644 --- a/src/include/storage/store/table_data.h +++ b/src/include/storage/store/table_data.h @@ -1,13 +1,18 @@ #pragma once +#include "storage/store/chunked_node_group.h" #include "storage/store/column.h" -#include "storage/store/node_group.h" namespace kuzu { +namespace catalog { +class TableCatalogEntry; +class Property; +} // namespace catalog + namespace storage { -struct TableReadState { - virtual ~TableReadState() = default; +struct TableDataReadState { + virtual ~TableDataReadState() = default; std::vector columnIDs; }; @@ -17,14 +22,14 @@ class TableData { public: virtual ~TableData() = default; - virtual void scan(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* nodeIDVector, + virtual void scan(transaction::Transaction* transaction, TableDataReadState& readState, + const common::ValueVector& nodeIDVector, const std::vector& outputVectors) = 0; - virtual void lookup(transaction::Transaction* transaction, TableReadState& readState, - common::ValueVector* nodeIDVector, + virtual void lookup(transaction::Transaction* transaction, TableDataReadState& readState, + const common::ValueVector& nodeIDVector, const std::vector& outputVectors) = 0; - virtual void append(NodeGroup* nodeGroup) = 0; + virtual void append(ChunkedNodeGroup* nodeGroup) = 0; inline void dropColumn(common::column_id_t columnID) { columns.erase(columns.begin() + columnID); @@ -35,15 +40,17 @@ class TableData { TablesStatistics* tableStats); inline common::vector_idx_t getNumColumns() const { return columns.size(); } - inline virtual Column* getColumn(common::column_id_t columnID) { - KU_ASSERT(columnID < columns.size()); + inline Column* getColumn(common::column_id_t columnID) { + KU_ASSERT(columnID < columns.size() && columnID != common::INVALID_COLUMN_ID); return columns[columnID].get(); } + inline const std::vector>& getColumns() const { return columns; } - virtual void prepareLocalTableToCommit( - transaction::Transaction* transaction, LocalTableData* localTable) = 0; + virtual void prepareLocalTableToCommit(transaction::Transaction* transaction, + LocalTableData* localTable) = 0; virtual void checkpointInMemory(); virtual void rollbackInMemory(); + virtual void prepareCommit(); virtual common::node_group_idx_t getNumNodeGroups( transaction::Transaction* transaction) const = 0; @@ -51,10 +58,7 @@ class TableData { protected: TableData(BMFileHandle* dataFH, BMFileHandle* metadataFH, catalog::TableCatalogEntry* tableEntry, BufferManager* bufferManager, WAL* wal, - bool enableCompression) - : dataFH{dataFH}, metadataFH{metadataFH}, tableID{tableEntry->getTableID()}, - tableName{tableEntry->getName()}, bufferManager{bufferManager}, wal{wal}, - enableCompression{enableCompression} {} + bool enableCompression); protected: BMFileHandle* dataFH; diff --git a/src/include/storage/store/var_list_column.h b/src/include/storage/store/var_list_column.h deleted file mode 100644 index 9fc7cdcb420..00000000000 --- a/src/include/storage/store/var_list_column.h +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once - -#include "column.h" - -// List is a nested data type which is stored as two chunks: -// 1. Offset column (type: INT64). Using offset to partition the data column into multiple lists. -// 2. Data column. Stores the actual data of the list. -// Similar to other data types, nulls are stored in the null column. -// Example layout for list of INT64: -// Four lists: [4,7,8,12], null, [2, 3], [] -// Offset column: [4, 4, 6, 6] -// data column: [4, 7, 8, 12, 2, 3] -// When reading the data, we firstly read the offset column and utilize the offset column to find -// the data column partitions. -// 1st list(offset 4): Since it is the first element, the start offset is a constant 0, and the end -// offset is 4. Its data is stored at position 0-4 in the data column. -// 2nd list(offset 4): By reading the null column, we know that the 2nd list is null. So we don't -// need to read from the data column. -// 3rd list(offset 6): The start offset is 4(by looking up the offset for the 2nd list), and the end -// offset is 6. Its data is stored at position 4-6 in the data column. -// 4th list(offset 6): The start offset is 6(by looking up the offset for the 3rd list), and the end -// offset is 6. Its data is stored at position 6-6 in the data column (empty list). - -namespace kuzu { -namespace storage { - -struct ListOffsetInfoInStorage { - common::offset_t prevNodeListOffset; - std::vector> offsetVectors; - - ListOffsetInfoInStorage(common::offset_t prevNodeListOffset, - std::vector> offsetVectors) - : prevNodeListOffset{prevNodeListOffset}, offsetVectors{std::move(offsetVectors)} {} - - common::offset_t getListOffset(uint64_t nodePos) const; - - inline uint64_t getListLength(uint64_t nodePos) const { - KU_ASSERT(getListOffset(nodePos + 1) >= getListOffset(nodePos)); - return getListOffset(nodePos + 1) - getListOffset(nodePos); - } -}; - -class VarListColumn : public Column { - friend class VarListLocalColumn; - -public: - VarListColumn(std::string name, common::LogicalType dataType, - const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, - BufferManager* bufferManager, WAL* wal, transaction::Transaction* transaction, - RWPropertyStats propertyStatistics, bool enableCompression); - - void scan(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, - common::offset_t startOffsetInGroup, common::offset_t endOffsetInGroup, - common::ValueVector* resultVector, uint64_t offsetInVector = 0) final; - - void scan(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, - ColumnChunk* columnChunk, common::offset_t startOffset = 0, - common::offset_t endOffset = common::INVALID_OFFSET) final; - - inline Column* getDataColumn() { return dataColumn.get(); } - -protected: - void scanInternal(transaction::Transaction* transaction, common::ValueVector* nodeIDVector, - common::ValueVector* resultVector) final; - - void lookupValue(transaction::Transaction* transaction, common::offset_t nodeOffset, - common::ValueVector* resultVector, uint32_t posInVector) final; - - void append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) override; - -private: - inline common::offset_t readListOffsetInStorage(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInNodeGroup) { - return offsetInNodeGroup == 0 ? - 0 : - readOffset(transaction, nodeGroupIdx, offsetInNodeGroup - 1); - } - - void scanUnfiltered(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, common::ValueVector* resultVector, - const ListOffsetInfoInStorage& listOffsetInfoInStorage); - void scanFiltered(transaction::Transaction* transaction, common::node_group_idx_t nodeGroupIdx, - common::ValueVector* offsetVector, const ListOffsetInfoInStorage& listOffsetInfoInStorage); - - inline bool canCommitInPlace(transaction::Transaction* /*transaction*/, - common::node_group_idx_t /*nodeGroupIdx*/, LocalVectorCollection* /*localChunk*/, - const offset_to_row_idx_t& /*insertInfo*/, - const offset_to_row_idx_t& /*updateInfo*/) override { - // Always perform out-of-place commit for VAR_LIST columns. - return false; - } - inline bool canCommitInPlace(transaction::Transaction* /*transaction*/, - common::node_group_idx_t /*nodeGroupIdx*/, - const std::vector& /*dstOffsets*/, ColumnChunk* /*chunk*/, - common::offset_t /*startOffset*/) override { - // Always perform out-of-place commit for VAR_LIST columns. - return false; - } - - void checkpointInMemory() final; - void rollbackInMemory() final; - - common::offset_t readOffset(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, common::offset_t offsetInNodeGroup); - ListOffsetInfoInStorage getListOffsetInfoInStorage(transaction::Transaction* transaction, - common::node_group_idx_t nodeGroupIdx, common::offset_t startOffsetInNodeGroup, - common::offset_t endOffsetInNodeGroup, - const std::shared_ptr& state); - -private: - std::unique_ptr dataColumn; -}; - -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/store/var_list_column_chunk.h b/src/include/storage/store/var_list_column_chunk.h deleted file mode 100644 index bc2c9986100..00000000000 --- a/src/include/storage/store/var_list_column_chunk.h +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include "storage/store/column_chunk.h" - -namespace kuzu { -namespace storage { - -// TODO(Guodong): Let's simplify the data structure here by getting rid of this class. -struct VarListDataColumnChunk { - std::unique_ptr dataColumnChunk; - uint64_t capacity; - - explicit VarListDataColumnChunk(std::unique_ptr dataChunk) - : dataColumnChunk{std::move(dataChunk)}, capacity{this->dataColumnChunk->capacity} {} - - void reset() const; - - void resizeBuffer(uint64_t numValues); - - inline void append(common::ValueVector* dataVector) const { - dataColumnChunk->append(dataVector); - } - - inline uint64_t getNumValues() const { return dataColumnChunk->getNumValues(); } -}; - -class VarListColumnChunk : public ColumnChunk { - -public: - VarListColumnChunk(common::LogicalType dataType, uint64_t capacity, bool enableCompression); - - inline ColumnChunk* getDataColumnChunk() const { - return varListDataColumnChunk->dataColumnChunk.get(); - } - - void resetToEmpty() final; - - void append(common::ValueVector* vector) final; - // Note: `write` assumes that no `append` will be called afterward. - void write(common::ValueVector* vector, common::offset_t offsetInVector, - common::offset_t offsetInChunk) final; - void write(common::ValueVector* valueVector, common::ValueVector* offsetInChunkVector, - bool isCSR) final; - void write(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, - common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) override; - void copy(ColumnChunk* srcChunk, common::offset_t srcOffsetInChunk, - common::offset_t dstOffsetInChunk, common::offset_t numValuesToCopy) final; - - inline void resizeDataColumnChunk(uint64_t numValues) { - varListDataColumnChunk->resizeBuffer(numValues); - } - - void finalize() final; - - inline common::offset_t getListOffset(common::offset_t offset) const { - return offset == 0 ? 0 : getValue(offset - 1); - } - -protected: - void copyListValues(const common::list_entry_t& entry, common::ValueVector* dataVector); - -private: - void append(ColumnChunk* other, common::offset_t startPosInOtherChunk, - uint32_t numValuesToAppend) final; - - inline void initializeIndices() { - indicesColumnChunk = ColumnChunkFactory::createColumnChunk( - *common::LogicalType::INT64(), false /*enableCompression*/, capacity); - indicesColumnChunk->getNullChunk()->resetToAllNull(); - for (auto i = 0u; i < numValues; i++) { - indicesColumnChunk->setValue(i, i); - indicesColumnChunk->getNullChunk()->setNull(i, nullChunk->isNull(i)); - } - indicesColumnChunk->setNumValues(numValues); - } - inline uint64_t getListLen(common::offset_t offset) const { - return getListOffset(offset + 1) - getListOffset(offset); - } - - void resetFromOtherChunk(VarListColumnChunk* other); - void appendNullList(); - -protected: - std::unique_ptr varListDataColumnChunk; - // The following is needed to write var list to random positions in the column chunk. - // We first append var list to the end of the column chunk. Then use indicesColumnChunk to track - // where each var list data is inside the column chunk. - // `needFinalize` is set to true whenever `write` is called. - // During `finalize`, the whole column chunk will be re-written according to indices. - bool needFinalize; - std::unique_ptr indicesColumnChunk; -}; - -} // namespace storage -} // namespace kuzu diff --git a/src/include/storage/wal/wal.h b/src/include/storage/wal/wal.h index 042c97cb809..ba08f65cf56 100644 --- a/src/include/storage/wal/wal.h +++ b/src/include/storage/wal/wal.h @@ -5,10 +5,6 @@ #include "storage/buffer_manager/buffer_manager.h" #include "storage/wal/wal_record.h" -namespace spdlog { -class logger; -} - namespace kuzu { namespace storage { @@ -90,11 +86,11 @@ class WAL : public BaseWALAndWALIterator { return make_unique(fileHandle, mtx); } - common::page_idx_t logPageUpdateRecord( - DBFileID dbFileID, common::page_idx_t pageIdxInOriginalFile); + common::page_idx_t logPageUpdateRecord(DBFileID dbFileID, + common::page_idx_t pageIdxInOriginalFile); - common::page_idx_t logPageInsertRecord( - DBFileID dbFileID, common::page_idx_t pageIdxInOriginalFile); + common::page_idx_t logPageInsertRecord(DBFileID dbFileID, + common::page_idx_t pageIdxInOriginalFile); void logCommit(uint64_t transactionID); @@ -102,22 +98,16 @@ class WAL : public BaseWALAndWALIterator { void logCatalogRecord(); - void logCreateNodeTableRecord(common::table_id_t tableID); - void logCreateRelTableRecord(common::table_id_t tableID); - void logRdfGraphRecord(common::table_id_t rdfGraphID, common::table_id_t resourceTableID, + void logCreateTableRecord(common::table_id_t tableID, common::TableType tableType); + void logCreateRdfGraphRecord(common::table_id_t rdfGraphID, common::table_id_t resourceTableID, common::table_id_t literalTableID, common::table_id_t resourceTripleTableID, common::table_id_t literalTripleTableID); - - void logOverflowFileNextBytePosRecord(DBFileID dbFileID, uint64_t prevNextByteToWriteTo); - - void logCopyTableRecord(common::table_id_t tableID); - void logDropTableRecord(common::table_id_t tableID); - void logDropPropertyRecord(common::table_id_t tableID, common::property_id_t propertyID); - void logAddPropertyRecord(common::table_id_t tableID, common::property_id_t propertyID); + void logCopyTableRecord(common::table_id_t tableID); + // Removes the contents of WAL file. void clearWAL(); @@ -157,7 +147,6 @@ class WAL : public BaseWALAndWALIterator { // Node/Rel tables that might have changes to their in-memory data structures that need to be // committed/rolled back accordingly during the wal replaying. std::unordered_set updatedTables; - std::shared_ptr logger; std::string directory; std::mutex mtx; BufferManager& bufferManager; diff --git a/src/include/storage/wal/wal_record.h b/src/include/storage/wal/wal_record.h index ef11cd24310..e544baa318e 100644 --- a/src/include/storage/wal/wal_record.h +++ b/src/include/storage/wal/wal_record.h @@ -3,6 +3,7 @@ #include "common/enums/table_type.h" #include "common/types/internal_id_t.h" #include "common/types/types.h" +#include "function/hash/hash_functions.h" namespace kuzu { namespace storage { @@ -51,9 +52,6 @@ enum class WALRecordType : uint8_t { CREATE_TABLE_RECORD = 6, CREATE_REL_TABLE_GROUP_RECORD = 7, CREATE_RDF_GRAPH_RECORD = 8, - // Records the nextBytePosToWriteTo field's last value before the write trx started. This is - // used when rolling back to restore this value. - OVERFLOW_FILE_NEXT_BYTE_POS_RECORD = 17, COPY_TABLE_RECORD = 19, DROP_TABLE_RECORD = 20, DROP_PROPERTY_RECORD = 21, @@ -71,8 +69,8 @@ struct PageUpdateOrInsertRecord { PageUpdateOrInsertRecord() = default; - PageUpdateOrInsertRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL, bool isInsert) + PageUpdateOrInsertRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL, bool isInsert) : dbFileID{dbFileID}, pageIdxInOriginalFile{pageIdxInOriginalFile}, pageIdxInWAL{pageIdxInWAL}, isInsert{isInsert} {} @@ -120,8 +118,8 @@ struct RdfGraphRecord { CreateTableRecord literalTripleTableRecord) : tableID{tableID}, resourceTableRecord{resourceTableRecord}, literalTableRecord{literalTableRecord}, - resourceTripleTableRecord{resourceTripleTableRecord}, literalTripleTableRecord{ - literalTripleTableRecord} {} + resourceTripleTableRecord{resourceTripleTableRecord}, + literalTripleTableRecord{literalTripleTableRecord} {} inline bool operator==(const RdfGraphRecord& rhs) const { return tableID == rhs.tableID && resourceTableRecord == rhs.resourceTableRecord && @@ -131,20 +129,6 @@ struct RdfGraphRecord { } }; -struct DiskOverflowFileNextBytePosRecord { - DBFileID dbFileID; - uint64_t prevNextBytePosToWriteTo; - - DiskOverflowFileNextBytePosRecord() = default; - - DiskOverflowFileNextBytePosRecord(DBFileID dbFileID, uint64_t prevNextByteToWriteTo) - : dbFileID{dbFileID}, prevNextBytePosToWriteTo{prevNextByteToWriteTo} {} - - inline bool operator==(const DiskOverflowFileNextBytePosRecord& rhs) const { - return dbFileID == rhs.dbFileID && prevNextBytePosToWriteTo == rhs.prevNextBytePosToWriteTo; - } -}; - struct CopyTableRecord { common::table_id_t tableID; @@ -213,7 +197,6 @@ struct WALRecord { CommitRecord commitRecord; CreateTableRecord createTableRecord; RdfGraphRecord rdfGraphRecord; - DiskOverflowFileNextBytePosRecord diskOverflowFileNextBytePosRecord; CopyTableRecord copyTableRecord; TableStatisticsRecord tableStatisticsRecord; DropTableRecord dropTableRecord; @@ -223,10 +206,10 @@ struct WALRecord { bool operator==(const WALRecord& rhs) const; - static WALRecord newPageUpdateRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL); - static WALRecord newPageInsertRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL); + static WALRecord newPageUpdateRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL); + static WALRecord newPageInsertRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL); static WALRecord newCommitRecord(uint64_t transactionID); static WALRecord newTableStatisticsRecord(bool isNodeTable); static WALRecord newCatalogRecord(); @@ -234,23 +217,34 @@ struct WALRecord { static WALRecord newRdfGraphRecord(common::table_id_t rdfGraphID, common::table_id_t resourceTableID, common::table_id_t literalTableID, common::table_id_t resourceTripleTableID, common::table_id_t literalTripleTableID); - static WALRecord newOverflowFileNextBytePosRecord( - DBFileID dbFileID, uint64_t prevNextByteToWriteTo_); static WALRecord newCopyTableRecord(common::table_id_t tableID); static WALRecord newDropTableRecord(common::table_id_t tableID); - static WALRecord newDropPropertyRecord( - common::table_id_t tableID, common::property_id_t propertyID); - static WALRecord newAddPropertyRecord( - common::table_id_t tableID, common::property_id_t propertyID); + static WALRecord newDropPropertyRecord(common::table_id_t tableID, + common::property_id_t propertyID); + static WALRecord newAddPropertyRecord(common::table_id_t tableID, + common::property_id_t propertyID); static void constructWALRecordFromBytes(WALRecord& retVal, uint8_t* bytes, uint64_t& offset); // This functions assumes that the caller ensures there is enough space in the bytes pointer // to write the record. This should be checked by calling numBytesToWrite. void writeWALRecordToBytes(uint8_t* bytes, uint64_t& offset) const; private: - static WALRecord newPageInsertOrUpdateRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL, bool isInsert); + static WALRecord newPageInsertOrUpdateRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL, bool isInsert); }; } // namespace storage } // namespace kuzu + +namespace std { +template<> +struct hash { + size_t operator()(const kuzu::storage::DBFileID& fileId) const { + auto dbFileTypeHash = std::hash()(static_cast(fileId.dbFileType)); + auto isOverflowHash = std::hash()(fileId.isOverflow); + auto nodeIndexIDHash = std::hash()(fileId.nodeIndexID.tableID); + return kuzu::function::combineHashScalar(dbFileTypeHash, + kuzu::function::combineHashScalar(isOverflowHash, nodeIndexIDHash)); + } +}; +} // namespace std diff --git a/src/include/storage/wal_replayer.h b/src/include/storage/wal_replayer.h index 6be113cb76e..53a729a2672 100644 --- a/src/include/storage/wal_replayer.h +++ b/src/include/storage/wal_replayer.h @@ -6,10 +6,6 @@ #include "storage/wal/wal.h" #include "storage/wal/wal_record.h" -namespace spdlog { -class logger; -} - namespace kuzu { namespace storage { @@ -27,22 +23,23 @@ class WALReplayer { private: void init(); - void replayWALRecord(WALRecord& walRecord); - void replayPageUpdateOrInsertRecord(const WALRecord& walRecord); + void replayWALRecord(WALRecord& walRecord, + std::unordered_map>& fileCache); + void replayPageUpdateOrInsertRecord(const WALRecord& walRecord, + std::unordered_map>& fileCache); void replayTableStatisticsRecord(const WALRecord& walRecord); void replayCatalogRecord(); void replayCreateTableRecord(const WALRecord& walRecord); void replayRdfGraphRecord(const WALRecord& walRecord); - void replayOverflowFileNextBytePosRecord(const WALRecord& walRecord); void replayCopyTableRecord(const WALRecord& walRecord); void replayDropTableRecord(const WALRecord& walRecord); void replayDropPropertyRecord(const WALRecord& walRecord); void replayAddPropertyRecord(const WALRecord& walRecord); - void checkpointOrRollbackVersionedFileHandleAndBufferManager( - const WALRecord& walRecord, const DBFileID& dbFileID); - void truncateFileIfInsertion( - BMFileHandle* fileHandle, const PageUpdateOrInsertRecord& pageInsertOrUpdateRecord); + void checkpointOrRollbackVersionedFileHandleAndBufferManager(const WALRecord& walRecord, + const DBFileID& dbFileID); + void truncateFileIfInsertion(BMFileHandle* fileHandle, + const PageUpdateOrInsertRecord& pageInsertOrUpdateRecord); BMFileHandle* getVersionedFileHandleIfWALVersionAndBMShouldBeCleared(const DBFileID& dbFileID); std::unique_ptr getCatalogForRecovery(common::FileVersionType dbFileType); diff --git a/src/include/storage/wal_replayer_utils.h b/src/include/storage/wal_replayer_utils.h index 5c7718713f9..cddcdb2a3bb 100644 --- a/src/include/storage/wal_replayer_utils.h +++ b/src/include/storage/wal_replayer_utils.h @@ -19,8 +19,8 @@ namespace storage { class WALReplayerUtils { public: - static void removeHashIndexFile( - common::VirtualFileSystem* vfs, common::table_id_t tableID, const std::string& directory); + static void removeHashIndexFile(common::VirtualFileSystem* vfs, common::table_id_t tableID, + const std::string& directory); // Create empty hash index file for the new node table. static void createEmptyHashIndexFiles(catalog::NodeTableCatalogEntry* nodeTableEntry, diff --git a/src/include/transaction/transaction.h b/src/include/transaction/transaction.h index 2088ffb457a..dd97c4e95c8 100644 --- a/src/include/transaction/transaction.h +++ b/src/include/transaction/transaction.h @@ -5,9 +5,11 @@ #include "storage/local_storage/local_storage.h" namespace kuzu { +namespace main { +class ClientContext; +} // namespace main namespace storage { class LocalStorage; -class MemoryManager; } // namespace storage namespace transaction { class TransactionManager; @@ -19,9 +21,10 @@ class Transaction { friend class TransactionManager; public: - Transaction(TransactionType transactionType, uint64_t transactionID, storage::MemoryManager* mm) + Transaction(main::ClientContext& clientContext, TransactionType transactionType, + uint64_t transactionID) : type{transactionType}, ID{transactionID} { - localStorage = std::make_unique(mm); + localStorage = std::make_unique(clientContext); } constexpr explicit Transaction(TransactionType transactionType) noexcept diff --git a/src/include/transaction/transaction_context.h b/src/include/transaction/transaction_context.h index 4d3f367e11a..05f1549e44e 100644 --- a/src/include/transaction/transaction_context.h +++ b/src/include/transaction/transaction_context.h @@ -4,7 +4,7 @@ namespace kuzu { namespace main { -class Database; +class ClientContext; } namespace transaction { @@ -29,7 +29,7 @@ enum class TransactionMode : uint8_t { AUTO = 0, MANUAL = 1 }; class TransactionContext { public: - explicit TransactionContext(main::Database* database); + explicit TransactionContext(main::ClientContext& clientContext); ~TransactionContext(); inline bool isAutoTransaction() const { return mode == TransactionMode::AUTO; } @@ -57,7 +57,7 @@ class TransactionContext { private: std::mutex mtx; - main::Database* database; + main::ClientContext& clientContext; TransactionMode mode; std::unique_ptr activeTransaction; }; diff --git a/src/include/transaction/transaction_manager.h b/src/include/transaction/transaction_manager.h index eea9a340b9c..7e04f66e050 100644 --- a/src/include/transaction/transaction_manager.h +++ b/src/include/transaction/transaction_manager.h @@ -10,16 +10,18 @@ using lock_t = std::unique_lock; namespace kuzu { +namespace main { +class ClientContext; +} // namespace main namespace transaction { class TransactionManager { public: - explicit TransactionManager(storage::WAL& wal, storage::MemoryManager* mm) - : wal{wal}, mm{mm}, activeWriteTransactionID{INT64_MAX}, lastTransactionID{0}, lastCommitID{ - 0} {}; - std::unique_ptr beginWriteTransaction(); - std::unique_ptr beginReadOnlyTransaction(); + explicit TransactionManager(storage::WAL& wal) + : wal{wal}, activeWriteTransactionID{INT64_MAX}, lastTransactionID{0}, lastCommitID{0} {}; + std::unique_ptr beginWriteTransaction(main::ClientContext& clientContext); + std::unique_ptr beginReadOnlyTransaction(main::ClientContext& clientContext); void commit(Transaction* transaction); void commitButKeepActiveWriteTransaction(Transaction* transaction); void manuallyClearActiveWriteTransaction(Transaction* transaction); @@ -61,7 +63,6 @@ class TransactionManager { private: storage::WAL& wal; - storage::MemoryManager* mm; uint64_t activeWriteTransactionID; diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index 5d9049d1433..20e628f67dc 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(kuzu_main client_context.cpp connection.cpp database.cpp + database_manager.cpp plan_printer.cpp prepared_statement.cpp query_result.cpp diff --git a/src/main/client_context.cpp b/src/main/client_context.cpp index 87d2e63b9b6..784713f1ea2 100644 --- a/src/main/client_context.cpp +++ b/src/main/client_context.cpp @@ -3,7 +3,6 @@ #include #include "binder/binder.h" -#include "common/constants.h" #include "common/exception/connection.h" #include "common/exception/runtime.h" #include "common/random_engine.h" @@ -18,6 +17,7 @@ #include "planner/planner.h" #include "processor/plan_mapper.h" #include "processor/processor.h" +#include "storage/storage_manager.h" #include "transaction/transaction_context.h" #if defined(_WIN32) @@ -42,27 +42,55 @@ void ActiveQuery::reset() { timer = Timer(); } -ClientContext::ClientContext(Database* database) - : numThreadsForExecution{database->systemConfig.maxNumThreads}, - timeoutInMS{ClientContextConstants::TIMEOUT_IN_MS}, - varLengthExtendMaxDepth{DEFAULT_VAR_LENGTH_EXTEND_MAX_DEPTH}, - enableSemiMask{DEFAULT_ENABLE_SEMI_MASK}, database{database} { - transactionContext = std::make_unique(database); +ClientContext::ClientContext(Database* database) : database{database} { + progressBar = std::make_unique(); + transactionContext = std::make_unique(*this); randomEngine = std::make_unique(); - fileSearchPath = ""; #if defined(_WIN32) - homeDirectory = getEnvVariable("USERPROFILE"); + config.homeDirectory = getEnvVariable("USERPROFILE"); #else - homeDirectory = getEnvVariable("HOME"); + config.homeDirectory = getEnvVariable("HOME"); #endif + config.fileSearchPath = ""; + config.enableSemiMask = ClientConfigDefault::ENABLE_SEMI_MASK; + config.numThreads = database->systemConfig.maxNumThreads; + config.timeoutInMS = ClientConfigDefault::TIMEOUT_IN_MS; + config.varLengthMaxDepth = ClientConfigDefault::VAR_LENGTH_MAX_DEPTH; + config.enableProgressBar = ClientConfigDefault::ENABLE_PROGRESS_BAR; + config.showProgressAfter = ClientConfigDefault::SHOW_PROGRESS_AFTER; + config.enableMultiCopy = ClientConfigDefault::ENABLE_MULTI_COPY; } -void ClientContext::startTimingIfEnabled() { - if (isTimeOutEnabled()) { +uint64_t ClientContext::getTimeoutRemainingInMS() const { + KU_ASSERT(hasTimeout()); + auto elapsed = activeQuery.timer.getElapsedTimeInMS(); + return elapsed >= config.timeoutInMS ? 0 : config.timeoutInMS - elapsed; +} + +void ClientContext::startTimer() { + if (hasTimeout()) { activeQuery.timer.start(); } } +void ClientContext::setQueryTimeOut(uint64_t timeoutInMS) { + lock_t lck{mtx}; + config.timeoutInMS = timeoutInMS; +} + +uint64_t ClientContext::getQueryTimeOut() const { + return config.timeoutInMS; +} + +void ClientContext::setMaxNumThreadForExec(uint64_t numThreads) { + lock_t lck{mtx}; + config.numThreads = numThreads; +} + +uint64_t ClientContext::getMaxNumThreadForExec() const { + return config.numThreads; +} + Value ClientContext::getCurrentSetting(const std::string& optionName) { auto lowerCaseOptionName = optionName; StringUtils::toLower(lowerCaseOptionName); @@ -91,20 +119,40 @@ TransactionContext* ClientContext::getTransactionContext() const { return transactionContext.get(); } +common::ProgressBar* ClientContext::getProgressBar() const { + return progressBar.get(); +} + +void ClientContext::addScanReplace(function::ScanReplacement scanReplacement) { + scanReplacements.push_back(std::move(scanReplacement)); +} + +std::unique_ptr ClientContext::tryReplace( + const std::string& objectName) const { + for (auto& scanReplacement : scanReplacements) { + auto replaceData = scanReplacement.replaceFunc(objectName); + if (replaceData == nullptr) { + continue; // Fail to replace. + } + return replaceData; + } + return nullptr; +} + void ClientContext::setExtensionOption(std::string name, common::Value value) { StringUtils::toLower(name); extensionOptionValues.insert_or_assign(name, std::move(value)); } -VirtualFileSystem* ClientContext::getVFSUnsafe() const { - return database->vfs.get(); +extension::ExtensionOptions* ClientContext::getExtensionOptions() const { + return database->extensionOptions.get(); } std::string ClientContext::getExtensionDir() const { - return common::stringFormat("{}/.kuzu/extension", homeDirectory); + return common::stringFormat("{}/.kuzu/extension", config.homeDirectory); } -storage::StorageManager* ClientContext::getStorageManager() { +storage::StorageManager* ClientContext::getStorageManager() const { return database->storageManager.get(); } @@ -112,10 +160,18 @@ storage::MemoryManager* ClientContext::getMemoryManager() { return database->memoryManager.get(); } -catalog::Catalog* ClientContext::getCatalog() { +catalog::Catalog* ClientContext::getCatalog() const { return database->catalog.get(); } +VirtualFileSystem* ClientContext::getVFSUnsafe() const { + return database->vfs.get(); +} + +common::RandomEngine* ClientContext::getRandomEngine() { + return randomEngine.get(); +} + std::string ClientContext::getEnvVariable(const std::string& name) { #if defined(_WIN32) auto envValue = common::WindowsUtils::utf8ToUnicode(name.c_str()); @@ -133,22 +189,34 @@ std::string ClientContext::getEnvVariable(const std::string& name) { #endif } -void ClientContext::setMaxNumThreadForExec(uint64_t numThreads) { - numThreadsForExecution = numThreads; -} - -uint64_t ClientContext::getMaxNumThreadForExec() { +std::unique_ptr ClientContext::prepare(std::string_view query) { + auto preparedStatement = std::unique_ptr(); + if (query.empty()) { + return preparedStatementWithError("Connection Exception: Query is empty."); + } std::unique_lock lck{mtx}; - return numThreadsForExecution; + auto parsedStatements = std::vector>(); + try { + parsedStatements = Parser::parseQuery(query); + } catch (std::exception& exception) { + return preparedStatementWithError(exception.what()); + } + if (parsedStatements.size() > 1) { + return preparedStatementWithError( + "Connection Exception: We do not support prepare multiple statements."); + } + return prepareNoLock(parsedStatements[0]); } -std::unique_ptr ClientContext::prepare(std::string_view query) { +std::unique_ptr ClientContext::prepareTest(std::string_view query) { auto preparedStatement = std::unique_ptr(); std::unique_lock lck{mtx}; - auto parsedStatements = std::vector>(); + auto parsedStatements = std::vector>(); try { - parsedStatements = parseQuery(query); - } catch (std::exception& exception) { return preparedStatementWithError(exception.what()); } + parsedStatements = Parser::parseQuery(query); + } catch (std::exception& exception) { + return preparedStatementWithError(exception.what()); + } if (parsedStatements.size() > 1) { return preparedStatementWithError( "Connection Exception: We do not support prepare multiple statements."); @@ -156,30 +224,33 @@ std::unique_ptr ClientContext::prepare(std::string_view query if (parsedStatements.empty()) { return preparedStatementWithError("Connection Exception: Query is empty."); } - return prepareNoLock(parsedStatements[0].get()); + return prepareNoLock(parsedStatements[0], false /* enumerate all plans */, "", + false /*requireNewTx*/); } std::unique_ptr ClientContext::query(std::string_view queryStatement) { return query(queryStatement, std::string_view() /*encodedJoin*/, false /*enumerateAllPlans */); } -std::unique_ptr ClientContext::query( - std::string_view query, std::string_view encodedJoin, bool enumerateAllPlans) { +std::unique_ptr ClientContext::query(std::string_view query, + std::string_view encodedJoin, bool enumerateAllPlans) { lock_t lck{mtx}; - // parsing - auto parsedStatements = std::vector>(); - try { - parsedStatements = parseQuery(query); - } catch (std::exception& exception) { return queryResultWithError(exception.what()); } - if (parsedStatements.empty()) { + if (query.empty()) { return queryResultWithError("Connection Exception: Query is empty."); } + auto parsedStatements = std::vector>(); + try { + parsedStatements = Parser::parseQuery(query); + } catch (std::exception& exception) { + return queryResultWithError(exception.what()); + } std::unique_ptr queryResult; QueryResult* lastResult = nullptr; for (auto& statement : parsedStatements) { - auto preparedStatement = prepareNoLock( - statement.get(), enumerateAllPlans /* enumerate all plans */, encodedJoin); - auto currentQueryResult = executeAndAutoCommitIfNecessaryNoLock(preparedStatement.get()); + auto preparedStatement = prepareNoLock(statement, + enumerateAllPlans /* enumerate all plans */, encodedJoin, false /*requireNewTx*/); + auto currentQueryResult = executeAndAutoCommitIfNecessaryNoLock(preparedStatement.get(), 0u, + false /*requiredNexTx*/); if (!lastResult) { // first result of the query queryResult = std::move(currentQueryResult); @@ -197,6 +268,7 @@ std::unique_ptr ClientContext::queryResultWithError(std::string_vie queryResult->success = false; queryResult->errMsg = errMsg; queryResult->nextQueryResult = nullptr; + queryResult->queryResultIterator = QueryResult::QueryResultIterator{queryResult.get()}; return queryResult; } @@ -209,7 +281,9 @@ std::unique_ptr ClientContext::preparedStatementWithError( } std::unique_ptr ClientContext::prepareNoLock( - Statement* parsedStatement, bool enumerateAllPlans, std::string_view encodedJoin) { + std::shared_ptr parsedStatement, bool enumerateAllPlans, + std::string_view encodedJoin, bool requireNewTx, + std::optional>> inputParams) { auto preparedStatement = std::make_unique(); auto compilingTimer = TimeMetric(true /* enable */); compilingTimer.start(); @@ -220,18 +294,8 @@ std::unique_ptr ClientContext::prepareNoLock( if (database->systemConfig.readOnly && !preparedStatement->isReadOnly()) { throw ConnectionException("Cannot execute write operations in a read-only database!"); } - } catch (std::exception& exception) { - preparedStatement->success = false; - preparedStatement->errMsg = exception.what(); - compilingTimer.stop(); - preparedStatement->preparedSummary.compilingTime = compilingTimer.getElapsedTimeMS(); - return preparedStatement; - } - std::unique_ptr executionContext; - std::unique_ptr logicalPlan; - try { - // parsing - if (parsedStatement->getStatementType() != StatementType::TRANSACTION) { + preparedStatement->parsedStatement = parsedStatement; + if (parsedStatement->requireTx()) { if (transactionContext->isAutoTransaction()) { transactionContext->beginAutoTransaction(preparedStatement->readOnly); } else { @@ -244,15 +308,16 @@ std::unique_ptr ClientContext::prepareNoLock( } } // binding - auto binder = Binder(*database->catalog, database->memoryManager.get(), - database->storageManager.get(), database->vfs.get(), this, - database->extensionOptions.get()); + auto binder = Binder(this); + if (inputParams) { + binder.setInputParameters(*inputParams); + } auto boundStatement = binder.bind(*parsedStatement); preparedStatement->parameterMap = binder.getParameterMap(); preparedStatement->statementResult = std::make_unique(boundStatement->getStatementResult()->copy()); // planning - auto planner = Planner(database->catalog.get(), database->storageManager.get()); + auto planner = Planner(this); std::vector> plans; if (enumerateAllPlans) { plans = planner.getAllPlans(*boundStatement); @@ -278,6 +343,9 @@ std::unique_ptr ClientContext::prepareNoLock( } else { preparedStatement->logicalPlans = std::move(plans); } + if (transactionContext->isAutoTransaction() && requireNewTx) { + this->transactionContext->commit(); + } } catch (std::exception& exception) { preparedStatement->success = false; preparedStatement->errMsg = exception.what(); @@ -288,8 +356,8 @@ std::unique_ptr ClientContext::prepareNoLock( return preparedStatement; } -std::vector> ClientContext::parseQuery(std::string_view query) { - std::vector> statements; +std::vector> ClientContext::parseQuery(std::string_view query) { + std::vector> statements; if (query.empty()) { return statements; } @@ -297,16 +365,6 @@ std::vector> ClientContext::parseQuery(std::string_vi return statements; } -void ClientContext::setQueryTimeOut(uint64_t timeoutInMS) { - lock_t lck{mtx}; - this->timeoutInMS = timeoutInMS; -} - -uint64_t ClientContext::getQueryTimeOut() { - lock_t lck{mtx}; - return this->timeoutInMS; -} - std::unique_ptr ClientContext::executeWithParams(PreparedStatement* preparedStatement, std::unordered_map> inputParams) { // NOLINT(performance-unnecessary-value-param): It doesn't make sense to pass @@ -321,7 +379,11 @@ std::unique_ptr ClientContext::executeWithParams(PreparedStatement* std::string errMsg = exception.what(); return queryResultWithError(errMsg); } - return executeAndAutoCommitIfNecessaryNoLock(preparedStatement); + // rebind + KU_ASSERT(preparedStatement->parsedStatement != nullptr); + auto rebindPreparedStatement = prepareNoLock(preparedStatement->parsedStatement, false, "", + false, preparedStatement->parameterMap); + return executeAndAutoCommitIfNecessaryNoLock(rebindPreparedStatement.get(), 0u, false); } void ClientContext::bindParametersNoLock(PreparedStatement* preparedStatement, @@ -332,11 +394,6 @@ void ClientContext::bindParametersNoLock(PreparedStatement* preparedStatement, throw Exception("Parameter " + name + " not found."); } auto expectParam = parameterMap.at(name); - if (*expectParam->getDataType() != *value->getDataType()) { - throw Exception("Parameter " + name + " has data type " + - value->getDataType()->toString() + " but expects " + - expectParam->getDataType()->toString() + "."); - } // The much more natural `parameterMap.at(name) = std::move(v)` fails. // The reason is that other parts of the code rely on the existing Value object to be // modified in-place, not replaced in this map. @@ -345,12 +402,11 @@ void ClientContext::bindParametersNoLock(PreparedStatement* preparedStatement, } std::unique_ptr ClientContext::executeAndAutoCommitIfNecessaryNoLock( - PreparedStatement* preparedStatement, uint32_t planIdx) { + PreparedStatement* preparedStatement, uint32_t planIdx, bool requiredNexTx) { if (!preparedStatement->isSuccess()) { return queryResultWithError(preparedStatement->errMsg); } - if (preparedStatement->preparedSummary.statementType != common::StatementType::TRANSACTION && - this->getTx() == nullptr) { + if (preparedStatement->parsedStatement->requireTx() && requiredNexTx && getTx() == nullptr) { this->transactionContext->beginAutoTransaction(preparedStatement->isReadOnly()); if (!preparedStatement->readOnly) { database->catalog->initCatalogContentForWriteTrxIfNecessary(); @@ -358,9 +414,8 @@ std::unique_ptr ClientContext::executeAndAutoCommitIfNecessaryNoLoc } } this->resetActiveQuery(); - this->startTimingIfEnabled(); - auto mapper = PlanMapper( - *database->storageManager, database->memoryManager.get(), database->catalog.get(), this); + this->startTimer(); + auto mapper = PlanMapper(this); std::unique_ptr physicalPlan; if (preparedStatement->isSuccess()) { try { @@ -399,8 +454,8 @@ std::unique_ptr ClientContext::executeAndAutoCommitIfNecessaryNoLoc } executingTimer.stop(); queryResult->querySummary->executionTime = executingTimer.getElapsedTimeMS(); - queryResult->initResultTableAndIterator( - std::move(resultFT), preparedStatement->statementResult->getColumns()); + queryResult->initResultTableAndIterator(std::move(resultFT), + preparedStatement->statementResult->getColumns()); return queryResult; } @@ -433,23 +488,27 @@ void ClientContext::runQuery(std::string query) { if (transactionContext->hasActiveTransaction()) { transactionContext->commit(); } - auto parsedStatements = std::vector>(); + auto parsedStatements = std::vector>(); try { - parsedStatements = parseQuery(query); - } catch (std::exception& exception) { throw ConnectionException(exception.what()); } + parsedStatements = Parser::parseQuery(query); + } catch (std::exception& exception) { + throw ConnectionException(exception.what()); + } if (parsedStatements.empty()) { throw ConnectionException("Connection Exception: Query is empty."); } try { for (auto& statement : parsedStatements) { - auto preparedStatement = prepareNoLock(statement.get()); + auto preparedStatement = prepareNoLock(statement, false, "", false); auto currentQueryResult = - executeAndAutoCommitIfNecessaryNoLock(preparedStatement.get()); + executeAndAutoCommitIfNecessaryNoLock(preparedStatement.get(), 0u, false); if (!currentQueryResult->isSuccess()) { throw ConnectionException(currentQueryResult->errMsg); } } - } catch (std::exception& exception) { throw ConnectionException(exception.what()); } + } catch (std::exception& exception) { + throw ConnectionException(exception.what()); + } return; } } // namespace main diff --git a/src/main/connection.cpp b/src/main/connection.cpp index 320a363cc58..8b39398b1b5 100644 --- a/src/main/connection.cpp +++ b/src/main/connection.cpp @@ -39,8 +39,8 @@ std::unique_ptr Connection::query(std::string_view queryStatement) return clientContext->query(queryStatement); } -std::unique_ptr Connection::query( - std::string_view query, std::string_view encodedJoin, bool enumerateAllPlans) { +std::unique_ptr Connection::query(std::string_view query, std::string_view encodedJoin, + bool enumerateAllPlans) { return clientContext->query(query, encodedJoin, enumerateAllPlans); } @@ -53,14 +53,11 @@ std::unique_ptr Connection::preparedStatementWithError(std::s } std::unique_ptr Connection::prepareNoLock( - Statement* parsedStatement, bool enumerateAllPlans, std::string_view encodedJoin) { + std::shared_ptr parsedStatement, bool enumerateAllPlans, + std::string_view encodedJoin) { return clientContext->prepareNoLock(parsedStatement, enumerateAllPlans, encodedJoin); } -std::vector> Connection::parseQuery(std::string_view query) { - return clientContext->parseQuery(query); -} - void Connection::interrupt() { clientContext->interrupt(); } diff --git a/src/main/database.cpp b/src/main/database.cpp index 7a5bc110800..77720645d23 100644 --- a/src/main/database.cpp +++ b/src/main/database.cpp @@ -1,5 +1,8 @@ #include "main/database.h" +#include "common/random_engine.h" +#include "main/database_manager.h" + #if defined(_WIN32) #include #else @@ -15,6 +18,7 @@ #include "main/db_config.h" #include "processor/processor.h" #include "spdlog/spdlog.h" +#include "storage/storage_extension.h" #include "storage/storage_manager.h" #include "storage/wal_replayer.h" #include "transaction/transaction_action.h" @@ -46,9 +50,9 @@ SystemConfig::SystemConfig(uint64_t bufferPoolSize_, uint64_t maxNumThreads, boo // On 32-bit systems or systems with extremely large memory, the buffer pool size may // exceed the maximum size of a VMRegion. In this case, we set the buffer pool size to // 80% of the maximum size of a VMRegion. - bufferPoolSize_ = (uint64_t)std::min( - (double)bufferPoolSize_, BufferPoolConstants::DEFAULT_VM_REGION_MAX_SIZE * - BufferPoolConstants::DEFAULT_PHY_MEM_SIZE_RATIO_FOR_BM); + bufferPoolSize_ = (uint64_t)std::min((double)bufferPoolSize_, + BufferPoolConstants::DEFAULT_VM_REGION_MAX_SIZE * + BufferPoolConstants::DEFAULT_PHY_MEM_SIZE_RATIO_FOR_BM); } bufferPoolSize = bufferPoolSize_; if (maxNumThreads == 0) { @@ -69,12 +73,17 @@ static void getLockFileFlagsAndType(bool readOnly, bool createNew, int& flags, F } Database::Database(std::string_view databasePath, SystemConfig systemConfig) - : databasePath{databasePath}, systemConfig{systemConfig} { + : systemConfig{systemConfig} { initLoggers(); logger = LoggerUtils::getLogger(LoggerConstants::LoggerEnum::DATABASE); vfs = std::make_unique(); - bufferManager = std::make_unique( - this->systemConfig.bufferPoolSize, this->systemConfig.maxDBSize); + // To expand a path with home directory(~), we have to pass in a dummy clientContext which + // handles the home directory expansion. + auto clientContext = ClientContext(this); + auto dbPathStr = std::string(databasePath); + this->databasePath = vfs->expandPath(&clientContext, dbPathStr); + bufferManager = std::make_unique(this->systemConfig.bufferPoolSize, + this->systemConfig.maxDBSize); memoryManager = std::make_unique(bufferManager.get(), vfs.get()); queryProcessor = std::make_unique(this->systemConfig.maxNumThreads); initDBDirAndCoreFilesIfNecessary(); @@ -84,9 +93,9 @@ Database::Database(std::string_view databasePath, SystemConfig systemConfig) catalog = std::make_unique(wal.get(), vfs.get()); storageManager = std::make_unique(systemConfig.readOnly, *catalog, *memoryManager, wal.get(), systemConfig.enableCompression, vfs.get()); - transactionManager = - std::make_unique(*wal, memoryManager.get()); + transactionManager = std::make_unique(*wal); extensionOptions = std::make_unique(); + databaseManager = std::make_unique(); } Database::~Database() { @@ -106,8 +115,13 @@ void Database::registerFileSystem(std::unique_ptr fs) { vfs->registerFileSystem(std::move(fs)); } -void Database::addExtensionOption( - std::string name, common::LogicalTypeID type, common::Value defaultValue) { +void Database::registerStorageExtension(std::string name, + std::unique_ptr storageExtension) { + storageExtensions.emplace(std::move(name), std::move(storageExtension)); +} + +void Database::addExtensionOption(std::string name, common::LogicalTypeID type, + common::Value defaultValue) { if (extensionOptions->getExtensionOption(name) != nullptr) { throw ExtensionException{common::stringFormat("Extension option {} already exists.", name)}; } @@ -118,6 +132,15 @@ ExtensionOption* Database::getExtensionOption(std::string name) { return extensionOptions->getExtensionOption(std::move(name)); } +common::case_insensitive_map_t>& +Database::getStorageExtensions() { + return storageExtensions; +} + +DatabaseManager* Database::getDatabaseManagerUnsafe() const { + return databaseManager.get(); +} + void Database::openLockFile() { int flags; FileLockType lock; @@ -138,13 +161,13 @@ void Database::initDBDirAndCoreFilesIfNecessary() { vfs->createDir(databasePath); } openLockFile(); - if (!vfs->fileOrPathExists(StorageUtils::getNodesStatisticsAndDeletedIDsFilePath( - vfs.get(), databasePath, FileVersionType::ORIGINAL))) { - NodesStoreStatsAndDeletedIDs::saveInitialNodesStatisticsAndDeletedIDsToFile( - vfs.get(), databasePath); + if (!vfs->fileOrPathExists(StorageUtils::getNodesStatisticsAndDeletedIDsFilePath(vfs.get(), + databasePath, FileVersionType::ORIGINAL))) { + NodesStoreStatsAndDeletedIDs::saveInitialNodesStatisticsAndDeletedIDsToFile(vfs.get(), + databasePath); } - if (!vfs->fileOrPathExists(StorageUtils::getRelsStatisticsFilePath( - vfs.get(), databasePath, FileVersionType::ORIGINAL))) { + if (!vfs->fileOrPathExists(StorageUtils::getRelsStatisticsFilePath(vfs.get(), databasePath, + FileVersionType::ORIGINAL))) { RelsStoreStats::saveInitialRelsStatisticsToFile(vfs.get(), databasePath); } if (!vfs->fileOrPathExists( @@ -207,8 +230,8 @@ void Database::commit(Transaction* transaction, bool skipCheckpointForTestingRec transactionManager->allowReceivingNewTransactions(); } -void Database::rollback( - transaction::Transaction* transaction, bool skipCheckpointForTestingRecovery) { +void Database::rollback(transaction::Transaction* transaction, + bool skipCheckpointForTestingRecovery) { if (transaction->isReadOnly()) { transactionManager->rollback(transaction); return; @@ -227,8 +250,8 @@ void Database::rollback( void Database::checkpointAndClearWAL(WALReplayMode replayMode) { KU_ASSERT(replayMode == WALReplayMode::COMMIT_CHECKPOINT || replayMode == WALReplayMode::RECOVERY_CHECKPOINT); - auto walReplayer = std::make_unique( - wal.get(), storageManager.get(), bufferManager.get(), catalog.get(), replayMode, vfs.get()); + auto walReplayer = std::make_unique(wal.get(), storageManager.get(), + bufferManager.get(), catalog.get(), replayMode, vfs.get()); walReplayer->replay(); wal->clearWAL(); } diff --git a/src/main/database_manager.cpp b/src/main/database_manager.cpp new file mode 100644 index 00000000000..23dc3d111f7 --- /dev/null +++ b/src/main/database_manager.cpp @@ -0,0 +1,38 @@ +#include "main/database_manager.h" + +#include "common/string_utils.h" + +namespace kuzu { +namespace main { + +void DatabaseManager::registerAttachedDatabase(std::unique_ptr attachedDatabase) { + attachedDatabases.push_back(std::move(attachedDatabase)); +} + +AttachedDatabase* DatabaseManager::getAttachedDatabase(const std::string& name) { + auto upperCaseName = common::StringUtils::getUpper(name); + for (auto& attachedDatabase : attachedDatabases) { + auto attachedDBName = attachedDatabase->getDBName(); + common::StringUtils::toUpper(attachedDBName); + if (attachedDBName == upperCaseName) { + return attachedDatabase.get(); + } + } + return nullptr; +} + +void DatabaseManager::detachDatabase(const std::string& databaseName) { + auto upperCaseName = common::StringUtils::getUpper(databaseName); + for (auto it = attachedDatabases.begin(); it != attachedDatabases.end(); ++it) { + auto attachedDBName = (*it)->getDBName(); + common::StringUtils::toUpper(attachedDBName); + if (attachedDBName == upperCaseName) { + attachedDatabases.erase(it); + return; + } + } + KU_UNREACHABLE; +} + +} // namespace main +} // namespace kuzu diff --git a/src/main/db_config.cpp b/src/main/db_config.cpp index ad567a43206..6a1b1fb7df2 100644 --- a/src/main/db_config.cpp +++ b/src/main/db_config.cpp @@ -14,7 +14,9 @@ namespace main { static ConfigurationOption options[] = { // NOLINT(cert-err58-cpp): GET_CONFIGURATION(ThreadsSetting), GET_CONFIGURATION(TimeoutSetting), GET_CONFIGURATION(VarLengthExtendMaxDepthSetting), GET_CONFIGURATION(EnableSemiMaskSetting), - GET_CONFIGURATION(HomeDirectorySetting), GET_CONFIGURATION(FileSearchPathSetting)}; + GET_CONFIGURATION(HomeDirectorySetting), GET_CONFIGURATION(FileSearchPathSetting), + GET_CONFIGURATION(ProgressBarSetting), GET_CONFIGURATION(ProgressBarTimerSetting), + GET_CONFIGURATION(EnableMultiCopySetting)}; ConfigurationOption* DBConfig::getOptionByName(const std::string& optionName) { auto lOptionName = optionName; diff --git a/src/main/plan_printer.cpp b/src/main/plan_printer.cpp index ae0f4766a0c..44edb54364f 100644 --- a/src/main/plan_printer.cpp +++ b/src/main/plan_printer.cpp @@ -11,8 +11,8 @@ using namespace kuzu::processor; namespace kuzu { namespace main { -OpProfileBox::OpProfileBox( - std::string opName, const std::string& paramsName, std::vector attributes) +OpProfileBox::OpProfileBox(std::string opName, const std::string& paramsName, + std::vector attributes) : opName{std::move(opName)}, attributes{std::move(attributes)} { std::stringstream paramsStream{paramsName}; std::string paramStr = ""; @@ -94,8 +94,8 @@ std::ostringstream OpProfileTree::printPlanToOstream() const { return oss; } -void OpProfileTree::calculateNumRowsAndColsForOp( - PhysicalOperator* op, uint32_t& numRows, uint32_t& numCols) { +void OpProfileTree::calculateNumRowsAndColsForOp(PhysicalOperator* op, uint32_t& numRows, + uint32_t& numCols) { if (!op->getNumChildren()) { numRows = 1; numCols = 1; @@ -123,8 +123,8 @@ uint32_t OpProfileTree::fillOpProfileBoxes(PhysicalOperator* op, uint32_t rowIdx uint32_t colOffset = 0; for (auto i = 0u; i < op->getNumChildren(); i++) { - colOffset += fillOpProfileBoxes( - op->getChild(i), rowIdx + 1, colIdx + colOffset, maxFieldWidth, profiler); + colOffset += fillOpProfileBoxes(op->getChild(i), rowIdx + 1, colIdx + colOffset, + maxFieldWidth, profiler); } return colOffset; } @@ -268,8 +268,8 @@ std::string OpProfileTree::genHorizLine(uint32_t len) { return tableFrame.str(); } -void OpProfileTree::insertOpProfileBox( - uint32_t rowIdx, uint32_t colIdx, std::unique_ptr opProfileBox) { +void OpProfileTree::insertOpProfileBox(uint32_t rowIdx, uint32_t colIdx, + std::unique_ptr opProfileBox) { validateRowIdxAndColIdx(rowIdx, colIdx); opProfileBoxes[rowIdx][colIdx] = std::move(opProfileBox); } @@ -295,8 +295,8 @@ uint32_t OpProfileTree::calculateRowHeight(uint32_t rowIdx) const { for (auto i = 0u; i < opProfileBoxes[rowIdx].size(); i++) { auto opProfileBox = getOpProfileBox(rowIdx, i); if (opProfileBox) { - height = std::max( - height, 2 * opProfileBox->getNumAttributes() + opProfileBox->getNumParams()); + height = std::max(height, + 2 * opProfileBox->getNumAttributes() + opProfileBox->getNumParams()); } } return height + 2; diff --git a/src/main/query_result.cpp b/src/main/query_result.cpp index 1a62e21bd48..6fa17c6ce7d 100644 --- a/src/main/query_result.cpp +++ b/src/main/query_result.cpp @@ -13,8 +13,8 @@ using namespace kuzu::processor; namespace kuzu { namespace main { -std::unique_ptr DataTypeInfo::getInfoForDataType( - const LogicalType& type, const std::string& name) { +std::unique_ptr DataTypeInfo::getInfoForDataType(const LogicalType& type, + const std::string& name) { auto columnTypeInfo = std::make_unique(type.getLogicalTypeID(), name); switch (type.getLogicalTypeID()) { case LogicalTypeID::INTERNAL_ID: { @@ -23,15 +23,15 @@ std::unique_ptr DataTypeInfo::getInfoForDataType( columnTypeInfo->childrenTypesInfo.push_back( std::make_unique(LogicalTypeID::INT64, "tableID")); } break; - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::LIST: { auto parentTypeInfo = columnTypeInfo.get(); - auto childType = VarListType::getChildType(&type); + auto childType = ListType::getChildType(&type); parentTypeInfo->childrenTypesInfo.push_back(getInfoForDataType(*childType, "")); } break; - case LogicalTypeID::FIXED_LIST: { + case LogicalTypeID::ARRAY: { auto parentTypeInfo = columnTypeInfo.get(); - parentTypeInfo->numValuesPerList = FixedListType::getNumValuesInList(&type); - auto childType = FixedListType::getChildType(&type); + parentTypeInfo->fixedNumValues = ArrayType::getNumElements(&type); + auto childType = ArrayType::getChildType(&type); parentTypeInfo->childrenTypesInfo.push_back(getInfoForDataType(*childType, "")); } break; case LogicalTypeID::STRUCT: { @@ -55,6 +55,7 @@ QueryResult::QueryResult(const PreparedSummary& preparedSummary) { querySummary = std::make_unique(); querySummary->setPreparedSummary(preparedSummary); nextQueryResult = nullptr; + queryResultIterator = QueryResultIterator{this}; } QueryResult::~QueryResult() = default; @@ -152,6 +153,21 @@ bool QueryResult::hasNext() const { return iterator->hasNextFlatTuple(); } +bool QueryResult::hasNextQueryResult() const { + if (!queryResultIterator.isEnd()) { + return true; + } + return false; +} + +QueryResult* QueryResult::getNextQueryResult() { + ++queryResultIterator; + if (!queryResultIterator.isEnd()) { + return queryResultIterator.getCurrentResult(); + } + return nullptr; +} + std::shared_ptr QueryResult::getNext() { if (!hasNext()) { throw RuntimeException( @@ -163,16 +179,6 @@ std::shared_ptr QueryResult::getNext() { } std::string QueryResult::toString() { - std::string result; - QueryResultIterator it(this); - while (!it.isEnd()) { - result += it.getCurrentResult()->toSingleQueryString() + "\n"; - ++it; - } - return result; -} - -std::string QueryResult::toSingleQueryString() { std::string result; if (isSuccess()) { // print header diff --git a/src/main/storage_driver.cpp b/src/main/storage_driver.cpp index 56032d4bb68..4e1cefa797d 100644 --- a/src/main/storage_driver.cpp +++ b/src/main/storage_driver.cpp @@ -2,10 +2,15 @@ #include +#include "common/types/types.h" +#include "common/vector/value_vector.h" #include "storage/storage_manager.h" +#include "storage/storage_utils.h" +#include "storage/store/node_table.h" using namespace kuzu::common; using namespace kuzu::transaction; +using namespace kuzu::storage; namespace kuzu { namespace main { @@ -19,7 +24,7 @@ void StorageDriver::scan(const std::string& nodeName, const std::string& propert auto nodeTableID = catalog->getTableID(&DUMMY_READ_TRANSACTION, nodeName); auto propertyID = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, nodeTableID) ->getPropertyID(propertyName); - auto nodeTable = storageManager->getNodeTable(nodeTableID); + auto nodeTable = ku_dynamic_cast(storageManager->getTable(nodeTableID)); auto column = nodeTable->getColumn(propertyID); auto current_buffer = result; std::vector threads; @@ -31,6 +36,8 @@ void StorageDriver::scan(const std::string& nodeName, const std::string& propert threads.emplace_back(&StorageDriver::scanColumn, this, dummyReadOnlyTransaction.get(), column, offsets, sizeToRead, current_buffer); offsets += sizeToRead; + // TODO(Guodong/Xiyang/Chang): StorageDriver should figure numBytesPerValue from logicalType + // and not rely on Column to provide this information. current_buffer += sizeToRead * column->getNumBytesPerValue(); sizeLeft -= sizeToRead; } @@ -43,20 +50,36 @@ uint64_t StorageDriver::getNumNodes(const std::string& nodeName) { auto nodeTableID = catalog->getTableID(&DUMMY_READ_TRANSACTION, nodeName); auto nodeStatistics = storageManager->getNodesStatisticsAndDeletedIDs()->getNodeStatisticsAndDeletedIDs( - nodeTableID); + &DUMMY_READ_TRANSACTION, nodeTableID); return nodeStatistics->getNumTuples(); } uint64_t StorageDriver::getNumRels(const std::string& relName) { auto relTableID = catalog->getTableID(&DUMMY_READ_TRANSACTION, relName); - auto relStatistics = storageManager->getRelsStatistics()->getRelStatistics( - relTableID, Transaction::getDummyReadOnlyTrx().get()); + auto relStatistics = storageManager->getRelsStatistics()->getRelStatistics(relTableID, + Transaction::getDummyReadOnlyTrx().get()); return relStatistics->getNumTuples(); } void StorageDriver::scanColumn(Transaction* transaction, storage::Column* column, offset_t* offsets, size_t size, uint8_t* result) { - column->batchLookup(transaction, offsets, size, result); + auto dataType = column->getDataType(); + if (dataType.getPhysicalType() == PhysicalTypeID::LIST) { + auto resultVector = ValueVector(dataType); + for (auto i = 0u; i < size; ++i) { + auto nodeOffset = offsets[i]; + auto [nodeGroupIdx, offsetInChunk] = + StorageUtils::getNodeGroupIdxAndOffsetInChunk(nodeOffset); + column->scan(transaction, nodeGroupIdx, offsetInChunk, offsetInChunk + 1, &resultVector, + i); + } + auto dataVector = ListVector::getDataVector(&resultVector); + auto dataVectorSize = ListVector::getDataVectorSize(&resultVector); + auto dataChildTypeSize = LogicalTypeUtils::getRowLayoutSize(dataVector->dataType); + memcpy(result, dataVector->getData(), dataVectorSize * dataChildTypeSize); + } else { + column->batchLookup(transaction, offsets, size, result); + } } } // namespace main diff --git a/src/main/version.cpp b/src/main/version.cpp index 440a0c2db23..18212896d19 100644 --- a/src/main/version.cpp +++ b/src/main/version.cpp @@ -1,6 +1,6 @@ #include "main/version.h" -#include "storage/storage_info.h" +#include "storage/storage_version_info.h" namespace kuzu { namespace main { diff --git a/src/optimizer/acc_hash_join_optimizer.cpp b/src/optimizer/acc_hash_join_optimizer.cpp index a629277e32a..a8122f1eff1 100644 --- a/src/optimizer/acc_hash_join_optimizer.cpp +++ b/src/optimizer/acc_hash_join_optimizer.cpp @@ -201,8 +201,8 @@ std::vector HashJoinSIPOptimizer::resolveScanInternal } std::vector -HashJoinSIPOptimizer::resolveShortestPathExtendToApplySemiMask( - const binder::Expression& nodeID, planner::LogicalOperator* root) { +HashJoinSIPOptimizer::resolveShortestPathExtendToApplySemiMask(const binder::Expression& nodeID, + planner::LogicalOperator* root) { std::vector result; auto recursiveJoinCollector = LogicalRecursiveExtendCollector(); recursiveJoinCollector.collect(root); @@ -252,16 +252,16 @@ std::shared_ptr HashJoinSIPOptimizer::appendPathSemiMa auto op = opsToApplySemiMask[0]; KU_ASSERT(op->getOperatorType() == planner::LogicalOperatorType::SCAN_INTERNAL_ID); auto scan = ku_dynamic_cast(op); - auto semiMasker = std::make_shared( - SemiMaskType::PATH, pathExpression, scan->getTableIDs(), opsToApplySemiMask, child); + auto semiMasker = std::make_shared(SemiMaskType::PATH, pathExpression, + scan->getTableIDs(), opsToApplySemiMask, child); semiMasker->computeFlatSchema(); return semiMasker; } std::shared_ptr HashJoinSIPOptimizer::appendAccumulate( std::shared_ptr child) { - auto accumulate = std::make_shared( - AccumulateType::REGULAR, expression_vector{}, std::move(child)); + auto accumulate = std::make_shared(AccumulateType::REGULAR, + expression_vector{}, nullptr /* offset */, std::move(child)); accumulate->computeFlatSchema(); return accumulate; } diff --git a/src/optimizer/agg_key_dependency_optimizer.cpp b/src/optimizer/agg_key_dependency_optimizer.cpp index 04dcd7fbf9e..e027e792e31 100644 --- a/src/optimizer/agg_key_dependency_optimizer.cpp +++ b/src/optimizer/agg_key_dependency_optimizer.cpp @@ -33,9 +33,9 @@ void AggKeyDependencyOptimizer::visitAggregate(planner::LogicalOperator* op) { void AggKeyDependencyOptimizer::visitDistinct(planner::LogicalOperator* op) { auto distinct = (LogicalDistinct*)op; - auto [keys, dependentKeys] = resolveKeysAndDependentKeys(distinct->getKeyExpressions()); - distinct->setKeyExpressions(keys); - distinct->setDependentKeyExpressions(dependentKeys); + auto [keys, dependentKeys] = resolveKeysAndDependentKeys(distinct->getKeys()); + distinct->setKeys(keys); + distinct->setPayloads(dependentKeys); } std::pair diff --git a/src/optimizer/factorization_rewriter.cpp b/src/optimizer/factorization_rewriter.cpp index d18e3ad37e4..007de0c18bc 100644 --- a/src/optimizer/factorization_rewriter.cpp +++ b/src/optimizer/factorization_rewriter.cpp @@ -1,6 +1,7 @@ #include "optimizer/factorization_rewriter.h" #include "binder/expression_visitor.h" +#include "common/cast.h" #include "planner/operator/extend/logical_extend.h" #include "planner/operator/extend/logical_recursive_extend.h" #include "planner/operator/factorization/flatten_resolver.h" @@ -12,6 +13,7 @@ #include "planner/operator/logical_hash_join.h" #include "planner/operator/logical_intersect.h" #include "planner/operator/logical_limit.h" +#include "planner/operator/logical_mark_accmulate.h" #include "planner/operator/logical_order_by.h" #include "planner/operator/logical_projection.h" #include "planner/operator/logical_union.h" @@ -22,6 +24,7 @@ #include "planner/operator/persistent/logical_merge.h" #include "planner/operator/persistent/logical_set.h" +using namespace kuzu::common; using namespace kuzu::binder; using namespace kuzu::planner; @@ -68,8 +71,8 @@ void FactorizationRewriter::visitIntersect(planner::LogicalOperator* op) { for (auto i = 0u; i < intersect->getNumBuilds(); ++i) { auto groupPosToFlatten = intersect->getGroupsPosToFlattenOnBuildSide(i); auto childIdx = i + 1; // skip probe - intersect->setChild( - childIdx, appendFlattens(intersect->getChild(childIdx), groupPosToFlatten)); + intersect->setChild(childIdx, + appendFlattens(intersect->getChild(childIdx), groupPosToFlatten)); } } @@ -84,8 +87,8 @@ void FactorizationRewriter::visitProjection(planner::LogicalOperator* op) { if (hasRandomFunction) { // Fall back to tuple-at-a-time evaluation. auto groupsPos = op->getChild(0)->getSchema()->getGroupsPosInScope(); - auto groupsPosToFlatten = factorization::FlattenAll::getGroupsPosToFlatten( - groupsPos, op->getChild(0)->getSchema()); + auto groupsPosToFlatten = factorization::FlattenAll::getGroupsPosToFlatten(groupsPos, + op->getChild(0)->getSchema()); projection->setChild(0, appendFlattens(projection->getChild(0), groupsPosToFlatten)); } else { for (auto& expression : projection->getExpressionsToProject()) { @@ -104,6 +107,12 @@ void FactorizationRewriter::visitAccumulate(planner::LogicalOperator* op) { accumulate->setChild(0, appendFlattens(accumulate->getChild(0), groupsPosToFlatten)); } +void FactorizationRewriter::visitMarkAccumulate(planner::LogicalOperator* op) { + auto markAccumulate = ku_dynamic_cast(op); + auto groupsPos = markAccumulate->getGroupsPosToFlatten(); + markAccumulate->setChild(0, appendFlattens(markAccumulate->getChild(0), groupsPos)); +} + void FactorizationRewriter::visitAggregate(planner::LogicalOperator* op) { auto aggregate = (LogicalAggregate*)op; auto groupsPosToFlattenForGroupBy = aggregate->getGroupsPosToFlattenForGroupBy(); @@ -154,8 +163,8 @@ void FactorizationRewriter::visitSetNodeProperty(planner::LogicalOperator* op) { auto setNodeProperty = (LogicalSetNodeProperty*)op; for (auto i = 0u; i < setNodeProperty->getInfosRef().size(); ++i) { auto groupsPosToFlatten = setNodeProperty->getGroupsPosToFlatten(i); - setNodeProperty->setChild( - 0, appendFlattens(setNodeProperty->getChild(0), groupsPosToFlatten)); + setNodeProperty->setChild(0, + appendFlattens(setNodeProperty->getChild(0), groupsPosToFlatten)); } } @@ -163,8 +172,8 @@ void FactorizationRewriter::visitSetRelProperty(planner::LogicalOperator* op) { auto setRelProperty = (LogicalSetRelProperty*)op; for (auto i = 0u; i < setRelProperty->getInfosRef().size(); ++i) { auto groupsPosToFlatten = setRelProperty->getGroupsPosToFlatten(i); - setRelProperty->setChild( - 0, appendFlattens(setRelProperty->getChild(0), groupsPosToFlatten)); + setRelProperty->setChild(0, + appendFlattens(setRelProperty->getChild(0), groupsPosToFlatten)); } } diff --git a/src/optimizer/filter_push_down_optimizer.cpp b/src/optimizer/filter_push_down_optimizer.cpp index b9abed2f355..2d47f41b280 100644 --- a/src/optimizer/filter_push_down_optimizer.cpp +++ b/src/optimizer/filter_push_down_optimizer.cpp @@ -86,8 +86,8 @@ std::shared_ptr FilterPushDownOptimizer::visitCrossProductRepla if (joinConditions.empty()) { return finishPushDown(op); } - auto hashJoin = std::make_shared( - joinConditions, JoinType::INNER, op->getChild(0), op->getChild(1)); + auto hashJoin = std::make_shared(joinConditions, JoinType::INNER, + op->getChild(0), op->getChild(1)); hashJoin->setSIP(planner::SidewaysInfoPassing::PROHIBIT); hashJoin->computeFlatSchema(); return hashJoin; @@ -111,8 +111,8 @@ std::shared_ptr FilterPushDownOptimizer::visitScanNode std::vector infos; KU_ASSERT(tableIDs.size() == 1); infos.push_back(IndexLookupInfo(tableIDs[0], nodeID, rhs, rhs->getDataType())); - auto indexScan = std::make_shared( - std::move(infos), std::move(expressionsScan)); + auto indexScan = std::make_shared(std::move(infos), + std::move(expressionsScan)); indexScan->computeFlatSchema(); op->setChild(0, std::move(indexScan)); } else { @@ -182,8 +182,8 @@ std::shared_ptr FilterPushDownOptimizer::appendScanNod if (properties.empty()) { return child; } - auto scanNodeProperty = std::make_shared( - std::move(nodeID), std::move(nodeTableIDs), std::move(properties), std::move(child)); + auto scanNodeProperty = std::make_shared(std::move(nodeID), + std::move(nodeTableIDs), std::move(properties), std::move(child)); scanNodeProperty->computeFlatSchema(); return scanNodeProperty; } diff --git a/src/optimizer/logical_operator_visitor.cpp b/src/optimizer/logical_operator_visitor.cpp index 53b38d24cc8..9cb1e0fb2cf 100644 --- a/src/optimizer/logical_operator_visitor.cpp +++ b/src/optimizer/logical_operator_visitor.cpp @@ -52,6 +52,9 @@ void LogicalOperatorVisitor::visitOperatorSwitch(planner::LogicalOperator* op) { case LogicalOperatorType::ACCUMULATE: { visitAccumulate(op); } break; + case LogicalOperatorType::MARK_ACCUMULATE: { + visitMarkAccumulate(op); + } break; case LogicalOperatorType::DISTINCT: { visitDistinct(op); } break; @@ -85,6 +88,9 @@ void LogicalOperatorVisitor::visitOperatorSwitch(planner::LogicalOperator* op) { case LogicalOperatorType::COPY_TO: { visitCopyTo(op); } break; + case LogicalOperatorType::COPY_FROM: { + visitCopyFrom(op); + } break; default: return; } @@ -138,6 +144,9 @@ std::shared_ptr LogicalOperatorVisitor::visitOperatorR case LogicalOperatorType::ACCUMULATE: { return visitAccumulateReplace(op); } + case LogicalOperatorType::MARK_ACCUMULATE: { + return visitMarkAccumulateReplace(op); + } case LogicalOperatorType::DISTINCT: { return visitDistinctReplace(op); } @@ -171,6 +180,9 @@ std::shared_ptr LogicalOperatorVisitor::visitOperatorR case LogicalOperatorType::COPY_TO: { return visitCopyToReplace(op); } + case LogicalOperatorType::COPY_FROM: { + return visitCopyFromReplace(op); + } default: return op; } diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index c89786f97e3..86d10f3249b 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -31,7 +31,7 @@ void Optimizer::optimize(planner::LogicalPlan* plan, main::ClientContext* client auto projectionPushDownOptimizer = ProjectionPushDownOptimizer(); projectionPushDownOptimizer.rewrite(plan); - if (client->isEnableSemiMask()) { + if (client->getClientConfig()->enableSemiMask) { // HashJoinSIPOptimizer should be applied after optimizers that manipulate hash join. auto hashJoinSIPOptimizer = HashJoinSIPOptimizer(); hashJoinSIPOptimizer.rewrite(plan); diff --git a/src/optimizer/projection_push_down_optimizer.cpp b/src/optimizer/projection_push_down_optimizer.cpp index db1eebb7b9d..a5168939ed7 100644 --- a/src/optimizer/projection_push_down_optimizer.cpp +++ b/src/optimizer/projection_push_down_optimizer.cpp @@ -1,6 +1,7 @@ #include "optimizer/projection_push_down_optimizer.h" #include "binder/expression_visitor.h" +#include "common/cast.h" #include "planner/operator/extend/logical_extend.h" #include "planner/operator/extend/logical_recursive_extend.h" #include "planner/operator/logical_accumulate.h" @@ -10,6 +11,7 @@ #include "planner/operator/logical_order_by.h" #include "planner/operator/logical_projection.h" #include "planner/operator/logical_unwind.h" +#include "planner/operator/persistent/logical_copy_from.h" #include "planner/operator/persistent/logical_delete.h" #include "planner/operator/persistent/logical_insert.h" #include "planner/operator/persistent/logical_merge.h" @@ -64,7 +66,7 @@ void ProjectionPushDownOptimizer::visitAccumulate(planner::LogicalOperator* op) if (accumulate->getAccumulateType() != AccumulateType::REGULAR) { return; } - auto expressionsBeforePruning = accumulate->getExpressionsToAccumulate(); + auto expressionsBeforePruning = accumulate->getPayloads(); auto expressionsAfterPruning = pruneExpressions(expressionsBeforePruning); if (expressionsBeforePruning.size() == expressionsAfterPruning.size()) { return; @@ -154,7 +156,7 @@ void ProjectionPushDownOptimizer::visitOrderBy(planner::LogicalOperator* op) { void ProjectionPushDownOptimizer::visitUnwind(planner::LogicalOperator* op) { auto unwind = (LogicalUnwind*)op; - collectExpressionsInUse(unwind->getExpression()); + collectExpressionsInUse(unwind->getInExpr()); } void ProjectionPushDownOptimizer::visitInsert(planner::LogicalOperator* op) { @@ -198,7 +200,10 @@ void ProjectionPushDownOptimizer::visitDeleteRel(planner::LogicalOperator* op) { // TODO(Xiyang): come back and refactor this after changing insert interface void ProjectionPushDownOptimizer::visitMerge(planner::LogicalOperator* op) { auto merge = (LogicalMerge*)op; - collectExpressionsInUse(merge->getMark()); + if (merge->hasDistinctMark()) { + collectExpressionsInUse(merge->getDistinctMark()); + } + collectExpressionsInUse(merge->getExistenceMark()); for (auto& info : merge->getInsertNodeInfosRef()) { visitInsertInfo(&info); } @@ -251,6 +256,14 @@ void ProjectionPushDownOptimizer::visitSetRelProperty(planner::LogicalOperator* } } +void ProjectionPushDownOptimizer::visitCopyFrom(planner::LogicalOperator* op) { + auto copyFrom = ku_dynamic_cast(op); + for (auto& expr : copyFrom->getInfo()->source->getColumns()) { + collectExpressionsInUse(expr); + } + collectExpressionsInUse(copyFrom->getInfo()->offset); +} + // See comments above this class for how to collect expressions in use. void ProjectionPushDownOptimizer::collectExpressionsInUse( std::shared_ptr expression) { @@ -288,8 +301,8 @@ binder::expression_vector ProjectionPushDownOptimizer::pruneExpressions( return expression_vector{expressionsAfterPruning.begin(), expressionsAfterPruning.end()}; } -void ProjectionPushDownOptimizer::preAppendProjection( - planner::LogicalOperator* op, uint32_t childIdx, binder::expression_vector expressions) { +void ProjectionPushDownOptimizer::preAppendProjection(planner::LogicalOperator* op, + uint32_t childIdx, binder::expression_vector expressions) { auto projection = std::make_shared(std::move(expressions), op->getChild(childIdx)); projection->computeFlatSchema(); diff --git a/src/parser/antlr_parser/kuzu_cypher_parser.cpp b/src/parser/antlr_parser/kuzu_cypher_parser.cpp index 281b7fa6e07..82f11e8ee31 100644 --- a/src/parser/antlr_parser/kuzu_cypher_parser.cpp +++ b/src/parser/antlr_parser/kuzu_cypher_parser.cpp @@ -10,8 +10,8 @@ void KuzuCypherParser::notifyQueryNotConcludeWithReturn(antlr4::Token* startToke notifyErrorListeners(startToken, errorMsg, nullptr); } -void KuzuCypherParser::notifyNodePatternWithoutParentheses( - std::string nodeName, antlr4::Token* startToken) { +void KuzuCypherParser::notifyNodePatternWithoutParentheses(std::string nodeName, + antlr4::Token* startToken) { auto errorMsg = "Parentheses are required to identify nodes in patterns, i.e. (" + nodeName + ")"; notifyErrorListeners(startToken, errorMsg, nullptr); diff --git a/src/parser/antlr_parser/parser_error_listener.cpp b/src/parser/antlr_parser/parser_error_listener.cpp index 845f2667985..7eb9aacb4ba 100644 --- a/src/parser/antlr_parser/parser_error_listener.cpp +++ b/src/parser/antlr_parser/parser_error_listener.cpp @@ -17,8 +17,8 @@ void ParserErrorListener::syntaxError(Recognizer* recognizer, Token* offendingSy throw ParserException(finalError); } -std::string ParserErrorListener::formatUnderLineError( - Recognizer& recognizer, const Token& offendingToken, size_t line, size_t charPositionInLine) { +std::string ParserErrorListener::formatUnderLineError(Recognizer& recognizer, + const Token& offendingToken, size_t line, size_t charPositionInLine) { auto tokens = (CommonTokenStream*)recognizer.getInputStream(); auto input = tokens->getTokenSource()->getInputStream()->toString(); auto errorLine = StringUtils::split(input, "\n")[line - 1]; diff --git a/src/parser/antlr_parser/parser_error_strategy.cpp b/src/parser/antlr_parser/parser_error_strategy.cpp index 055490750b9..b5e4e36d302 100644 --- a/src/parser/antlr_parser/parser_error_strategy.cpp +++ b/src/parser/antlr_parser/parser_error_strategy.cpp @@ -3,8 +3,8 @@ namespace kuzu { namespace parser { -void ParserErrorStrategy::reportNoViableAlternative( - antlr4::Parser* recognizer, const antlr4::NoViableAltException& e) { +void ParserErrorStrategy::reportNoViableAlternative(antlr4::Parser* recognizer, + const antlr4::NoViableAltException& e) { auto tokens = recognizer->getTokenStream(); auto errorMsg = tokens ? diff --git a/src/parser/expression/parsed_case_expression.cpp b/src/parser/expression/parsed_case_expression.cpp index 9276b6bca5e..6c1f381d754 100644 --- a/src/parser/expression/parsed_case_expression.cpp +++ b/src/parser/expression/parsed_case_expression.cpp @@ -27,8 +27,8 @@ std::unique_ptr ParsedCaseExpression::deserialize( deserializer.deserializeVector(caseAlternatives); std::unique_ptr elseExpression; deserializer.deserializeOptionalValue(elseExpression); - return std::make_unique( - std::move(caseExpression), std::move(caseAlternatives), std::move(elseExpression)); + return std::make_unique(std::move(caseExpression), + std::move(caseAlternatives), std::move(elseExpression)); } std::unique_ptr ParsedCaseExpression::copy() const { diff --git a/src/parser/expression/parsed_expression.cpp b/src/parser/expression/parsed_expression.cpp index e3d3c934957..1d1e8187fcc 100644 --- a/src/parser/expression/parsed_expression.cpp +++ b/src/parser/expression/parsed_expression.cpp @@ -15,8 +15,8 @@ using namespace kuzu::common; namespace kuzu { namespace parser { -ParsedExpression::ParsedExpression( - ExpressionType type, std::unique_ptr child, std::string rawName) +ParsedExpression::ParsedExpression(ExpressionType type, std::unique_ptr child, + std::string rawName) : type{type}, rawName{std::move(rawName)} { children.push_back(std::move(child)); } diff --git a/src/parser/parsed_statement_visitor.cpp b/src/parser/parsed_statement_visitor.cpp index 55bbf52219c..957e843f5be 100644 --- a/src/parser/parsed_statement_visitor.cpp +++ b/src/parser/parsed_statement_visitor.cpp @@ -53,6 +53,12 @@ void StatementVisitor::visit(const Statement& statement) { case StatementType::IMPORT_DATABASE: { visitImportDatabase(statement); } break; + case StatementType::ATTACH_DATABASE: { + visitAttachDatabase(statement); + } break; + case StatementType::DETACH_DATABASE: { + visitDetachDatabase(statement); + } break; default: KU_UNREACHABLE; } diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index d0fab07a1f7..ed9f50773e6 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -16,7 +16,7 @@ using namespace antlr4; namespace kuzu { namespace parser { -std::vector> Parser::parseQuery(std::string_view query) { +std::vector> Parser::parseQuery(std::string_view query) { auto inputStream = ANTLRInputStream(query); auto parserErrorListener = ParserErrorListener(); diff --git a/src/parser/transform/CMakeLists.txt b/src/parser/transform/CMakeLists.txt index 5a98ccb7adc..e98fe0caa0f 100644 --- a/src/parser/transform/CMakeLists.txt +++ b/src/parser/transform/CMakeLists.txt @@ -13,7 +13,9 @@ add_library(kuzu_parser_transform transform_transaction.cpp transform_updating_clause.cpp transform_extension.cpp - transform_port_db.cpp) + transform_port_db.cpp + transform_attach_database.cpp + transform_detach_database.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/parser/transform/transform_attach_database.cpp b/src/parser/transform/transform_attach_database.cpp new file mode 100644 index 00000000000..c472b67ea0e --- /dev/null +++ b/src/parser/transform/transform_attach_database.cpp @@ -0,0 +1,20 @@ +#include "parser/attach_database.h" +#include "parser/transformer.h" + +namespace kuzu { +namespace parser { + +std::unique_ptr Transformer::transformAttachDatabase( + CypherParser::KU_AttachDatabaseContext& ctx) { + AttachInfo attachInfo; + attachInfo.dbPath = transformStringLiteral(*ctx.StringLiteral()[0]); + attachInfo.dbAlias = ""; + if (ctx.oC_SchemaName()) { + attachInfo.dbAlias = transformSchemaName(*ctx.oC_SchemaName()); + } + attachInfo.dbType = transformStringLiteral(*ctx.StringLiteral()[1]); + return std::make_unique(std::move(attachInfo)); +} + +} // namespace parser +} // namespace kuzu diff --git a/src/parser/transform/transform_copy.cpp b/src/parser/transform/transform_copy.cpp index 9bf52f9413a..65947143e2c 100644 --- a/src/parser/transform/transform_copy.cpp +++ b/src/parser/transform/transform_copy.cpp @@ -1,4 +1,6 @@ +#include "common/assert.h" #include "parser/copy.h" +#include "parser/scan_source.h" #include "parser/transformer.h" using namespace kuzu::common; @@ -17,9 +19,9 @@ std::unique_ptr Transformer::transformCopyTo(CypherParser::KU_CopyTOC } std::unique_ptr Transformer::transformCopyFrom(CypherParser::KU_CopyFromContext& ctx) { - auto filePaths = transformFilePaths(ctx.kU_FilePaths()->StringLiteral()); + auto source = transformScanSource(*ctx.kU_ScanSource()); auto tableName = transformSchemaName(*ctx.oC_SchemaName()); - auto copyFrom = std::make_unique(std::move(filePaths), std::move(tableName)); + auto copyFrom = std::make_unique(std::move(source), std::move(tableName)); if (ctx.kU_ColumnNames()) { copyFrom->setColumnNames(transformColumnNames(*ctx.kU_ColumnNames())); } @@ -31,9 +33,9 @@ std::unique_ptr Transformer::transformCopyFrom(CypherParser::KU_CopyF std::unique_ptr Transformer::transformCopyFromByColumn( CypherParser::KU_CopyFromByColumnContext& ctx) { - auto filePaths = transformFilePaths(ctx.StringLiteral()); + auto source = std::make_unique(transformFilePaths(ctx.StringLiteral())); auto tableName = transformSchemaName(*ctx.oC_SchemaName()); - auto copyFrom = std::make_unique(std::move(filePaths), std::move(tableName)); + auto copyFrom = std::make_unique(std::move(source), std::move(tableName)); copyFrom->setByColumn(); return copyFrom; } @@ -57,6 +59,22 @@ std::vector Transformer::transformFilePaths( return csvFiles; } +std::unique_ptr Transformer::transformScanSource( + CypherParser::KU_ScanSourceContext& ctx) { + if (ctx.kU_FilePaths()) { + auto filePaths = transformFilePaths(ctx.kU_FilePaths()->StringLiteral()); + return std::make_unique(std::move(filePaths)); + } else if (ctx.oC_Query()) { + auto query = transformQuery(*ctx.oC_Query()); + return std::make_unique(std::move(query)); + } else if (ctx.oC_Variable()) { + auto variable = transformVariable(*ctx.oC_Variable()); + return std::make_unique(std::move(variable)); + } else { + KU_UNREACHABLE; + } +} + parsing_option_t Transformer::transformParsingOptions(CypherParser::KU_ParsingOptionsContext& ctx) { std::unordered_map> copyOptions; for (auto loadOption : ctx.kU_ParsingOption()) { diff --git a/src/parser/transform/transform_ddl.cpp b/src/parser/transform/transform_ddl.cpp index 84fc56ec5d5..86f76de1654 100644 --- a/src/parser/transform/transform_ddl.cpp +++ b/src/parser/transform/transform_ddl.cpp @@ -66,8 +66,8 @@ std::unique_ptr Transformer::transformCreateRelTable( createTableInfo.propertyNameDataTypes = transformPropertyDefinitions(*ctx.kU_PropertyDefinitions()); } - createTableInfo.extraInfo = std::make_unique( - relMultiplicity, std::move(srcTableName), std::move(dstTableName)); + createTableInfo.extraInfo = std::make_unique(relMultiplicity, + std::move(srcTableName), std::move(dstTableName)); return std::make_unique(std::move(createTableInfo)); } @@ -91,8 +91,8 @@ std::unique_ptr Transformer::transformCreateRelTableGroup( createTableInfo.propertyNameDataTypes = transformPropertyDefinitions(*ctx.kU_PropertyDefinitions()); } - createTableInfo.extraInfo = std::make_unique( - relMultiplicity, std::move(srcDstTablePairs)); + createTableInfo.extraInfo = std::make_unique(relMultiplicity, + std::move(srcDstTablePairs)); return std::make_unique(std::move(createTableInfo)); } @@ -129,8 +129,8 @@ std::unique_ptr Transformer::transformAddProperty( } else { defaultValue = std::make_unique(Value::createNullValue(), "NULL"); } - auto extraInfo = std::make_unique( - std::move(propertyName), std::move(dataType), std::move(defaultValue)); + auto extraInfo = std::make_unique(std::move(propertyName), + std::move(dataType), std::move(defaultValue)); auto info = AlterInfo(AlterType::ADD_PROPERTY, tableName, std::move(extraInfo)); return std::make_unique(std::move(info)); } diff --git a/src/parser/transform/transform_detach_database.cpp b/src/parser/transform/transform_detach_database.cpp new file mode 100644 index 00000000000..5f375c71817 --- /dev/null +++ b/src/parser/transform/transform_detach_database.cpp @@ -0,0 +1,14 @@ +#include "parser/detach_database.h" +#include "parser/transformer.h" + +namespace kuzu { +namespace parser { + +std::unique_ptr Transformer::transformDetachDatabase( + CypherParser::KU_DetachDatabaseContext& ctx) { + auto dbName = transformSchemaName(*ctx.oC_SchemaName()); + return std::make_unique(std::move(dbName)); +} + +} // namespace parser +} // namespace kuzu diff --git a/src/parser/transform/transform_expression.cpp b/src/parser/transform/transform_expression.cpp index cc7edbf694b..e142a4cda06 100644 --- a/src/parser/transform/transform_expression.cpp +++ b/src/parser/transform/transform_expression.cpp @@ -1,4 +1,9 @@ +#include "function/aggregate/count_star.h" +#include "function/arithmetic/vector_arithmetic_functions.h" #include "function/cast/functions/cast_from_string_functions.h" +#include "function/list/vector_list_functions.h" +#include "function/string/vector_string_functions.h" +#include "function/struct/vector_struct_functions.h" #include "parser/expression/parsed_case_expression.h" #include "parser/expression/parsed_function_expression.h" #include "parser/expression/parsed_literal_expression.h" @@ -9,6 +14,7 @@ #include "parser/transformer.h" using namespace kuzu::common; +using namespace kuzu::function; namespace kuzu { namespace parser { @@ -27,8 +33,8 @@ std::unique_ptr Transformer::transformOrExpression( expression = std::move(next); } else { auto rawName = expression->getRawName() + " OR " + next->getRawName(); - expression = std::make_unique( - ExpressionType::OR, std::move(expression), std::move(next), rawName); + expression = std::make_unique(ExpressionType::OR, + std::move(expression), std::move(next), rawName); } } return expression; @@ -43,8 +49,8 @@ std::unique_ptr Transformer::transformXorExpression( expression = std::move(next); } else { auto rawName = expression->getRawName() + " XOR " + next->getRawName(); - expression = std::make_unique( - ExpressionType::XOR, std::move(expression), std::move(next), rawName); + expression = std::make_unique(ExpressionType::XOR, + std::move(expression), std::move(next), rawName); } } return expression; @@ -59,8 +65,8 @@ std::unique_ptr Transformer::transformAndExpression( expression = std::move(next); } else { auto rawName = expression->getRawName() + " AND " + next->getRawName(); - expression = std::make_unique( - ExpressionType::AND, std::move(expression), std::move(next), rawName); + expression = std::make_unique(ExpressionType::AND, + std::move(expression), std::move(next), rawName); } } return expression; @@ -72,8 +78,8 @@ std::unique_ptr Transformer::transformNotExpression( if (!ctx.NOT().empty()) { for ([[maybe_unused]] auto& _ : ctx.NOT()) { auto rawName = "NOT " + result->toString(); - result = std::make_unique( - ExpressionType::NOT, std::move(result), std::move(rawName)); + result = std::make_unique(ExpressionType::NOT, std::move(result), + std::move(rawName)); } } return result; @@ -91,24 +97,24 @@ std::unique_ptr Transformer::transformComparisonExpression( auto right = transformBitwiseOrOperatorExpression(*ctx.kU_BitwiseOrOperatorExpression(1)); auto comparisonOperator = ctx.kU_ComparisonOperator()[0]->getText(); if (comparisonOperator == "=") { - return std::make_unique( - ExpressionType::EQUALS, std::move(left), std::move(right), ctx.getText()); + return std::make_unique(ExpressionType::EQUALS, std::move(left), + std::move(right), ctx.getText()); } else if (comparisonOperator == "<>") { - return std::make_unique( - ExpressionType::NOT_EQUALS, std::move(left), std::move(right), ctx.getText()); + return std::make_unique(ExpressionType::NOT_EQUALS, std::move(left), + std::move(right), ctx.getText()); } else if (comparisonOperator == ">") { - return std::make_unique( - ExpressionType::GREATER_THAN, std::move(left), std::move(right), ctx.getText()); + return std::make_unique(ExpressionType::GREATER_THAN, std::move(left), + std::move(right), ctx.getText()); } else if (comparisonOperator == ">=") { - return std::make_unique( - ExpressionType::GREATER_THAN_EQUALS, std::move(left), std::move(right), ctx.getText()); + return std::make_unique(ExpressionType::GREATER_THAN_EQUALS, + std::move(left), std::move(right), ctx.getText()); } else if (comparisonOperator == "<") { - return std::make_unique( - ExpressionType::LESS_THAN, std::move(left), std::move(right), ctx.getText()); + return std::make_unique(ExpressionType::LESS_THAN, std::move(left), + std::move(right), ctx.getText()); } else { KU_ASSERT(comparisonOperator == "<="); - return std::make_unique( - ExpressionType::LESS_THAN_EQUALS, std::move(left), std::move(right), ctx.getText()); + return std::make_unique(ExpressionType::LESS_THAN_EQUALS, std::move(left), + std::move(right), ctx.getText()); } } @@ -121,8 +127,8 @@ std::unique_ptr Transformer::transformBitwiseOrOperatorExpress expression = std::move(next); } else { auto rawName = expression->getRawName() + " | " + next->getRawName(); - expression = std::make_unique( - BITWISE_OR_FUNC_NAME, std::move(expression), std::move(next), rawName); + expression = std::make_unique(BitwiseOrFunction::name, + std::move(expression), std::move(next), rawName); } } return expression; @@ -137,8 +143,8 @@ std::unique_ptr Transformer::transformBitwiseAndOperatorExpres expression = std::move(next); } else { auto rawName = expression->getRawName() + " & " + next->getRawName(); - expression = std::make_unique( - BITWISE_AND_FUNC_NAME, std::move(expression), std::move(next), rawName); + expression = std::make_unique(BitwiseAndFunction::name, + std::move(expression), std::move(next), rawName); } } return expression; @@ -156,12 +162,12 @@ std::unique_ptr Transformer::transformBitShiftOperatorExpressi auto rawName = expression->getRawName() + " " + bitShiftOperator + " " + next->getRawName(); if (bitShiftOperator == "<<") { - expression = std::make_unique( - BITSHIFT_LEFT_FUNC_NAME, std::move(expression), std::move(next), rawName); + expression = std::make_unique(BitShiftLeftFunction::name, + std::move(expression), std::move(next), rawName); } else { KU_ASSERT(bitShiftOperator == ">>"); - expression = std::make_unique( - BITSHIFT_RIGHT_FUNC_NAME, std::move(expression), std::move(next), rawName); + expression = std::make_unique(BitShiftRightFunction::name, + std::move(expression), std::move(next), rawName); } } } @@ -180,8 +186,8 @@ std::unique_ptr Transformer::transformAddOrSubtractExpression( auto arithmeticOperator = ctx.kU_AddOrSubtractOperator(i - 1)->getText(); auto rawName = expression->getRawName() + " " + arithmeticOperator + " " + next->getRawName(); - expression = std::make_unique( - arithmeticOperator, std::move(expression), std::move(next), rawName); + expression = std::make_unique(arithmeticOperator, + std::move(expression), std::move(next), rawName); } } return expression; @@ -198,8 +204,8 @@ std::unique_ptr Transformer::transformMultiplyDivideModuloExpr auto arithmeticOperator = ctx.kU_MultiplyDivideModuloOperator(i - 1)->getText(); auto rawName = expression->getRawName() + " " + arithmeticOperator + " " + next->getRawName(); - expression = std::make_unique( - arithmeticOperator, std::move(expression), std::move(next), rawName); + expression = std::make_unique(arithmeticOperator, + std::move(expression), std::move(next), rawName); } } return expression; @@ -214,8 +220,8 @@ std::unique_ptr Transformer::transformPowerOfExpression( expression = std::move(next); } else { auto rawName = expression->getRawName() + " ^ " + next->getRawName(); - expression = std::make_unique( - POWER_FUNC_NAME, std::move(expression), std::move(next), rawName); + expression = std::make_unique(PowerFunction::name, + std::move(expression), std::move(next), rawName); } } return expression; @@ -227,14 +233,14 @@ std::unique_ptr Transformer::transformUnaryAddSubtractOrFactor transformStringListNullOperatorExpression(*ctx.oC_StringListNullOperatorExpression()); if (ctx.FACTORIAL()) { // Factorial has a higher auto raw = result->toString() + "!"; - result = std::make_unique( - FACTORIAL_FUNC_NAME, std::move(result), std::move(raw)); + result = std::make_unique(FactorialFunction::name, + std::move(result), std::move(raw)); } if (!ctx.MINUS().empty()) { for ([[maybe_unused]] auto& _ : ctx.MINUS()) { auto raw = "-" + result->toString(); - result = std::make_unique( - NEGATE_FUNC_NAME, std::move(result), std::move(raw)); + result = std::make_unique(NegateFunction::name, + std::move(result), std::move(raw)); } } return result; @@ -245,21 +251,21 @@ std::unique_ptr Transformer::transformStringListNullOperatorEx auto propertyExpression = transformPropertyOrLabelsExpression(*ctx.oC_PropertyOrLabelsExpression()); if (ctx.oC_NullOperatorExpression()) { - return transformNullOperatorExpression( - *ctx.oC_NullOperatorExpression(), std::move(propertyExpression)); + return transformNullOperatorExpression(*ctx.oC_NullOperatorExpression(), + std::move(propertyExpression)); } if (!ctx.oC_ListOperatorExpression().empty()) { - auto result = transformListOperatorExpression( - *ctx.oC_ListOperatorExpression(0), std::move(propertyExpression)); + auto result = transformListOperatorExpression(*ctx.oC_ListOperatorExpression(0), + std::move(propertyExpression)); for (auto i = 1u; i < ctx.oC_ListOperatorExpression().size(); ++i) { - result = transformListOperatorExpression( - *ctx.oC_ListOperatorExpression(i), std::move(result)); + result = transformListOperatorExpression(*ctx.oC_ListOperatorExpression(i), + std::move(result)); } return result; } if (ctx.oC_StringOperatorExpression()) { - return transformStringOperatorExpression( - *ctx.oC_StringOperatorExpression(), std::move(propertyExpression)); + return transformStringOperatorExpression(*ctx.oC_StringOperatorExpression(), + std::move(propertyExpression)); } return propertyExpression; } @@ -270,17 +276,17 @@ std::unique_ptr Transformer::transformStringOperatorExpression auto rawExpression = propertyExpression->getRawName() + " " + ctx.getText(); auto right = transformPropertyOrLabelsExpression(*ctx.oC_PropertyOrLabelsExpression()); if (ctx.STARTS()) { - return std::make_unique( - STARTS_WITH_FUNC_NAME, std::move(propertyExpression), std::move(right), rawExpression); + return std::make_unique(StartsWithFunction::name, + std::move(propertyExpression), std::move(right), rawExpression); } else if (ctx.ENDS()) { - return std::make_unique( - ENDS_WITH_FUNC_NAME, std::move(propertyExpression), std::move(right), rawExpression); + return std::make_unique(EndsWithFunction::name, + std::move(propertyExpression), std::move(right), rawExpression); } else if (ctx.CONTAINS()) { - return std::make_unique( - CONTAINS_FUNC_NAME, std::move(propertyExpression), std::move(right), rawExpression); + return std::make_unique(ContainsFunction::name, + std::move(propertyExpression), std::move(right), rawExpression); } else { KU_ASSERT(ctx.oC_RegularExpression()); - return std::make_unique(REGEXP_FULL_MATCH_FUNC_NAME, + return std::make_unique(RegexpFullMatchFunction::name, std::move(propertyExpression), std::move(right), rawExpression); } } @@ -290,7 +296,7 @@ std::unique_ptr Transformer::transformListOperatorExpression( auto raw = child->getRawName() + ctx.getText(); if (ctx.IN()) { // x IN y auto listContains = - std::make_unique(LIST_CONTAINS_FUNC_NAME, std::move(raw)); + std::make_unique(ListContainsFunction::name, std::move(raw)); auto right = transformPropertyOrLabelsExpression(*ctx.oC_PropertyOrLabelsExpression()); listContains->addChild(std::move(right)); listContains->addChild(std::move(child)); @@ -298,7 +304,7 @@ std::unique_ptr Transformer::transformListOperatorExpression( } if (ctx.COLON()) { // x[:] auto listSlice = - std::make_unique(LIST_SLICE_FUNC_NAME, std::move(raw)); + std::make_unique(ListSliceFunction::name, std::move(raw)); listSlice->addChild(std::move(child)); std::unique_ptr left; std::unique_ptr right; @@ -323,7 +329,7 @@ std::unique_ptr Transformer::transformListOperatorExpression( } // x[a] auto listExtract = - std::make_unique(LIST_EXTRACT_FUNC_NAME, std::move(raw)); + std::make_unique(ListExtractFunction::name, std::move(raw)); listExtract->addChild(std::move(child)); KU_ASSERT(ctx.oC_Expression().size() == 1); listExtract->addChild(transformExpression(*ctx.oC_Expression()[0])); @@ -337,8 +343,8 @@ std::unique_ptr Transformer::transformNullOperatorExpression( KU_ASSERT(ctx.IS() && ctx.NULL_()); return ctx.NOT() ? std::make_unique(ExpressionType::IS_NOT_NULL, std::move(propertyExpression), rawExpression) : - std::make_unique( - ExpressionType::IS_NULL, std::move(propertyExpression), rawExpression); + std::make_unique(ExpressionType::IS_NULL, + std::move(propertyExpression), rawExpression); } std::unique_ptr Transformer::transformPropertyOrLabelsExpression( @@ -376,8 +382,8 @@ std::unique_ptr Transformer::transformAtom(CypherParser::OC_At return transformCountSubquery(*ctx.kU_CountSubquery()); } else { KU_ASSERT(ctx.oC_Variable()); - return std::make_unique( - transformVariable(*ctx.oC_Variable()), ctx.getText()); + return std::make_unique(transformVariable(*ctx.oC_Variable()), + ctx.getText()); } } @@ -392,8 +398,8 @@ std::unique_ptr Transformer::transformLiteral( Value(LogicalType::STRING(), transformStringLiteral(*ctx.StringLiteral())), ctx.getText()); } else if (ctx.NULL_()) { - return std::make_unique( - Value(Value::createNullValue()), ctx.getText()); + return std::make_unique(Value(Value::createNullValue()), + ctx.getText()); } else if (ctx.kU_StructLiteral()) { return transformStructLiteral(*ctx.kU_StructLiteral()); } else { @@ -415,7 +421,7 @@ std::unique_ptr Transformer::transformBooleanLiteral( std::unique_ptr Transformer::transformListLiteral( CypherParser::OC_ListLiteralContext& ctx) { auto listCreation = - std::make_unique(LIST_CREATION_FUNC_NAME, ctx.getText()); + std::make_unique(ListCreationFunction::name, ctx.getText()); if (ctx.oC_Expression() == nullptr) { // empty list return listCreation; } @@ -435,7 +441,7 @@ std::unique_ptr Transformer::transformListLiteral( std::unique_ptr Transformer::transformStructLiteral( CypherParser::KU_StructLiteralContext& ctx) { auto structPack = - std::make_unique(STRUCT_PACK_FUNC_NAME, ctx.getText()); + std::make_unique(StructPackFunctions::name, ctx.getText()); for (auto& structField : ctx.kU_StructField()) { auto structExpr = transformExpression(*structField->oC_Expression()); std::string alias; @@ -465,7 +471,7 @@ std::unique_ptr Transformer::transformParenthesizedExpression( std::unique_ptr Transformer::transformFunctionInvocation( CypherParser::OC_FunctionInvocationContext& ctx) { if (ctx.STAR()) { - return std::make_unique(COUNT_STAR_FUNC_NAME, ctx.getText()); + return std::make_unique(CountStarFunction::name, ctx.getText()); } std::string functionName; if (ctx.COUNT()) { @@ -473,8 +479,8 @@ std::unique_ptr Transformer::transformFunctionInvocation( } else { functionName = transformFunctionName(*ctx.oC_FunctionName()); } - auto expression = std::make_unique( - functionName, ctx.getText(), ctx.DISTINCT() != nullptr); + auto expression = std::make_unique(functionName, ctx.getText(), + ctx.DISTINCT() != nullptr); for (auto& functionParameter : ctx.kU_FunctionParameter()) { expression->addChild(transformFunctionParameterExpression(*functionParameter)); } @@ -529,8 +535,8 @@ std::unique_ptr Transformer::createPropertyExpression( CypherParser::OC_PropertyLookupContext& ctx, std::unique_ptr child) { auto key = ctx.STAR() ? InternalKeyword::STAR : transformPropertyKeyName(*ctx.oC_PropertyKeyName()); - return std::make_unique( - key, std::move(child), child->toString() + ctx.getText()); + return std::make_unique(key, std::move(child), + child->toString() + ctx.getText()); } std::unique_ptr Transformer::transformCaseExpression( diff --git a/src/parser/transform/transform_extension.cpp b/src/parser/transform/transform_extension.cpp index f0c92ba0553..7fd7d7c858f 100644 --- a/src/parser/transform/transform_extension.cpp +++ b/src/parser/transform/transform_extension.cpp @@ -9,8 +9,8 @@ namespace parser { std::unique_ptr Transformer::transformExtension(CypherParser::KU_ExtensionContext& ctx) { if (ctx.kU_InstallExtension()) { - return std::make_unique( - ExtensionAction::INSTALL, transformVariable(*ctx.kU_InstallExtension()->oC_Variable())); + return std::make_unique(ExtensionAction::INSTALL, + transformVariable(*ctx.kU_InstallExtension()->oC_Variable())); } else { auto path = ctx.kU_LoadExtension()->StringLiteral() ? transformStringLiteral(*ctx.kU_LoadExtension()->StringLiteral()) : diff --git a/src/parser/transform/transform_projection.cpp b/src/parser/transform/transform_projection.cpp index 3cbe690dec0..b253ba3b5e5 100644 --- a/src/parser/transform/transform_projection.cpp +++ b/src/parser/transform/transform_projection.cpp @@ -20,8 +20,8 @@ ReturnClause Transformer::transformReturn(CypherParser::OC_ReturnContext& ctx) { } ProjectionBody Transformer::transformProjectionBody(CypherParser::OC_ProjectionBodyContext& ctx) { - auto projectionBody = ProjectionBody( - nullptr != ctx.DISTINCT(), transformProjectionItems(*ctx.oC_ProjectionItems())); + auto projectionBody = ProjectionBody(nullptr != ctx.DISTINCT(), + transformProjectionItems(*ctx.oC_ProjectionItems())); if (ctx.oC_Order()) { std::vector> orderByExpressions; std::vector isAscOrders; diff --git a/src/parser/transform/transform_query.cpp b/src/parser/transform/transform_query.cpp index 6a14af76c29..6f90eea3a68 100644 --- a/src/parser/transform/transform_query.cpp +++ b/src/parser/transform/transform_query.cpp @@ -12,8 +12,8 @@ std::unique_ptr Transformer::transformRegularQuery( CypherParser::OC_RegularQueryContext& ctx) { auto regularQuery = std::make_unique(transformSingleQuery(*ctx.oC_SingleQuery())); for (auto unionClause : ctx.oC_Union()) { - regularQuery->addSingleQuery( - transformSingleQuery(*unionClause->oC_SingleQuery()), unionClause->ALL()); + regularQuery->addSingleQuery(transformSingleQuery(*unionClause->oC_SingleQuery()), + unionClause->ALL()); } return regularQuery; } diff --git a/src/parser/transform/transform_reading_clause.cpp b/src/parser/transform/transform_reading_clause.cpp index 69f9b99f247..522907bb290 100644 --- a/src/parser/transform/transform_reading_clause.cpp +++ b/src/parser/transform/transform_reading_clause.cpp @@ -53,13 +53,8 @@ std::unique_ptr Transformer::transformInQueryCall( std::unique_ptr Transformer::transformLoadFrom( CypherParser::KU_LoadFromContext& ctx) { - auto loadFrom = std::make_unique(); - if (ctx.kU_FilePaths()) { - loadFrom->setFilePaths(transformFilePaths(ctx.kU_FilePaths()->StringLiteral())); - } else { - KU_ASSERT(ctx.oC_Variable()); - loadFrom->setObjectName(transformVariable(*ctx.oC_Variable())); - } + auto source = transformScanSource(*ctx.kU_ScanSource()); + auto loadFrom = std::make_unique(std::move(source)); if (ctx.kU_PropertyDefinitions()) { loadFrom->setColumnNameDataTypes( transformPropertyDefinitions(*ctx.kU_PropertyDefinitions())); diff --git a/src/parser/transform/transform_updating_clause.cpp b/src/parser/transform/transform_updating_clause.cpp index de36ad9ccb8..b28cd2dfb91 100644 --- a/src/parser/transform/transform_updating_clause.cpp +++ b/src/parser/transform/transform_updating_clause.cpp @@ -52,8 +52,8 @@ std::unique_ptr Transformer::transformSet(CypherParser::OC_SetCo } parsed_expr_pair Transformer::transformSetItem(CypherParser::OC_SetItemContext& ctx) { - return make_pair( - transformProperty(*ctx.oC_PropertyExpression()), transformExpression(*ctx.oC_Expression())); + return make_pair(transformProperty(*ctx.oC_PropertyExpression()), + transformExpression(*ctx.oC_Expression())); } std::unique_ptr Transformer::transformDelete(CypherParser::OC_DeleteContext& ctx) { diff --git a/src/parser/transformer.cpp b/src/parser/transformer.cpp index 3350df9853f..dafcfcad7bd 100644 --- a/src/parser/transformer.cpp +++ b/src/parser/transformer.cpp @@ -10,8 +10,8 @@ using namespace kuzu::common; namespace kuzu { namespace parser { -std::vector> Transformer::transform() { - std::vector> statements; +std::vector> Transformer::transform() { + std::vector> statements; for (auto& oc_Statement : root.oC_Cypher()) { auto statement = transformStatement(*oc_Statement->oC_Statement()); if (oc_Statement->oC_AnyCypherOption()) { @@ -52,6 +52,10 @@ std::unique_ptr Transformer::transformStatement(CypherParser::OC_Stat return transformExportDatabase(*ctx.kU_ExportDatabase()); } else if (ctx.kU_ImportDatabase()) { return transformImportDatabase(*ctx.kU_ImportDatabase()); + } else if (ctx.kU_AttachDatabase()) { + return transformAttachDatabase(*ctx.kU_AttachDatabase()); + } else if (ctx.kU_DetachDatabase()) { + return transformDetachDatabase(*ctx.kU_DetachDatabase()); } else { KU_UNREACHABLE; } diff --git a/src/planner/join_order/cardinality_estimator.cpp b/src/planner/join_order/cardinality_estimator.cpp index d6035e22694..91b6239a190 100644 --- a/src/planner/join_order/cardinality_estimator.cpp +++ b/src/planner/join_order/cardinality_estimator.cpp @@ -6,29 +6,30 @@ using namespace kuzu::binder; using namespace kuzu::common; +using namespace kuzu::transaction; namespace kuzu { namespace planner { -void CardinalityEstimator::initNodeIDDom(const QueryGraph& queryGraph) { +void CardinalityEstimator::initNodeIDDom(const QueryGraph& queryGraph, Transaction* transaction) { for (auto i = 0u; i < queryGraph.getNumQueryNodes(); ++i) { auto node = queryGraph.getQueryNode(i).get(); - addNodeIDDom(*node->getInternalID(), node->getTableIDs()); + addNodeIDDom(*node->getInternalID(), node->getTableIDs(), transaction); } for (auto i = 0u; i < queryGraph.getNumQueryRels(); ++i) { auto rel = queryGraph.getQueryRel(i); if (QueryRelTypeUtils::isRecursive(rel->getRelType())) { auto node = rel->getRecursiveInfo()->node.get(); - addNodeIDDom(*node->getInternalID(), node->getTableIDs()); + addNodeIDDom(*node->getInternalID(), node->getTableIDs(), transaction); } } } -void CardinalityEstimator::addNodeIDDom( - const binder::Expression& nodeID, const std::vector& tableIDs) { +void CardinalityEstimator::addNodeIDDom(const binder::Expression& nodeID, + const std::vector& tableIDs, Transaction* transaction) { auto key = nodeID.getUniqueName(); if (!nodeIDName2dom.contains(key)) { - nodeIDName2dom.insert({key, getNumNodes(tableIDs)}); + nodeIDName2dom.insert({key, getNumNodes(tableIDs, transaction)}); } } @@ -37,8 +38,8 @@ uint64_t CardinalityEstimator::estimateScanNode(LogicalOperator* op) { return atLeastOne(getNodeIDDom(scan->getInternalID()->getUniqueName())); } -uint64_t CardinalityEstimator::estimateHashJoin( - const expression_vector& joinKeys, const LogicalPlan& probePlan, const LogicalPlan& buildPlan) { +uint64_t CardinalityEstimator::estimateHashJoin(const expression_vector& joinKeys, + const LogicalPlan& probePlan, const LogicalPlan& buildPlan) { auto denominator = 1u; for (auto& joinKey : joinKeys) { // TODO(Xiyang): we should be able to estimate non-ID-based joins as well. @@ -50,8 +51,8 @@ uint64_t CardinalityEstimator::estimateHashJoin( JoinOrderUtil::getJoinKeysFlatCardinality(joinKeys, buildPlan) / denominator); } -uint64_t CardinalityEstimator::estimateCrossProduct( - const LogicalPlan& probePlan, const LogicalPlan& buildPlan) { +uint64_t CardinalityEstimator::estimateCrossProduct(const LogicalPlan& probePlan, + const LogicalPlan& buildPlan) { return atLeastOne(probePlan.estCardinality * buildPlan.estCardinality); } @@ -74,8 +75,8 @@ uint64_t CardinalityEstimator::estimateIntersect(const expression_vector& joinNo return atLeastOne(std::min(estCardinality1, estCardinality2)); } -uint64_t CardinalityEstimator::estimateFlatten( - const LogicalPlan& childPlan, f_group_pos groupPosToFlatten) { +uint64_t CardinalityEstimator::estimateFlatten(const LogicalPlan& childPlan, + f_group_pos groupPosToFlatten) { auto group = childPlan.getSchema()->getGroup(groupPosToFlatten); return atLeastOne(childPlan.estCardinality * group->cardinalityMultiplier); } @@ -87,8 +88,8 @@ static bool isPrimaryKey(const Expression& expression) { return ((PropertyExpression&)expression).isPrimaryKey(); } -uint64_t CardinalityEstimator::estimateFilter( - const LogicalPlan& childPlan, const Expression& predicate) { +uint64_t CardinalityEstimator::estimateFilter(const LogicalPlan& childPlan, + const Expression& predicate) { if (predicate.expressionType == ExpressionType::EQUALS) { if (isPrimaryKey(*predicate.getChild(0)) || isPrimaryKey(*predicate.getChild(1))) { return 1; @@ -102,29 +103,29 @@ uint64_t CardinalityEstimator::estimateFilter( } } -uint64_t CardinalityEstimator::getNumNodes(const std::vector& tableIDs) { +uint64_t CardinalityEstimator::getNumNodes(const std::vector& tableIDs, + Transaction* transaction) { auto numNodes = 0u; for (auto& tableID : tableIDs) { - numNodes += nodesStatistics->getNodeStatisticsAndDeletedIDs(tableID)->getNumTuples(); + numNodes += + nodesStatistics->getNodeStatisticsAndDeletedIDs(transaction, tableID)->getNumTuples(); } return atLeastOne(numNodes); } -uint64_t CardinalityEstimator::getNumRels(const std::vector& tableIDs) { +uint64_t CardinalityEstimator::getNumRels(const std::vector& tableIDs, + Transaction* transaction) { auto numRels = 0u; for (auto tableID : tableIDs) { - numRels += - relsStatistics - ->getRelStatistics(tableID, transaction::Transaction::getDummyReadOnlyTrx().get()) - ->getNumTuples(); + numRels += relsStatistics->getRelStatistics(tableID, transaction)->getNumTuples(); } return atLeastOne(numRels); } -double CardinalityEstimator::getExtensionRate( - const RelExpression& rel, const NodeExpression& boundNode) { - auto numBoundNodes = (double)getNumNodes(boundNode.getTableIDs()); - auto numRels = (double)getNumRels(rel.getTableIDs()); +double CardinalityEstimator::getExtensionRate(const RelExpression& rel, + const NodeExpression& boundNode, Transaction* transaction) { + auto numBoundNodes = (double)getNumNodes(boundNode.getTableIDs(), transaction); + auto numRels = (double)getNumRels(rel.getTableIDs(), transaction); auto oneHopExtensionRate = numRels / numBoundNodes; switch (rel.getRelType()) { case QueryRelType::NON_RECURSIVE: { diff --git a/src/planner/join_order/cost_model.cpp b/src/planner/join_order/cost_model.cpp index 1b4d3d6b5eb..2d95e2ec9a8 100644 --- a/src/planner/join_order/cost_model.cpp +++ b/src/planner/join_order/cost_model.cpp @@ -12,8 +12,8 @@ uint64_t CostModel::computeExtendCost(const LogicalPlan& childPlan) { return childPlan.estCardinality; } -uint64_t CostModel::computeRecursiveExtendCost( - uint8_t upperBound, double extensionRate, const LogicalPlan& childPlan) { +uint64_t CostModel::computeRecursiveExtendCost(uint8_t upperBound, double extensionRate, + const LogicalPlan& childPlan) { return PlannerKnobs::BUILD_PENALTY * childPlan.estCardinality * (uint64_t)extensionRate * upperBound; } diff --git a/src/planner/join_order/join_order_util.cpp b/src/planner/join_order/join_order_util.cpp index a79ee300ad0..f06b8644e4f 100644 --- a/src/planner/join_order/join_order_util.cpp +++ b/src/planner/join_order/join_order_util.cpp @@ -3,8 +3,8 @@ namespace kuzu { namespace planner { -uint64_t JoinOrderUtil::getJoinKeysFlatCardinality( - const binder::expression_vector& joinNodeIDs, const LogicalPlan& buildPlan) { +uint64_t JoinOrderUtil::getJoinKeysFlatCardinality(const binder::expression_vector& joinNodeIDs, + const LogicalPlan& buildPlan) { auto schema = buildPlan.getSchema(); f_group_pos_set unFlatGroupsPos; for (auto& joinID : joinNodeIDs) { diff --git a/src/planner/join_order_enumerator_context.cpp b/src/planner/join_order_enumerator_context.cpp index a17831fa7e3..ea3ce5d0398 100644 --- a/src/planner/join_order_enumerator_context.cpp +++ b/src/planner/join_order_enumerator_context.cpp @@ -5,8 +5,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void JoinOrderEnumeratorContext::init( - const QueryGraph* queryGraph_, const expression_vector& predicates) { +void JoinOrderEnumeratorContext::init(const QueryGraph* queryGraph_, + const expression_vector& predicates) { whereExpressionsSplitOnAND = predicates; this->queryGraph = queryGraph_; // clear and resize subPlansTable diff --git a/src/planner/operator/CMakeLists.txt b/src/planner/operator/CMakeLists.txt index a69aaf38a68..fd176ffe117 100644 --- a/src/planner/operator/CMakeLists.txt +++ b/src/planner/operator/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(kuzu_planner_operator logical_in_query_call.cpp logical_intersect.cpp logical_limit.cpp + logical_mark_accumulate.cpp logical_operator.cpp logical_order_by.cpp logical_partitioner.cpp diff --git a/src/planner/operator/factorization/flatten_resolver.cpp b/src/planner/operator/factorization/flatten_resolver.cpp index bd375a84e5c..74cb5f8ffd4 100644 --- a/src/planner/operator/factorization/flatten_resolver.cpp +++ b/src/planner/operator/factorization/flatten_resolver.cpp @@ -4,8 +4,8 @@ namespace kuzu { namespace planner { namespace factorization { -f_group_pos_set FlattenAllButOne::getGroupsPosToFlatten( - const f_group_pos_set& groupsPos, Schema* schema) { +f_group_pos_set FlattenAllButOne::getGroupsPosToFlatten(const f_group_pos_set& groupsPos, + Schema* schema) { std::vector unFlatGroupsPos; for (auto groupPos : groupsPos) { if (!schema->getGroup(groupPos)->isFlat()) { @@ -20,8 +20,8 @@ f_group_pos_set FlattenAllButOne::getGroupsPosToFlatten( return result; } -f_group_pos_set FlattenAll::getGroupsPosToFlatten( - const f_group_pos_set& groupsPos, Schema* schema) { +f_group_pos_set FlattenAll::getGroupsPosToFlatten(const f_group_pos_set& groupsPos, + Schema* schema) { f_group_pos_set result; for (auto groupPos : groupsPos) { if (!schema->getGroup(groupPos)->isFlat()) { diff --git a/src/planner/operator/factorization/sink_util.cpp b/src/planner/operator/factorization/sink_util.cpp index c49e7aeee6d..cb4b5e16842 100644 --- a/src/planner/operator/factorization/sink_util.cpp +++ b/src/planner/operator/factorization/sink_util.cpp @@ -30,8 +30,8 @@ void SinkOperatorUtil::recomputeSchema(const Schema& inputSchema, } std::unordered_map -SinkOperatorUtil::getUnFlatPayloadsPerGroup( - const Schema& schema, const binder::expression_vector& payloads) { +SinkOperatorUtil::getUnFlatPayloadsPerGroup(const Schema& schema, + const binder::expression_vector& payloads) { std::unordered_map result; for (auto& payload : payloads) { auto groupPos = schema.getGroupPos(*payload); @@ -46,8 +46,8 @@ SinkOperatorUtil::getUnFlatPayloadsPerGroup( return result; } -binder::expression_vector SinkOperatorUtil::getFlatPayloads( - const Schema& schema, const binder::expression_vector& payloads) { +binder::expression_vector SinkOperatorUtil::getFlatPayloads(const Schema& schema, + const binder::expression_vector& payloads) { binder::expression_vector result; for (auto& payload : payloads) { if (schema.getGroup(payload)->isFlat()) { @@ -57,8 +57,8 @@ binder::expression_vector SinkOperatorUtil::getFlatPayloads( return result; } -uint32_t SinkOperatorUtil::appendPayloadsToNewGroup( - Schema& schema, binder::expression_vector& payloads) { +uint32_t SinkOperatorUtil::appendPayloadsToNewGroup(Schema& schema, + binder::expression_vector& payloads) { auto outputGroupPos = schema.createGroup(); for (auto& payload : payloads) { schema.insertToGroupAndScope(payload, outputGroupPos); diff --git a/src/planner/operator/logical_accumulate.cpp b/src/planner/operator/logical_accumulate.cpp index d05a224edde..ffc4dc760ea 100644 --- a/src/planner/operator/logical_accumulate.cpp +++ b/src/planner/operator/logical_accumulate.cpp @@ -9,17 +9,26 @@ namespace planner { void LogicalAccumulate::computeFactorizedSchema() { createEmptySchema(); auto childSchema = children[0]->getSchema(); - SinkOperatorUtil::recomputeSchema(*childSchema, getExpressionsToAccumulate(), *schema); + SinkOperatorUtil::recomputeSchema(*childSchema, getPayloads(), *schema); + if (offset != nullptr) { + // If we need to generate row offset. Then all expressions must have been flattened and + // accumulated. So the new schema should just have one group. + KU_ASSERT(schema->getNumGroups() == 1); + schema->insertToGroupAndScope(offset, 0); + } } void LogicalAccumulate::computeFlatSchema() { copyChildSchema(0); + if (offset != nullptr) { + schema->insertToGroupAndScope(offset, 0); + } } f_group_pos_set LogicalAccumulate::getGroupPositionsToFlatten() const { f_group_pos_set result; auto childSchema = children[0]->getSchema(); - for (auto& expression : expressionsToFlatten) { + for (auto& expression : flatExprs) { auto groupPos = childSchema->getGroupPos(*expression); result.insert(groupPos); } diff --git a/src/planner/operator/logical_aggregate.cpp b/src/planner/operator/logical_aggregate.cpp index 3fe16e522ff..daa04431db9 100644 --- a/src/planner/operator/logical_aggregate.cpp +++ b/src/planner/operator/logical_aggregate.cpp @@ -30,8 +30,8 @@ f_group_pos_set LogicalAggregate::getGroupsPosToFlattenForGroupBy() { if (hasDistinctAggregate()) { return FlattenAll::getGroupsPosToFlatten(dependentGroupsPos, children[0]->getSchema()); } else { - return FlattenAllButOne::getGroupsPosToFlatten( - dependentGroupsPos, children[0]->getSchema()); + return FlattenAllButOne::getGroupsPosToFlatten(dependentGroupsPos, + children[0]->getSchema()); } } diff --git a/src/planner/operator/logical_distinct.cpp b/src/planner/operator/logical_distinct.cpp index 74fde0ae8f9..b27415b7c8e 100644 --- a/src/planner/operator/logical_distinct.cpp +++ b/src/planner/operator/logical_distinct.cpp @@ -1,5 +1,6 @@ #include "planner/operator/logical_distinct.h" +#include "binder/expression/expression_util.h" #include "planner/operator/factorization/flatten_resolver.h" namespace kuzu { @@ -8,7 +9,7 @@ namespace planner { void LogicalDistinct::computeFactorizedSchema() { createEmptySchema(); auto groupPos = schema->createGroup(); - for (auto& expression : getAllDistinctExpressions()) { + for (auto& expression : getKeysAndPayloads()) { schema->insertToGroupAndScope(expression, groupPos); } } @@ -16,7 +17,7 @@ void LogicalDistinct::computeFactorizedSchema() { void LogicalDistinct::computeFlatSchema() { createEmptySchema(); schema->createGroup(); - for (auto& expression : getAllDistinctExpressions()) { + for (auto& expression : getKeysAndPayloads()) { schema->insertToGroupAndScope(expression, 0); } } @@ -24,7 +25,7 @@ void LogicalDistinct::computeFlatSchema() { f_group_pos_set LogicalDistinct::getGroupsPosToFlatten() { f_group_pos_set dependentGroupsPos; auto childSchema = children[0]->getSchema(); - for (auto& expression : getAllDistinctExpressions()) { + for (auto& expression : getKeysAndPayloads()) { for (auto groupPos : childSchema->getDependentGroupsPos(expression)) { dependentGroupsPos.insert(groupPos); } @@ -33,10 +34,13 @@ f_group_pos_set LogicalDistinct::getGroupsPosToFlatten() { } std::string LogicalDistinct::getExpressionsForPrinting() const { - std::string result; - for (auto& expression : getAllDistinctExpressions()) { - result += expression->getUniqueName() + ", "; - } + return binder::ExpressionUtil::toString(getKeysAndPayloads()); +} + +binder::expression_vector LogicalDistinct::getKeysAndPayloads() const { + binder::expression_vector result; + result.insert(result.end(), keys.begin(), keys.end()); + result.insert(result.end(), payloads.begin(), payloads.end()); return result; } diff --git a/src/planner/operator/logical_dummy_scan.cpp b/src/planner/operator/logical_dummy_scan.cpp index 9f09d9d7edf..9eeeddea592 100644 --- a/src/planner/operator/logical_dummy_scan.cpp +++ b/src/planner/operator/logical_dummy_scan.cpp @@ -21,8 +21,8 @@ void LogicalDummyScan::computeFlatSchema() { std::shared_ptr LogicalDummyScan::getDummyExpression() { auto logicalType = LogicalType(LogicalTypeID::STRING); auto nullValue = Value::createNullValue(logicalType); - return std::make_shared( - nullValue.copy(), InternalKeyword::PLACE_HOLDER); + return std::make_shared(nullValue.copy(), + InternalKeyword::PLACE_HOLDER); } } // namespace planner diff --git a/src/planner/operator/logical_hash_join.cpp b/src/planner/operator/logical_hash_join.cpp index 8a03e18c25c..95792f30ba1 100644 --- a/src/planner/operator/logical_hash_join.cpp +++ b/src/planner/operator/logical_hash_join.cpp @@ -65,8 +65,8 @@ void LogicalHashJoin::computeFactorizedSchema() { } } } - SinkOperatorUtil::mergeSchema( - *buildSchema, expressionsToMaterializeInNonKeyGroups, *schema); + SinkOperatorUtil::mergeSchema(*buildSchema, expressionsToMaterializeInNonKeyGroups, + *schema); } break; case JoinType::MARK: { std::unordered_set probeSideKeyGroupPositions; diff --git a/src/planner/operator/logical_intersect.cpp b/src/planner/operator/logical_intersect.cpp index df7196b8ed6..c5d57bac59b 100644 --- a/src/planner/operator/logical_intersect.cpp +++ b/src/planner/operator/logical_intersect.cpp @@ -61,8 +61,8 @@ std::unique_ptr LogicalIntersect::copy() { for (auto i = 1u; i < children.size(); ++i) { buildChildren.push_back(children[i]->copy()); } - return make_unique( - intersectNodeID, keyNodeIDs, children[0]->copy(), std::move(buildChildren)); + return make_unique(intersectNodeID, keyNodeIDs, children[0]->copy(), + std::move(buildChildren)); } } // namespace planner diff --git a/src/planner/operator/logical_mark_accumulate.cpp b/src/planner/operator/logical_mark_accumulate.cpp new file mode 100644 index 00000000000..01234d84f81 --- /dev/null +++ b/src/planner/operator/logical_mark_accumulate.cpp @@ -0,0 +1,46 @@ +#include "binder/expression/expression_util.h" +#include "planner/operator/factorization/flatten_resolver.h" +#include "planner/operator/factorization/sink_util.h" +#include "planner/operator/logical_mark_accmulate.h" + +using namespace kuzu::binder; + +namespace kuzu { +namespace planner { + +void LogicalMarkAccumulate::computeFactorizedSchema() { + createEmptySchema(); + auto childSchema = children[0]->getSchema(); + SinkOperatorUtil::recomputeSchema(*childSchema, childSchema->getExpressionsInScope(), *schema); + f_group_pos groupPos; + if (!keys.empty()) { + groupPos = schema->getGroupPos(*keys[0]); + } else { + groupPos = schema->createGroup(); + } + schema->insertToGroupAndScope(mark, groupPos); +} + +void LogicalMarkAccumulate::computeFlatSchema() { + copyChildSchema(0); + schema->insertToGroupAndScope(mark, 0); +} + +f_group_pos_set LogicalMarkAccumulate::getGroupsPosToFlatten() const { + f_group_pos_set dependentGroupsPos; + auto childSchema = children[0]->getSchema(); + for (auto& key : keys) { + for (auto groupPos : childSchema->getDependentGroupsPos(key)) { + dependentGroupsPos.insert(groupPos); + } + } + return factorization::FlattenAll::getGroupsPosToFlatten(dependentGroupsPos, childSchema); +} + +expression_vector LogicalMarkAccumulate::getPayloads() const { + auto exprs = children[0]->getSchema()->getExpressionsInScope(); + return ExpressionUtil::excludeExpressions(exprs, keys); +} + +} // namespace planner +} // namespace kuzu diff --git a/src/planner/operator/logical_operator.cpp b/src/planner/operator/logical_operator.cpp index b2d60c56884..d03b4820e63 100644 --- a/src/planner/operator/logical_operator.cpp +++ b/src/planner/operator/logical_operator.cpp @@ -7,6 +7,8 @@ namespace planner { std::string LogicalOperatorUtils::logicalOperatorTypeToString(LogicalOperatorType type) { switch (type) { + case LogicalOperatorType::ATTACH_DATABASE: + return "ATTACH_DATABASE"; case LogicalOperatorType::ACCUMULATE: return "ACCUMULATE"; case LogicalOperatorType::AGGREGATE: @@ -29,6 +31,8 @@ std::string LogicalOperatorUtils::logicalOperatorTypeToString(LogicalOperatorTyp return "DELETE_NODE"; case LogicalOperatorType::DELETE_REL: return "DELETE_REL"; + case LogicalOperatorType::DETACH_DATABASE: + return "DETACH_DATABASE"; case LogicalOperatorType::DISTINCT: return "DISTINCT"; case LogicalOperatorType::DROP_TABLE: @@ -59,6 +63,8 @@ std::string LogicalOperatorUtils::logicalOperatorTypeToString(LogicalOperatorTyp return "INSERT"; case LogicalOperatorType::LIMIT: return "LIMIT"; + case LogicalOperatorType::MARK_ACCUMULATE: + return "MARK_ACCUMULATE"; case LogicalOperatorType::MERGE: return "MERGE"; case LogicalOperatorType::MULTIPLICITY_REDUCER: @@ -108,8 +114,22 @@ std::string LogicalOperatorUtils::logicalOperatorTypeToString(LogicalOperatorTyp } } -LogicalOperator::LogicalOperator( - LogicalOperatorType operatorType, std::shared_ptr child) +bool LogicalOperatorUtils::isUpdate(LogicalOperatorType type) { + switch (type) { + case LogicalOperatorType::INSERT: + case LogicalOperatorType::DELETE_NODE: + case LogicalOperatorType::DELETE_REL: + case LogicalOperatorType::SET_NODE_PROPERTY: + case LogicalOperatorType::SET_REL_PROPERTY: + case LogicalOperatorType::MERGE: + return true; + default: + return false; + } +} + +LogicalOperator::LogicalOperator(LogicalOperatorType operatorType, + std::shared_ptr child) : operatorType{operatorType} { children.push_back(std::move(child)); } @@ -121,14 +141,26 @@ LogicalOperator::LogicalOperator(LogicalOperatorType operatorType, children.push_back(std::move(right)); } -LogicalOperator::LogicalOperator( - LogicalOperatorType operatorType, const logical_op_vector_t& children) +LogicalOperator::LogicalOperator(LogicalOperatorType operatorType, + const logical_op_vector_t& children) : operatorType{operatorType} { for (auto& child : children) { this->children.push_back(child); } } +bool LogicalOperator::hasUpdateRecursive() { + if (LogicalOperatorUtils::isUpdate(operatorType)) { + return true; + } + for (auto& child : children) { + if (child->hasUpdateRecursive()) { + return true; + } + } + return false; +} + std::string LogicalOperator::toString(uint64_t depth) const { auto padding = std::string(depth * 4, ' '); std::string result = padding; diff --git a/src/planner/operator/logical_plan.cpp b/src/planner/operator/logical_plan.cpp index 7a20fa88316..cbce3288054 100644 --- a/src/planner/operator/logical_plan.cpp +++ b/src/planner/operator/logical_plan.cpp @@ -1,8 +1,20 @@ #include "planner/operator/logical_plan.h" +#include "planner/operator/logical_explain.h" + namespace kuzu { namespace planner { +bool LogicalPlan::isProfile() const { + return lastOperator->getOperatorType() == LogicalOperatorType::EXPLAIN && + reinterpret_cast(lastOperator.get())->getExplainType() == + common::ExplainType::PROFILE; +} + +bool LogicalPlan::hasUpdate() const { + return lastOperator->hasUpdateRecursive(); +} + std::unique_ptr LogicalPlan::shallowCopy() const { auto plan = std::make_unique(); plan->lastOperator = lastOperator; // shallow copy sub-plan diff --git a/src/planner/operator/logical_plan_util.cpp b/src/planner/operator/logical_plan_util.cpp index a5d570632d4..92d8df2d329 100644 --- a/src/planner/operator/logical_plan_util.cpp +++ b/src/planner/operator/logical_plan_util.cpp @@ -12,8 +12,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void LogicalPlanUtil::encodeJoinRecursive( - LogicalOperator* logicalOperator, std::string& encodeString) { +void LogicalPlanUtil::encodeJoinRecursive(LogicalOperator* logicalOperator, + std::string& encodeString) { switch (logicalOperator->getOperatorType()) { case LogicalOperatorType::CROSS_PRODUCT: { encodeCrossProduct(logicalOperator, encodeString); @@ -57,8 +57,8 @@ void LogicalPlanUtil::encodeJoinRecursive( } } -void LogicalPlanUtil::encodeCrossProduct( - LogicalOperator* /*logicalOperator*/, std::string& encodeString) { +void LogicalPlanUtil::encodeCrossProduct(LogicalOperator* /*logicalOperator*/, + std::string& encodeString) { encodeString += "CP()"; } @@ -79,15 +79,15 @@ void LogicalPlanUtil::encodeExtend(LogicalOperator* logicalOperator, std::string encodeString += "E(" + logicalExtend->getNbrNode()->toString() + ")"; } -void LogicalPlanUtil::encodeRecursiveExtend( - LogicalOperator* logicalOperator, std::string& encodeString) { +void LogicalPlanUtil::encodeRecursiveExtend(LogicalOperator* logicalOperator, + std::string& encodeString) { auto logicalExtend = common::ku_dynamic_cast(logicalOperator); encodeString += "RE(" + logicalExtend->getNbrNode()->toString() + ")"; } -void LogicalPlanUtil::encodeScanInternalID( - LogicalOperator* logicalOperator, std::string& encodeString) { +void LogicalPlanUtil::encodeScanInternalID(LogicalOperator* logicalOperator, + std::string& encodeString) { auto scan = common::ku_dynamic_cast(logicalOperator); encodeString += "S(" + scan->getInternalID()->toString() + ")"; } diff --git a/src/planner/operator/logical_union.cpp b/src/planner/operator/logical_union.cpp index 27a3330f861..0fc0440bbb4 100644 --- a/src/planner/operator/logical_union.cpp +++ b/src/planner/operator/logical_union.cpp @@ -21,8 +21,8 @@ f_group_pos_set LogicalUnion::getGroupsPosToFlatten(uint32_t childIdx) { void LogicalUnion::computeFactorizedSchema() { auto firstChildSchema = children[0]->getSchema(); createEmptySchema(); - SinkOperatorUtil::recomputeSchema( - *firstChildSchema, firstChildSchema->getExpressionsInScope(), *schema); + SinkOperatorUtil::recomputeSchema(*firstChildSchema, firstChildSchema->getExpressionsInScope(), + *schema); } void LogicalUnion::computeFlatSchema() { diff --git a/src/planner/operator/logical_unwind.cpp b/src/planner/operator/logical_unwind.cpp index 303c6ae65c8..24e0c29d1cf 100644 --- a/src/planner/operator/logical_unwind.cpp +++ b/src/planner/operator/logical_unwind.cpp @@ -2,24 +2,33 @@ #include "planner/operator/factorization/flatten_resolver.h" +using namespace kuzu::binder; +using namespace kuzu::common; + namespace kuzu { namespace planner { f_group_pos_set LogicalUnwind::getGroupsPosToFlatten() { auto childSchema = children[0]->getSchema(); - auto dependentGroupsPos = childSchema->getDependentGroupsPos(expression); + auto dependentGroupsPos = childSchema->getDependentGroupsPos(inExpr); return factorization::FlattenAll::getGroupsPosToFlatten(dependentGroupsPos, childSchema); } void LogicalUnwind::computeFactorizedSchema() { copyChildSchema(0); auto groupPos = schema->createGroup(); - schema->insertToGroupAndScope(aliasExpression, groupPos); + schema->insertToGroupAndScope(outExpr, groupPos); + if (hasIDExpr()) { + schema->insertToGroupAndScope(idExpr, groupPos); + } } void LogicalUnwind::computeFlatSchema() { copyChildSchema(0); - schema->insertToGroupAndScope(aliasExpression, 0); + schema->insertToGroupAndScope(outExpr, 0); + if (hasIDExpr()) { + schema->insertToGroupAndScope(idExpr, 0); + } } } // namespace planner diff --git a/src/planner/operator/persistent/logical_insert.cpp b/src/planner/operator/persistent/logical_insert.cpp index 3549fbc1d8c..115797a1bcb 100644 --- a/src/planner/operator/persistent/logical_insert.cpp +++ b/src/planner/operator/persistent/logical_insert.cpp @@ -53,8 +53,8 @@ std::string LogicalInsert::getExpressionsForPrinting() const { f_group_pos_set LogicalInsert::getGroupsPosToFlatten() { auto childSchema = children[0]->getSchema(); - return factorization::FlattenAll::getGroupsPosToFlatten( - childSchema->getGroupsPosInScope(), childSchema); + return factorization::FlattenAll::getGroupsPosToFlatten(childSchema->getGroupsPosInScope(), + childSchema); } } // namespace planner diff --git a/src/planner/operator/persistent/logical_merge.cpp b/src/planner/operator/persistent/logical_merge.cpp index c8e980fa5df..5bc92535de5 100644 --- a/src/planner/operator/persistent/logical_merge.cpp +++ b/src/planner/operator/persistent/logical_merge.cpp @@ -33,8 +33,8 @@ void LogicalMerge::computeFlatSchema() { f_group_pos_set LogicalMerge::getGroupsPosToFlatten() { auto childSchema = children[0]->getSchema(); - return factorization::FlattenAll::getGroupsPosToFlatten( - childSchema->getGroupsPosInScope(), childSchema); + return factorization::FlattenAll::getGroupsPosToFlatten(childSchema->getGroupsPosInScope(), + childSchema); } } // namespace planner diff --git a/src/planner/operator/scan/logical_scan_file.cpp b/src/planner/operator/scan/logical_scan_file.cpp index d2c3795aa2c..3142c94554d 100644 --- a/src/planner/operator/scan/logical_scan_file.cpp +++ b/src/planner/operator/scan/logical_scan_file.cpp @@ -7,14 +7,18 @@ void LogicalScanFile::computeFactorizedSchema() { createEmptySchema(); auto groupPos = schema->createGroup(); schema->insertToGroupAndScope(info.columns, groupPos); - schema->insertToGroupAndScope(info.offset, groupPos); + if (offset != nullptr) { + schema->insertToGroupAndScope(offset, groupPos); + } } void LogicalScanFile::computeFlatSchema() { createEmptySchema(); schema->createGroup(); schema->insertToGroupAndScope(info.columns, 0); - schema->insertToGroupAndScope(info.offset, 0); + if (offset != nullptr) { + schema->insertToGroupAndScope(offset, 0); + } } } // namespace planner diff --git a/src/planner/operator/schema.cpp b/src/planner/operator/schema.cpp index 1367792ef03..cca6becc804 100644 --- a/src/planner/operator/schema.cpp +++ b/src/planner/operator/schema.cpp @@ -15,39 +15,39 @@ f_group_pos Schema::createGroup() { return pos; } -void Schema::insertToScope( - const std::shared_ptr& expression, f_group_pos groupPos) { +void Schema::insertToScope(const std::shared_ptr& expression, + f_group_pos groupPos) { KU_ASSERT(!expressionNameToGroupPos.contains(expression->getUniqueName())); expressionNameToGroupPos.insert({expression->getUniqueName(), groupPos}); expressionsInScope.push_back(expression); } -void Schema::insertToGroupAndScope( - const std::shared_ptr& expression, f_group_pos groupPos) { +void Schema::insertToGroupAndScope(const std::shared_ptr& expression, + f_group_pos groupPos) { KU_ASSERT(!expressionNameToGroupPos.contains(expression->getUniqueName())); expressionNameToGroupPos.insert({expression->getUniqueName(), groupPos}); groups[groupPos]->insertExpression(expression); expressionsInScope.push_back(expression); } -void Schema::insertToScopeMayRepeat( - const std::shared_ptr& expression, uint32_t groupPos) { +void Schema::insertToScopeMayRepeat(const std::shared_ptr& expression, + uint32_t groupPos) { if (expressionNameToGroupPos.contains(expression->getUniqueName())) { return; } insertToScope(expression, groupPos); } -void Schema::insertToGroupAndScopeMayRepeat( - const std::shared_ptr& expression, uint32_t groupPos) { +void Schema::insertToGroupAndScopeMayRepeat(const std::shared_ptr& expression, + uint32_t groupPos) { if (expressionNameToGroupPos.contains(expression->getUniqueName())) { return; } insertToGroupAndScope(expression, groupPos); } -void Schema::insertToGroupAndScope( - const binder::expression_vector& expressions, f_group_pos groupPos) { +void Schema::insertToGroupAndScope(const binder::expression_vector& expressions, + f_group_pos groupPos) { for (auto& expression : expressions) { insertToGroupAndScope(expression, groupPos); } @@ -132,8 +132,8 @@ size_t Schema::getNumGroups(bool isFlat) const { return result; } -f_group_pos SchemaUtils::getLeadingGroupPos( - const std::unordered_set& groupPositions, const Schema& schema) { +f_group_pos SchemaUtils::getLeadingGroupPos(const std::unordered_set& groupPositions, + const Schema& schema) { auto leadingGroupPos = INVALID_F_GROUP_POS; for (auto groupPos : groupPositions) { if (!schema.getGroup(groupPos)->isFlat()) { @@ -157,8 +157,8 @@ void SchemaUtils::validateAtMostOneUnFlatGroup( } } -void SchemaUtils::validateNoUnFlatGroup( - const std::unordered_set& groupPositions, const Schema& schema) { +void SchemaUtils::validateNoUnFlatGroup(const std::unordered_set& groupPositions, + const Schema& schema) { for (auto groupPos : groupPositions) { if (!schema.getGroup(groupPos)->isFlat()) { throw InternalException("Unexpected unFlat factorization group found."); diff --git a/src/planner/plan/CMakeLists.txt b/src/planner/plan/CMakeLists.txt index 5c658dec138..1c26c928621 100644 --- a/src/planner/plan/CMakeLists.txt +++ b/src/planner/plan/CMakeLists.txt @@ -14,6 +14,7 @@ add_library(kuzu_planner_plan_operator append_in_query_call.cpp append_join.cpp append_limit.cpp + append_mark_accumulate.cpp append_multiplicity_reducer.cpp append_order_by.cpp append_projection.cpp diff --git a/src/planner/plan/append_accumulate.cpp b/src/planner/plan/append_accumulate.cpp index 17d76e32b25..26ce1fb20a5 100644 --- a/src/planner/plan/append_accumulate.cpp +++ b/src/planner/plan/append_accumulate.cpp @@ -7,11 +7,21 @@ using namespace kuzu::common; namespace kuzu { namespace planner { -void Planner::appendAccumulate(AccumulateType accumulateType, - const expression_vector& expressionsToFlatten, LogicalPlan& plan) { - auto op = make_shared( - accumulateType, expressionsToFlatten, plan.getLastOperator()); +void Planner::appendAccumulate(AccumulateType accumulateType, LogicalPlan& plan) { + appendAccumulate(accumulateType, expression_vector{}, plan); +} + +void Planner::appendAccumulate(AccumulateType accumulateType, const expression_vector& flatExprs, + LogicalPlan& plan) { + appendAccumulate(accumulateType, flatExprs, nullptr, plan); +} + +void Planner::appendAccumulate(AccumulateType accumulateType, const expression_vector& flatExprs, + std::shared_ptr offset, LogicalPlan& plan) { + auto op = + make_shared(accumulateType, flatExprs, offset, plan.getLastOperator()); appendFlattens(op->getGroupPositionsToFlatten(), plan); + op->setChild(0, plan.getLastOperator()); op->computeFactorizedSchema(); plan.setLastOperator(std::move(op)); } diff --git a/src/planner/plan/append_aggregate.cpp b/src/planner/plan/append_aggregate.cpp index 09fcaebaf29..15a56f36806 100644 --- a/src/planner/plan/append_aggregate.cpp +++ b/src/planner/plan/append_aggregate.cpp @@ -8,8 +8,8 @@ namespace planner { void Planner::appendAggregate(const expression_vector& expressionsToGroupBy, const expression_vector& expressionsToAggregate, LogicalPlan& plan) { - auto aggregate = make_shared( - expressionsToGroupBy, expressionsToAggregate, plan.getLastOperator()); + auto aggregate = make_shared(expressionsToGroupBy, expressionsToAggregate, + plan.getLastOperator()); appendFlattens(aggregate->getGroupsPosToFlattenForGroupBy(), plan); aggregate->setChild(0, plan.getLastOperator()); appendFlattens(aggregate->getGroupsPosToFlattenForAggregate(), plan); diff --git a/src/planner/plan/append_cross_product.cpp b/src/planner/plan/append_cross_product.cpp index 80c7758c6f5..dbaf3dc8a11 100644 --- a/src/planner/plan/append_cross_product.cpp +++ b/src/planner/plan/append_cross_product.cpp @@ -6,16 +6,16 @@ using namespace kuzu::common; namespace kuzu { namespace planner { -void Planner::appendCrossProduct( - AccumulateType accumulateType, LogicalPlan& probePlan, LogicalPlan& buildPlan) { - auto crossProduct = make_shared( - accumulateType, probePlan.getLastOperator(), buildPlan.getLastOperator()); +void Planner::appendCrossProduct(AccumulateType accumulateType, const LogicalPlan& probePlan, + const LogicalPlan& buildPlan, LogicalPlan& resultPlan) { + auto crossProduct = make_shared(accumulateType, + probePlan.getLastOperator(), buildPlan.getLastOperator()); crossProduct->computeFactorizedSchema(); // update cost - probePlan.setCost(probePlan.getCardinality() + buildPlan.getCardinality()); + resultPlan.setCost(probePlan.getCardinality() + buildPlan.getCardinality()); // update cardinality - probePlan.setCardinality(cardinalityEstimator.estimateCrossProduct(probePlan, buildPlan)); - probePlan.setLastOperator(std::move(crossProduct)); + resultPlan.setCardinality(cardinalityEstimator.estimateCrossProduct(probePlan, buildPlan)); + resultPlan.setLastOperator(std::move(crossProduct)); } } // namespace planner diff --git a/src/planner/plan/append_delete.cpp b/src/planner/plan/append_delete.cpp index 4e7f7a9b443..8bd79bebf4e 100644 --- a/src/planner/plan/append_delete.cpp +++ b/src/planner/plan/append_delete.cpp @@ -8,8 +8,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::appendDeleteNode( - const std::vector& boundInfos, LogicalPlan& plan) { +void Planner::appendDeleteNode(const std::vector& boundInfos, + LogicalPlan& plan) { std::vector> infos; infos.reserve(boundInfos.size()); for (auto& boundInfo : boundInfos) { @@ -27,8 +27,8 @@ void Planner::appendDeleteNode( plan.setLastOperator(std::move(deleteNode)); } -void Planner::appendDeleteRel( - const std::vector& boundInfos, LogicalPlan& plan) { +void Planner::appendDeleteRel(const std::vector& boundInfos, + LogicalPlan& plan) { std::vector> rels; for (auto& info : boundInfos) { auto rel = std::static_pointer_cast(info->nodeOrRel); diff --git a/src/planner/plan/append_distinct.cpp b/src/planner/plan/append_distinct.cpp index ec6f620b36e..1fc8f9d06f3 100644 --- a/src/planner/plan/append_distinct.cpp +++ b/src/planner/plan/append_distinct.cpp @@ -6,8 +6,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::appendDistinct(const expression_vector& expressionsToDistinct, LogicalPlan& plan) { - auto distinct = make_shared(expressionsToDistinct, plan.getLastOperator()); +void Planner::appendDistinct(const expression_vector& keys, LogicalPlan& plan) { + auto distinct = make_shared(keys, plan.getLastOperator()); appendFlattens(distinct->getGroupsPosToFlatten(), plan); distinct->setChild(0, plan.getLastOperator()); distinct->computeFactorizedSchema(); diff --git a/src/planner/plan/append_extend.cpp b/src/planner/plan/append_extend.cpp index 9a17a5d64e6..9a35d4172c8 100644 --- a/src/planner/plan/append_extend.cpp +++ b/src/planner/plan/append_extend.cpp @@ -11,7 +11,6 @@ #include "planner/operator/extend/logical_recursive_extend.h" #include "planner/operator/logical_node_label_filter.h" #include "planner/planner.h" -#include "transaction/transaction.h" using namespace kuzu::common; using namespace kuzu::binder; @@ -22,7 +21,7 @@ namespace kuzu { namespace planner { static bool extendHasAtMostOneNbrGuarantee(RelExpression& rel, NodeExpression& boundNode, - ExtendDirection direction, const catalog::Catalog& catalog) { + ExtendDirection direction, const main::ClientContext& clientContext) { if (boundNode.isMultiLabeled()) { return false; } @@ -33,17 +32,19 @@ static bool extendHasAtMostOneNbrGuarantee(RelExpression& rel, NodeExpression& b return false; } auto relDirection = ExtendDirectionUtils::getRelDataDirection(direction); + auto catalog = clientContext.getCatalog(); auto relTableEntry = ku_dynamic_cast( - catalog.getTableCatalogEntry(&DUMMY_READ_TRANSACTION, rel.getSingleTableID())); + catalog->getTableCatalogEntry(clientContext.getTx(), rel.getSingleTableID())); return relTableEntry->isSingleMultiplicity(relDirection); } -static std::unordered_set getBoundNodeTableIDSet( - const RelExpression& rel, ExtendDirection extendDirection, const catalog::Catalog& catalog) { +static std::unordered_set getBoundNodeTableIDSet(const RelExpression& rel, + ExtendDirection extendDirection, const main::ClientContext& clientContext) { std::unordered_set result; + auto catalog = clientContext.getCatalog(); for (auto tableID : rel.getTableIDs()) { auto relTableEntry = ku_dynamic_cast( - catalog.getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID)); + catalog->getTableCatalogEntry(clientContext.getTx(), tableID)); switch (extendDirection) { case ExtendDirection::FWD: { result.insert(relTableEntry->getBoundTableID(RelDataDirection::FWD)); @@ -62,12 +63,13 @@ static std::unordered_set getBoundNodeTableIDSet( return result; } -static std::unordered_set getNbrNodeTableIDSet( - const RelExpression& rel, ExtendDirection extendDirection, const catalog::Catalog& catalog) { +static std::unordered_set getNbrNodeTableIDSet(const RelExpression& rel, + ExtendDirection extendDirection, const main::ClientContext& clientContext) { std::unordered_set result; + auto catalog = clientContext.getCatalog(); for (auto tableID : rel.getTableIDs()) { auto relTableEntry = ku_dynamic_cast( - catalog.getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID)); + catalog->getTableCatalogEntry(clientContext.getTx(), tableID)); switch (extendDirection) { case ExtendDirection::FWD: { result.insert(relTableEntry->getNbrTableID(RelDataDirection::FWD)); @@ -101,12 +103,13 @@ void Planner::appendNonRecursiveExtend(const std::shared_ptr& bo ExtendDirection direction, const expression_vector& properties, LogicalPlan& plan) { // Filter bound node label if we know some incoming nodes won't have any outgoing rel. This // cannot be done at binding time because the pruning is affected by extend direction. - auto boundNodeTableIDSet = getBoundNodeTableIDSet(*rel, direction, *catalog); + auto boundNodeTableIDSet = getBoundNodeTableIDSet(*rel, direction, *clientContext); if (boundNode->getNumTableIDs() > boundNodeTableIDSet.size()) { appendNodeLabelFilter(boundNode->getInternalID(), boundNodeTableIDSet, plan); } // Check for each bound node, can we extend to more than 1 nbr node. - auto hasAtMostOneNbr = extendHasAtMostOneNbrGuarantee(*rel, *boundNode, direction, *catalog); + auto hasAtMostOneNbr = + extendHasAtMostOneNbrGuarantee(*rel, *boundNode, direction, *clientContext); auto properties_ = properties; auto iri = getIRIProperty(properties); if (iri != nullptr) { @@ -116,18 +119,19 @@ void Planner::appendNonRecursiveExtend(const std::shared_ptr& bo properties_ = ExpressionUtil::removeDuplication(properties_); } // Append extend - auto extend = make_shared( - boundNode, nbrNode, rel, direction, properties_, hasAtMostOneNbr, plan.getLastOperator()); + auto extend = make_shared(boundNode, nbrNode, rel, direction, properties_, + hasAtMostOneNbr, plan.getLastOperator()); appendFlattens(extend->getGroupsPosToFlatten(), plan); extend->setChild(0, plan.getLastOperator()); extend->computeFactorizedSchema(); // Update cost & cardinality. Note that extend does not change cardinality. plan.setCost(CostModel::computeExtendCost(plan)); - auto extensionRate = cardinalityEstimator.getExtensionRate(*rel, *boundNode); + auto extensionRate = + cardinalityEstimator.getExtensionRate(*rel, *boundNode, clientContext->getTx()); auto group = extend->getSchema()->getGroup(nbrNode->getInternalID()); group->setMultiplier(extensionRate); plan.setLastOperator(std::move(extend)); - auto nbrNodeTableIDSet = getNbrNodeTableIDSet(*rel, direction, *catalog); + auto nbrNodeTableIDSet = getNbrNodeTableIDSet(*rel, direction, *clientContext); if (nbrNodeTableIDSet.size() > nbrNode->getNumTableIDs()) { appendNodeLabelFilter(nbrNode->getInternalID(), nbrNode->getTableIDsSet(), plan); } @@ -136,11 +140,13 @@ void Planner::appendNonRecursiveExtend(const std::shared_ptr& bo auto rdfInfo = rel->getRdfPredicateInfo(); // Append hash join for remaining properties auto tmpPlan = std::make_unique(); - cardinalityEstimator.addNodeIDDom(*rdfInfo->predicateID, rdfInfo->resourceTableIDs); + cardinalityEstimator.addNodeIDDom(*rdfInfo->predicateID, rdfInfo->resourceTableIDs, + clientContext->getTx()); appendScanInternalID(rdfInfo->predicateID, rdfInfo->resourceTableIDs, *tmpPlan); - appendScanNodeProperties( - rdfInfo->predicateID, rdfInfo->resourceTableIDs, expression_vector{iri}, *tmpPlan); - appendHashJoin(expression_vector{rdfInfo->predicateID}, JoinType::INNER, plan, *tmpPlan); + appendScanNodeProperties(rdfInfo->predicateID, rdfInfo->resourceTableIDs, + expression_vector{iri}, *tmpPlan); + appendHashJoin(expression_vector{rdfInfo->predicateID}, JoinType::INNER, plan, *tmpPlan, + plan); } } @@ -154,8 +160,8 @@ void Planner::appendRecursiveExtend(const std::shared_ptr& bound createRecursivePlan(*recursiveInfo, direction, *recursivePlan); // Create recursive extend if (boundNode->getNumTableIDs() > recursiveInfo->node->getNumTableIDs()) { - appendNodeLabelFilter( - boundNode->getInternalID(), recursiveInfo->node->getTableIDsSet(), plan); + appendNodeLabelFilter(boundNode->getInternalID(), recursiveInfo->node->getTableIDsSet(), + plan); } auto extend = std::make_shared(boundNode, nbrNode, rel, direction, RecursiveJoinType::TRACK_PATH, plan.getLastOperator(), recursivePlan->getLastOperator()); @@ -167,8 +173,8 @@ void Planner::appendRecursiveExtend(const std::shared_ptr& bound std::shared_ptr nodeScanRoot; if (!recursiveInfo->nodeProjectionList.empty()) { auto pathNodePropertyScanPlan = std::make_unique(); - createPathNodePropertyScanPlan( - recursiveInfo->node, recursiveInfo->nodeProjectionList, *pathNodePropertyScanPlan); + createPathNodePropertyScanPlan(recursiveInfo->node, recursiveInfo->nodeProjectionList, + *pathNodePropertyScanPlan); nodeScanRoot = pathNodePropertyScanPlan->getLastOperator(); } // Create path rel property scan plan @@ -184,8 +190,8 @@ void Planner::appendRecursiveExtend(const std::shared_ptr& bound relScanCardinality = pathRelPropertyScanPlan->getCardinality(); } // Create path property probe - auto pathPropertyProbe = std::make_shared( - rel, extend, nodeScanRoot, relScanRoot, RecursiveJoinType::TRACK_PATH); + auto pathPropertyProbe = std::make_shared(rel, extend, nodeScanRoot, + relScanRoot, RecursiveJoinType::TRACK_PATH); pathPropertyProbe->computeFactorizedSchema(); // Check for sip auto ratio = plan.getCardinality() / relScanCardinality; @@ -194,10 +200,12 @@ void Planner::appendRecursiveExtend(const std::shared_ptr& bound } plan.setLastOperator(std::move(pathPropertyProbe)); // Update cost - auto extensionRate = cardinalityEstimator.getExtensionRate(*rel, *boundNode); + auto extensionRate = + cardinalityEstimator.getExtensionRate(*rel, *boundNode, clientContext->getTx()); plan.setCost(CostModel::computeRecursiveExtendCost(rel->getUpperBound(), extensionRate, plan)); // Update cardinality - auto hasAtMostOneNbr = extendHasAtMostOneNbrGuarantee(*rel, *boundNode, direction, *catalog); + auto hasAtMostOneNbr = + extendHasAtMostOneNbrGuarantee(*rel, *boundNode, direction, *clientContext); if (!hasAtMostOneNbr) { auto group = plan.getSchema()->getGroup(nbrNode->getInternalID()); group->setMultiplier(extensionRate); @@ -211,13 +219,13 @@ static expression_vector collectPropertiesToRead(const std::shared_ptr( - boundNode->getInternalID(), recursiveInfo.nodePredicateExecFlag); + auto scanFrontier = std::make_shared(boundNode->getInternalID(), + recursiveInfo.nodePredicateExecFlag); scanFrontier->computeFactorizedSchema(); plan.setLastOperator(std::move(scanFrontier)); auto nodeProperties = collectPropertiesToRead(recursiveInfo.nodePredicate); @@ -239,8 +247,8 @@ void Planner::createRecursivePlan( appendNonRecursiveExtend(boundNode, nbrNode, rel, direction, ExpressionUtil::removeDuplication(relProperties), plan); auto rdfInfo = rel->getRdfPredicateInfo(); - appendScanNodeProperties( - rdfInfo->predicateID, rdfInfo->resourceTableIDs, expression_vector{iri}, plan); + appendScanNodeProperties(rdfInfo->predicateID, rdfInfo->resourceTableIDs, + expression_vector{iri}, plan); } else { appendNonRecursiveExtend(boundNode, nbrNode, rel, direction, ExpressionUtil::removeDuplication(relProperties), plan); @@ -266,8 +274,8 @@ void Planner::createPathRelPropertyScanPlan(const std::shared_ptr nodeID, std::unordered_set tableIDSet, LogicalPlan& plan) { - auto filter = std::make_shared( - std::move(nodeID), std::move(tableIDSet), plan.getLastOperator()); + auto filter = std::make_shared(std::move(nodeID), std::move(tableIDSet), + plan.getLastOperator()); filter->computeFactorizedSchema(); plan.setLastOperator(std::move(filter)); } diff --git a/src/planner/plan/append_filter.cpp b/src/planner/plan/append_filter.cpp index ae218d0ecd5..443e1df89d7 100644 --- a/src/planner/plan/append_filter.cpp +++ b/src/planner/plan/append_filter.cpp @@ -6,8 +6,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::appendFilters( - const binder::expression_vector& predicates, kuzu::planner::LogicalPlan& plan) { +void Planner::appendFilters(const binder::expression_vector& predicates, + kuzu::planner::LogicalPlan& plan) { for (auto& predicate : predicates) { appendFilter(predicate, plan); } diff --git a/src/planner/plan/append_insert.cpp b/src/planner/plan/append_insert.cpp index 2c8fc4a782b..f677ee3c89d 100644 --- a/src/planner/plan/append_insert.cpp +++ b/src/planner/plan/append_insert.cpp @@ -33,8 +33,8 @@ std::unique_ptr Planner::createLogicalInsertInfo(const BoundI return insertInfo; } -void Planner::appendInsertNode( - const std::vector& boundInsertInfos, LogicalPlan& plan) { +void Planner::appendInsertNode(const std::vector& boundInsertInfos, + LogicalPlan& plan) { std::vector logicalInfos; logicalInfos.reserve(boundInsertInfos.size()); for (auto& boundInfo : boundInsertInfos) { @@ -48,8 +48,8 @@ void Planner::appendInsertNode( plan.setLastOperator(insertNode); } -void Planner::appendInsertRel( - const std::vector& boundInsertInfos, LogicalPlan& plan) { +void Planner::appendInsertRel(const std::vector& boundInsertInfos, + LogicalPlan& plan) { std::vector logicalInfos; logicalInfos.reserve(boundInsertInfos.size()); for (auto& boundInfo : boundInsertInfos) { diff --git a/src/planner/plan/append_join.cpp b/src/planner/plan/append_join.cpp index b071e3d2bdb..ca1cf1cf39f 100644 --- a/src/planner/plan/append_join.cpp +++ b/src/planner/plan/append_join.cpp @@ -9,13 +9,13 @@ namespace kuzu { namespace planner { void Planner::appendHashJoin(const binder::expression_vector& joinNodeIDs, JoinType joinType, - LogicalPlan& probePlan, LogicalPlan& buildPlan) { + LogicalPlan& probePlan, LogicalPlan& buildPlan, LogicalPlan& resultPlan) { std::vector joinConditions; for (auto& joinNodeID : joinNodeIDs) { joinConditions.emplace_back(joinNodeID, joinNodeID); } - auto hashJoin = make_shared( - joinConditions, joinType, probePlan.getLastOperator(), buildPlan.getLastOperator()); + auto hashJoin = make_shared(joinConditions, joinType, + probePlan.getLastOperator(), buildPlan.getLastOperator()); // Apply flattening to probe side auto groupsPosToFlattenOnProbeSide = hashJoin->getGroupsPosToFlattenOnProbeSide(); appendFlattens(groupsPosToFlattenOnProbeSide, probePlan); @@ -32,11 +32,11 @@ void Planner::appendHashJoin(const binder::expression_vector& joinNodeIDs, JoinT hashJoin->setSIP(SidewaysInfoPassing::PROHIBIT_BUILD_TO_PROBE); } // Update cost - probePlan.setCost(CostModel::computeHashJoinCost(joinNodeIDs, probePlan, buildPlan)); + resultPlan.setCost(CostModel::computeHashJoinCost(joinNodeIDs, probePlan, buildPlan)); // Update cardinality - probePlan.setCardinality( + resultPlan.setCardinality( cardinalityEstimator.estimateHashJoin(joinNodeIDs, probePlan, buildPlan)); - probePlan.setLastOperator(std::move(hashJoin)); + resultPlan.setLastOperator(std::move(hashJoin)); } void Planner::appendMarkJoin(const binder::expression_vector& joinNodeIDs, @@ -46,8 +46,8 @@ void Planner::appendMarkJoin(const binder::expression_vector& joinNodeIDs, for (auto& joinNodeID : joinNodeIDs) { joinConditions.emplace_back(joinNodeID, joinNodeID); } - auto hashJoin = make_shared( - joinConditions, mark, probePlan.getLastOperator(), buildPlan.getLastOperator()); + auto hashJoin = make_shared(joinConditions, mark, probePlan.getLastOperator(), + buildPlan.getLastOperator()); // Apply flattening to probe side appendFlattens(hashJoin->getGroupsPosToFlattenOnProbeSide(), probePlan); hashJoin->setChild(0, probePlan.getLastOperator()); diff --git a/src/planner/plan/append_mark_accumulate.cpp b/src/planner/plan/append_mark_accumulate.cpp new file mode 100644 index 00000000000..83d34dd0324 --- /dev/null +++ b/src/planner/plan/append_mark_accumulate.cpp @@ -0,0 +1,20 @@ +#include "planner/operator/logical_mark_accmulate.h" +#include "planner/planner.h" + +using namespace kuzu::binder; + +namespace kuzu { +namespace planner { + +void Planner::appendMarkAccumulate(const expression_vector& keys, std::shared_ptr mark, + LogicalPlan& plan) { + auto markAccumulate = + std::make_shared(keys, mark, plan.getLastOperator()); + appendFlattens(markAccumulate->getGroupsPosToFlatten(), plan); + markAccumulate->setChild(0, plan.getLastOperator()); + markAccumulate->computeFactorizedSchema(); + plan.setLastOperator(std::move(markAccumulate)); +} + +} // namespace planner +} // namespace kuzu diff --git a/src/planner/plan/append_order_by.cpp b/src/planner/plan/append_order_by.cpp index e2a74a08cca..461cdf98d4f 100644 --- a/src/planner/plan/append_order_by.cpp +++ b/src/planner/plan/append_order_by.cpp @@ -6,8 +6,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::appendOrderBy( - const expression_vector& expressions, const std::vector& isAscOrders, LogicalPlan& plan) { +void Planner::appendOrderBy(const expression_vector& expressions, + const std::vector& isAscOrders, LogicalPlan& plan) { auto orderBy = make_shared(expressions, isAscOrders, plan.getLastOperator()); appendFlattens(orderBy->getGroupsPosToFlatten(), plan); orderBy->setChild(0, plan.getLastOperator()); diff --git a/src/planner/plan/append_scan_file.cpp b/src/planner/plan/append_scan_file.cpp index 1672a06ea06..923db472470 100644 --- a/src/planner/plan/append_scan_file.cpp +++ b/src/planner/plan/append_scan_file.cpp @@ -6,9 +6,14 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::appendScanFile(const BoundFileScanInfo* fileScanInfo, LogicalPlan& plan) { +void Planner::appendScanFile(const BoundFileScanInfo* info, LogicalPlan& plan) { + appendScanFile(info, nullptr /* offset */, plan); +} + +void Planner::appendScanFile(const binder::BoundFileScanInfo* info, + std::shared_ptr offset, kuzu::planner::LogicalPlan& plan) { KU_ASSERT(plan.isEmpty()); - auto scanFile = std::make_shared(fileScanInfo->copy()); + auto scanFile = std::make_shared(info->copy(), offset); scanFile->computeFactorizedSchema(); plan.setLastOperator(std::move(scanFile)); } diff --git a/src/planner/plan/append_scan_node.cpp b/src/planner/plan/append_scan_node.cpp index 100982d1d32..1ec6ea01591 100644 --- a/src/planner/plan/append_scan_node.cpp +++ b/src/planner/plan/append_scan_node.cpp @@ -9,8 +9,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::appendScanInternalID( - std::shared_ptr internalID, std::vector tableIDs, LogicalPlan& plan) { +void Planner::appendScanInternalID(std::shared_ptr internalID, + std::vector tableIDs, LogicalPlan& plan) { KU_ASSERT(plan.isEmpty()); auto scan = make_shared(std::move(internalID), std::move(tableIDs)); scan->computeFactorizedSchema(); @@ -33,8 +33,8 @@ void Planner::appendScanNodeProperties(std::shared_ptr nodeID, if (propertiesToScan_.empty()) { return; } - auto scanNodeProperty = make_shared( - std::move(nodeID), std::move(tableIDs), propertiesToScan_, plan.getLastOperator()); + auto scanNodeProperty = make_shared(std::move(nodeID), + std::move(tableIDs), propertiesToScan_, plan.getLastOperator()); scanNodeProperty->computeFactorizedSchema(); plan.setLastOperator(std::move(scanNodeProperty)); } diff --git a/src/planner/plan/append_set.cpp b/src/planner/plan/append_set.cpp index 94a0bd4cd28..364606a8b44 100644 --- a/src/planner/plan/append_set.cpp +++ b/src/planner/plan/append_set.cpp @@ -9,8 +9,8 @@ namespace planner { std::unique_ptr Planner::createLogicalSetPropertyInfo( const BoundSetPropertyInfo* boundSetPropertyInfo) { - return std::make_unique( - boundSetPropertyInfo->nodeOrRel, boundSetPropertyInfo->setItem); + return std::make_unique(boundSetPropertyInfo->nodeOrRel, + boundSetPropertyInfo->setItem); } void Planner::appendSetNodeProperty( diff --git a/src/planner/plan/append_simple.cpp b/src/planner/plan/append_simple.cpp index cfff08a68e7..5765caf6cdb 100644 --- a/src/planner/plan/append_simple.cpp +++ b/src/planner/plan/append_simple.cpp @@ -1,5 +1,7 @@ +#include "binder/bound_attach_database.h" #include "binder/bound_comment_on.h" #include "binder/bound_create_macro.h" +#include "binder/bound_detach_database.h" #include "binder/bound_explain.h" #include "binder/bound_extension_statement.h" #include "binder/bound_standalone_call.h" @@ -11,8 +13,10 @@ #include "planner/operator/ddl/logical_alter.h" #include "planner/operator/ddl/logical_create_table.h" #include "planner/operator/ddl/logical_drop_table.h" +#include "planner/operator/logical_attach_database.h" #include "planner/operator/logical_comment_on.h" #include "planner/operator/logical_create_macro.h" +#include "planner/operator/logical_detach_database.h" #include "planner/operator/logical_explain.h" #include "planner/operator/logical_extension.h" #include "planner/operator/logical_standalone_call.h" @@ -28,8 +32,8 @@ namespace planner { void Planner::appendCreateTable(const BoundStatement& statement, LogicalPlan& plan) { auto& creatTable = ku_dynamic_cast(statement); auto info = creatTable.getInfo(); - auto op = make_shared( - info->tableName, info->copy(), statement.getStatementResult()->getSingleColumnExpr()); + auto op = make_shared(info->tableName, info->copy(), + statement.getStatementResult()->getSingleColumnExpr()); plan.setLastOperator(std::move(op)); } @@ -43,16 +47,16 @@ void Planner::appendDropTable(const BoundStatement& statement, LogicalPlan& plan void Planner::appendAlter(const BoundStatement& statement, LogicalPlan& plan) { auto& alter = ku_dynamic_cast(statement); auto info = alter.getInfo(); - auto op = std::make_shared( - info->copy(), info->tableName, statement.getStatementResult()->getSingleColumnExpr()); + auto op = std::make_shared(info->copy(), info->tableName, + statement.getStatementResult()->getSingleColumnExpr()); plan.setLastOperator(std::move(op)); } void Planner::appendStandaloneCall(const BoundStatement& statement, LogicalPlan& plan) { auto& standaloneCallClause = ku_dynamic_cast(statement); - auto op = make_shared( - standaloneCallClause.getOption(), standaloneCallClause.getOptionValue()); + auto op = make_shared(standaloneCallClause.getOption(), + standaloneCallClause.getOptionValue()); plan.setLastOperator(std::move(op)); } @@ -91,10 +95,27 @@ void Planner::appendTransaction(const BoundStatement& statement, LogicalPlan& pl void Planner::appendExtension(const BoundStatement& statement, LogicalPlan& plan) { auto& extensionStatement = common::ku_dynamic_cast(statement); - auto op = std::make_shared( - extensionStatement.getAction(), extensionStatement.getPath()); + auto op = std::make_shared(extensionStatement.getAction(), + extensionStatement.getPath()); plan.setLastOperator(std::move(op)); } +void Planner::appendAttachDatabase(const BoundStatement& statement, LogicalPlan& plan) { + auto& boundAttachDatabase = + common::ku_dynamic_cast( + statement); + auto attachDatabase = + std::make_shared(boundAttachDatabase.getAttachInfo()); + plan.setLastOperator(std::move(attachDatabase)); +} + +void Planner::appendDetachDatabase(const BoundStatement& statement, LogicalPlan& plan) { + auto& boundDetachDatabase = + common::ku_dynamic_cast( + statement); + auto detachDatabase = std::make_shared(boundDetachDatabase.getDBName()); + plan.setLastOperator(std::move(detachDatabase)); +} + } // namespace planner } // namespace kuzu diff --git a/src/planner/plan/append_unwind.cpp b/src/planner/plan/append_unwind.cpp index 5a740392d4d..f3517ec77db 100644 --- a/src/planner/plan/append_unwind.cpp +++ b/src/planner/plan/append_unwind.cpp @@ -3,14 +3,16 @@ #include "planner/planner.h" using namespace kuzu::binder; +using namespace kuzu::common; namespace kuzu { namespace planner { -void Planner::appendUnwind(const BoundReadingClause& boundReadingClause, LogicalPlan& plan) { - auto& boundUnwindClause = (BoundUnwindClause&)boundReadingClause; - auto unwind = make_shared( - boundUnwindClause.getInExpr(), boundUnwindClause.getOutExpr(), plan.getLastOperator()); +void Planner::appendUnwind(const BoundReadingClause& readingClause, LogicalPlan& plan) { + auto& unwindClause = + ku_dynamic_cast(readingClause); + auto unwind = make_shared(unwindClause.getInExpr(), unwindClause.getOutExpr(), + unwindClause.getIDExpr(), plan.getLastOperator()); appendFlattens(unwind->getGroupsPosToFlatten(), plan); unwind->setChild(0, plan.getLastOperator()); unwind->computeFactorizedSchema(); diff --git a/src/planner/plan/plan_copy.cpp b/src/planner/plan/plan_copy.cpp index 4917a1ca9a8..0abb3846fc1 100644 --- a/src/planner/plan/plan_copy.cpp +++ b/src/planner/plan/plan_copy.cpp @@ -30,7 +30,7 @@ static void appendPartitioner(const BoundCopyFromInfo& copyFromInfo, LogicalPlan for (auto& column : extraInfo->propertyColumns) { payloads.push_back(column); } - payloads.push_back(copyFromInfo.fileScanInfo->offset); + payloads.push_back(copyFromInfo.offset); for (auto& lookupInfo : extraInfo->infos) { payloads.push_back(lookupInfo.offset); } @@ -53,8 +53,8 @@ static void appendPartitioner(const BoundCopyFromInfo& copyFromInfo, LogicalPlan plan.setLastOperator(std::move(partitioner)); } -static void appendCopyFrom( - const BoundCopyFromInfo& info, expression_vector outExprs, LogicalPlan& plan) { +static void appendCopyFrom(const BoundCopyFromInfo& info, expression_vector outExprs, + LogicalPlan& plan) { auto op = make_shared(info.copy(), std::move(outExprs), plan.getLastOperator()); op->computeFactorizedSchema(); @@ -81,29 +81,60 @@ std::unique_ptr Planner::planCopyFrom(const BoundStatement& stateme } } -std::unique_ptr Planner::planCopyNodeFrom( - const BoundCopyFromInfo* info, binder::expression_vector results) { +std::unique_ptr Planner::planCopyNodeFrom(const BoundCopyFromInfo* info, + binder::expression_vector results) { auto plan = std::make_unique(); - auto scanInfo = info->fileScanInfo.get(); - appendScanFile(scanInfo, *plan); + switch (info->source->type) { + case ScanSourceType::FILE: { + auto fileSource = + ku_dynamic_cast(info->source.get()); + appendScanFile(&fileSource->fileScanInfo, *plan); + } break; + case ScanSourceType::QUERY: { + auto querySource = + ku_dynamic_cast(info->source.get()); + plan = getBestPlan(planQuery(*querySource->statement)); + appendAccumulate(AccumulateType::REGULAR, plan->getSchema()->getExpressionsInScope(), + info->offset, *plan); + } break; + default: + KU_UNREACHABLE; + } appendCopyFrom(*info, results, *plan); return plan; } -std::unique_ptr Planner::planCopyResourceFrom( - const BoundCopyFromInfo* info, binder::expression_vector results) { +std::unique_ptr Planner::planCopyResourceFrom(const BoundCopyFromInfo* info, + binder::expression_vector results) { auto plan = std::make_unique(); - auto scanInfo = info->fileScanInfo.get(); - appendScanFile(scanInfo, *plan); - appendDistinct(scanInfo->columns, *plan); + KU_ASSERT(info->source->type == ScanSourceType::FILE); + auto fileSource = + ku_dynamic_cast(info->source.get()); + appendScanFile(&fileSource->fileScanInfo, *plan); + appendDistinct(fileSource->fileScanInfo.columns, *plan); appendCopyFrom(*info, results, *plan); return plan; } -std::unique_ptr Planner::planCopyRelFrom( - const BoundCopyFromInfo* info, binder::expression_vector results) { +std::unique_ptr Planner::planCopyRelFrom(const BoundCopyFromInfo* info, + binder::expression_vector results) { auto plan = std::make_unique(); - appendScanFile(info->fileScanInfo.get(), *plan); + switch (info->source->type) { + case ScanSourceType::FILE: { + auto fileSource = + ku_dynamic_cast(info->source.get()); + appendScanFile(&fileSource->fileScanInfo, info->offset, *plan); + } break; + case ScanSourceType::QUERY: { + auto querySource = + ku_dynamic_cast(info->source.get()); + plan = getBestPlan(planQuery(*querySource->statement)); + appendAccumulate(AccumulateType::REGULAR, plan->getSchema()->getExpressionsInScope(), + info->offset, *plan); + } break; + default: + KU_UNREACHABLE; + } auto extraInfo = ku_dynamic_cast(info->extraInfo.get()); appendIndexScan(copyVector(extraInfo->infos), *plan); @@ -112,8 +143,8 @@ std::unique_ptr Planner::planCopyRelFrom( return plan; } -std::unique_ptr Planner::planCopyRdfFrom( - const BoundCopyFromInfo* info, binder::expression_vector results) { +std::unique_ptr Planner::planCopyRdfFrom(const BoundCopyFromInfo* info, + binder::expression_vector results) { auto extraRdfInfo = ku_dynamic_cast(info->extraInfo.get()); auto rPlan = planCopyResourceFrom(&extraRdfInfo->rInfo, results); @@ -122,9 +153,11 @@ std::unique_ptr Planner::planCopyRdfFrom( auto rrlPlan = planCopyRelFrom(&extraRdfInfo->rrlInfo, results); auto children = logical_op_vector_t{rrlPlan->getLastOperator(), rrrPlan->getLastOperator(), lPlan->getLastOperator(), rPlan->getLastOperator()}; - if (info->fileScanInfo != nullptr) { + if (info->source->type == ScanSourceType::FILE) { auto readerPlan = LogicalPlan(); - appendScanFile(info->fileScanInfo.get(), readerPlan); + auto fileSource = + ku_dynamic_cast(info->source.get()); + appendScanFile(&fileSource->fileScanInfo, readerPlan); children.push_back(readerPlan.getLastOperator()); } auto resultPlan = std::make_unique(); @@ -137,11 +170,16 @@ std::unique_ptr Planner::planCopyRdfFrom( std::unique_ptr Planner::planCopyTo(const BoundStatement& statement) { auto& boundCopy = ku_dynamic_cast(statement); auto regularQuery = boundCopy.getRegularQuery(); + std::vector columnNames; + std::vector columnTypes; + for (auto& column : regularQuery->getStatementResult()->getColumns()) { + columnNames.push_back(column->toString()); + columnTypes.push_back(column->dataType); + } KU_ASSERT(regularQuery->getStatementType() == StatementType::QUERY); auto plan = getBestPlan(*regularQuery); auto copyTo = make_shared(boundCopy.getFilePath(), boundCopy.getFileType(), - boundCopy.getColumnNames(), boundCopy.getColumnTypesRef(), - boundCopy.getCopyOption()->copy(), plan->getLastOperator()); + columnNames, columnTypes, boundCopy.getCopyOption()->copy(), plan->getLastOperator()); plan->setLastOperator(std::move(copyTo)); return plan; } diff --git a/src/planner/plan/plan_join_order.cpp b/src/planner/plan/plan_join_order.cpp index 846f23905dd..d7942bdf443 100644 --- a/src/planner/plan/plan_join_order.cpp +++ b/src/planner/plan/plan_join_order.cpp @@ -25,8 +25,8 @@ std::unique_ptr Planner::planQueryGraphCollectionInNewContext( return getBestPlan(std::move(plans)); } -static int32_t getConnectedQueryGraphIdx( - const QueryGraphCollection& queryGraphCollection, const expression_set& expressionSet) { +static int32_t getConnectedQueryGraphIdx(const QueryGraphCollection& queryGraphCollection, + const expression_set& expressionSet) { for (auto i = 0u; i < queryGraphCollection.getNumQueryGraphs(); ++i) { auto queryGraph = queryGraphCollection.getQueryGraph(i); for (auto& queryNode : queryGraph->getQueryNodes()) { @@ -66,8 +66,8 @@ std::vector> Planner::enumerateQueryGraphCollection predicateToEvaluateIndices.insert(j); } } - evaluatedPredicatesIndices.insert( - predicateToEvaluateIndices.begin(), predicateToEvaluateIndices.end()); + evaluatedPredicatesIndices.insert(predicateToEvaluateIndices.begin(), + predicateToEvaluateIndices.end()); expression_vector predicatesToEvaluate; for (auto idx : predicateToEvaluateIndices) { predicatesToEvaluate.push_back(predicates[idx]); @@ -76,8 +76,8 @@ std::vector> Planner::enumerateQueryGraphCollection switch (context.subqueryType) { case SubqueryType::NONE: { // Plan current query graph as an isolated query graph. - plans = enumerateQueryGraph( - SubqueryType::NONE, expression_vector{}, *queryGraph, predicatesToEvaluate); + plans = enumerateQueryGraph(SubqueryType::NONE, expression_vector{}, *queryGraph, + predicatesToEvaluate); } break; case SubqueryType::INTERNAL_ID_CORRELATED: { // All correlated expressions are node IDs. Plan as isolated query graph but do not scan @@ -92,8 +92,8 @@ std::vector> Planner::enumerateQueryGraphCollection *queryGraph, predicatesToEvaluate); } else { // Plan current query graph as an isolated query graph. - plans = enumerateQueryGraph( - SubqueryType::NONE, expression_vector{}, *queryGraph, predicatesToEvaluate); + plans = enumerateQueryGraph(SubqueryType::NONE, expression_vector{}, *queryGraph, + predicatesToEvaluate); } } break; default: @@ -136,7 +136,7 @@ std::vector> Planner::enumerateQueryGraph(SubqueryT const expression_vector& correlatedExpressions, const QueryGraph& queryGraph, expression_vector& predicates) { context.init(&queryGraph, predicates); - cardinalityEstimator.initNodeIDDom(queryGraph); + cardinalityEstimator.initNodeIDDom(queryGraph, clientContext->getTx()); planBaseTableScans(subqueryType, correlatedExpressions); context.currentLevel++; while (context.currentLevel < context.maxLevel) { @@ -194,12 +194,12 @@ static expression_vector getNewlyMatchedExpressions(const std::vector{prevSubgraph}, newSubgraph, expressions); + return getNewlyMatchedExpressions(std::vector{prevSubgraph}, newSubgraph, + expressions); } -void Planner::planBaseTableScans( - SubqueryType subqueryType, const expression_vector& correlatedExpressions) { +void Planner::planBaseTableScans(SubqueryType subqueryType, + const expression_vector& correlatedExpressions) { auto queryGraph = context.getQueryGraph(); auto correlatedExpressionSet = expression_set{correlatedExpressions.begin(), correlatedExpressions.end()}; @@ -256,8 +256,8 @@ void Planner::planCorrelatedExpressionsScan( auto plan = std::make_unique(); appendExpressionsScan(correlatedExpressions, *plan); plan->setCardinality(context.correlatedExpressionsCardinality); - auto predicates = getNewlyMatchedExpressions( - context.getEmptySubqueryGraph(), newSubgraph, context.getWhereExpressions()); + auto predicates = getNewlyMatchedExpressions(context.getEmptySubqueryGraph(), newSubgraph, + context.getWhereExpressions()); appendFilters(predicates, *plan); appendDistinct(correlatedExpressions, *plan); context.addPlan(newSubgraph, std::move(plan)); @@ -271,8 +271,8 @@ void Planner::planNodeScan(uint32_t nodePos) { appendScanInternalID(node->getInternalID(), node->getTableIDs(), *plan); auto properties = getProperties(*node); appendScanNodeProperties(node->getInternalID(), node->getTableIDs(), properties, *plan); - auto predicates = getNewlyMatchedExpressions( - context.getEmptySubqueryGraph(), newSubgraph, context.getWhereExpressions()); + auto predicates = getNewlyMatchedExpressions(context.getEmptySubqueryGraph(), newSubgraph, + context.getWhereExpressions()); appendFilters(predicates, *plan); context.addPlan(newSubgraph, std::move(plan)); } @@ -298,8 +298,8 @@ void Planner::planRelScan(uint32_t relPos) { auto rel = context.queryGraph->getQueryRel(relPos); auto newSubgraph = context.getEmptySubqueryGraph(); newSubgraph.addQueryRel(relPos); - auto predicates = getNewlyMatchedExpressions( - context.getEmptySubqueryGraph(), newSubgraph, context.getWhereExpressions()); + auto predicates = getNewlyMatchedExpressions(context.getEmptySubqueryGraph(), newSubgraph, + context.getWhereExpressions()); // Regardless of whether rel is directed or not, // we always enumerate two plans, one from src to dst, and the other from dst to src. for (auto direction : {ExtendDirection::FWD, ExtendDirection::BWD}) { @@ -452,8 +452,8 @@ void Planner::planWCOJoin(const SubqueryGraph& subgraph, for (auto& relPlan : relPlans) { rightPlansCopy.push_back(relPlan->shallowCopy()); } - appendIntersect( - intersectNode->getInternalID(), boundNodeIDs, *leftPlanCopy, rightPlansCopy); + appendIntersect(intersectNode->getInternalID(), boundNodeIDs, *leftPlanCopy, + rightPlansCopy); for (auto& predicate : predicates) { appendFilter(predicate, *leftPlanCopy); } @@ -467,8 +467,8 @@ void Planner::planWCOJoin(const SubqueryGraph& subgraph, // We prune such join. // Note that this does not mean we may lose good plan. An equivalent join can be found between [e2] // and (a)-[e1]->(b). -static bool needPruneImplicitJoins( - const SubqueryGraph& leftSubgraph, const SubqueryGraph& rightSubgraph, uint32_t numJoinNodes) { +static bool needPruneImplicitJoins(const SubqueryGraph& leftSubgraph, + const SubqueryGraph& rightSubgraph, uint32_t numJoinNodes) { auto leftNodePositions = leftSubgraph.getNodePositionsIgnoringNodeSelector(); auto rightNodePositions = rightSubgraph.getNodePositionsIgnoringNodeSelector(); auto intersectionSize = 0u; @@ -561,8 +561,8 @@ void Planner::planInnerHashJoin(const SubqueryGraph& subgraph, const SubqueryGra if (CostModel::computeHashJoinCost(joinNodeIDs, *leftPlan, *rightPlan) < maxCost) { auto leftPlanProbeCopy = leftPlan->shallowCopy(); auto rightPlanBuildCopy = rightPlan->shallowCopy(); - appendHashJoin( - joinNodeIDs, JoinType::INNER, *leftPlanProbeCopy, *rightPlanBuildCopy); + appendHashJoin(joinNodeIDs, JoinType::INNER, *leftPlanProbeCopy, + *rightPlanBuildCopy, *leftPlanProbeCopy); appendFilters(predicates, *leftPlanProbeCopy); context.addPlan(newSubgraph, std::move(leftPlanProbeCopy)); } @@ -571,8 +571,8 @@ void Planner::planInnerHashJoin(const SubqueryGraph& subgraph, const SubqueryGra CostModel::computeHashJoinCost(joinNodeIDs, *rightPlan, *leftPlan) < maxCost) { auto leftPlanBuildCopy = leftPlan->shallowCopy(); auto rightPlanProbeCopy = rightPlan->shallowCopy(); - appendHashJoin( - joinNodeIDs, JoinType::INNER, *rightPlanProbeCopy, *leftPlanBuildCopy); + appendHashJoin(joinNodeIDs, JoinType::INNER, *rightPlanProbeCopy, + *leftPlanBuildCopy, *rightPlanProbeCopy); appendFilters(predicates, *rightPlanProbeCopy); context.addPlan(newSubgraph, std::move(rightPlanProbeCopy)); } @@ -588,7 +588,8 @@ std::vector> Planner::planCrossProduct( for (auto& rightPlan : rightPlans) { auto leftPlanCopy = leftPlan->shallowCopy(); auto rightPlanCopy = rightPlan->shallowCopy(); - appendCrossProduct(AccumulateType::REGULAR, *leftPlanCopy, *rightPlanCopy); + appendCrossProduct(AccumulateType::REGULAR, *leftPlanCopy, *rightPlanCopy, + *leftPlanCopy); result.push_back(std::move(leftPlanCopy)); } } diff --git a/src/planner/plan/plan_port_db.cpp b/src/planner/plan/plan_port_db.cpp index b9c91e0f601..1ab223fb39e 100644 --- a/src/planner/plan/plan_port_db.cpp +++ b/src/planner/plan/plan_port_db.cpp @@ -29,9 +29,9 @@ std::unique_ptr Planner::planExportDatabase(const BoundStatement& s auto regularQuery = exportTableData.getRegularQuery(); KU_ASSERT(regularQuery->getStatementType() == StatementType::QUERY); auto tablePlan = getBestPlan(*regularQuery); - auto copyTo = std::make_shared( - filePath + "/" + exportTableData.tableName + copyToSuffix, fileType, - exportTableData.columnNames, exportTableData.getColumnTypesRef(), + auto copyTo = std::make_shared(filePath + "/" + exportTableData.tableName + + copyToSuffix, + fileType, exportTableData.columnNames, exportTableData.getColumnTypesRef(), boundExportDatabase.getCopyOption(), tablePlan->getLastOperator()); logicalOperators.push_back(std::move(copyTo)); } diff --git a/src/planner/plan/plan_read.cpp b/src/planner/plan/plan_read.cpp index 01e106e7e07..a22dfe453cd 100644 --- a/src/planner/plan/plan_read.cpp +++ b/src/planner/plan/plan_read.cpp @@ -11,8 +11,8 @@ using namespace kuzu::common; namespace kuzu { namespace planner { -void Planner::planReadingClause( - const BoundReadingClause* readingClause, std::vector>& prevPlans) { +void Planner::planReadingClause(const BoundReadingClause* readingClause, + std::vector>& prevPlans) { auto readingClauseType = readingClause->getClauseType(); switch (readingClauseType) { case ClauseType::MATCH: { @@ -50,7 +50,12 @@ void Planner::planMatchClause(const BoundReadingClause* boundReadingClause, } break; case MatchClauseType::OPTIONAL_MATCH: { for (auto& plan : plans) { - planOptionalMatch(*queryGraphCollection, predicates, *plan); + expression_vector corrExprs; + if (!plan->isEmpty()) { + corrExprs = + getCorrelatedExprs(*queryGraphCollection, predicates, plan->getSchema()); + } + planOptionalMatch(*queryGraphCollection, predicates, corrExprs, *plan); } } break; default: @@ -79,8 +84,8 @@ static bool hasExternalDependency(const std::shared_ptr& expression, return false; } -void Planner::planInQueryCall( - const BoundReadingClause* readingClause, std::vector>& plans) { +void Planner::planInQueryCall(const BoundReadingClause* readingClause, + std::vector>& plans) { auto inQueryCall = ku_dynamic_cast(readingClause); std::unordered_set columnNameSet; @@ -103,7 +108,7 @@ void Planner::planInQueryCall( if (!predicatesToPushDown.empty()) { appendFilters(predicatesToPushDown, *tmpPlan); } - appendCrossProduct(AccumulateType::REGULAR, *plan, *tmpPlan); + appendCrossProduct(AccumulateType::REGULAR, *plan, *tmpPlan, *plan); } else { appendInQueryCall(*readingClause, *plan); if (!predicatesToPushDown.empty()) { @@ -116,8 +121,8 @@ void Planner::planInQueryCall( } } -void Planner::planLoadFrom( - const BoundReadingClause* readingClause, std::vector>& plans) { +void Planner::planLoadFrom(const BoundReadingClause* readingClause, + std::vector>& plans) { auto loadFrom = ku_dynamic_cast(readingClause); std::unordered_set columnNameSet; for (auto& column : loadFrom->getInfo()->columns) { @@ -139,7 +144,7 @@ void Planner::planLoadFrom( if (!predicatesToPushDown.empty()) { appendFilters(predicatesToPushDown, *tmpPlan); } - appendCrossProduct(AccumulateType::REGULAR, *plan, *tmpPlan); + appendCrossProduct(AccumulateType::REGULAR, *plan, *tmpPlan, *plan); } else { appendScanFile(loadFrom->getInfo(), *plan); if (!predicatesToPushDown.empty()) { diff --git a/src/planner/plan/plan_subquery.cpp b/src/planner/plan/plan_subquery.cpp index 90c28fdaa62..6f90d93c1e3 100644 --- a/src/planner/plan/plan_subquery.cpp +++ b/src/planner/plan/plan_subquery.cpp @@ -9,7 +9,7 @@ using namespace kuzu::common; namespace kuzu { namespace planner { -static expression_vector getCorrelatedExpressions(const QueryGraphCollection& collection, +binder::expression_vector Planner::getCorrelatedExprs(const QueryGraphCollection& collection, const expression_vector& predicates, Schema* outerSchema) { expression_vector result; for (auto& predicate : predicates) { @@ -22,11 +22,12 @@ static expression_vector getCorrelatedExpressions(const QueryGraphCollection& co result.push_back(node->getInternalID()); } } - return result; + return ExpressionUtil::removeDuplication(result); } void Planner::planOptionalMatch(const QueryGraphCollection& queryGraphCollection, - const expression_vector& predicates, LogicalPlan& leftPlan) { + const expression_vector& predicates, const binder::expression_vector& corrExprs, + LogicalPlan& leftPlan) { if (leftPlan.isEmpty()) { // Optional match is the first clause. No left plan to join. auto plan = planQueryGraphCollection(queryGraphCollection, predicates); @@ -34,36 +35,42 @@ void Planner::planOptionalMatch(const QueryGraphCollection& queryGraphCollection appendAccumulate(AccumulateType::OPTIONAL_, leftPlan); return; } - auto correlatedExpressions = - getCorrelatedExpressions(queryGraphCollection, predicates, leftPlan.getSchema()); - if (correlatedExpressions.empty()) { + if (corrExprs.empty()) { // No join condition, apply cross product. auto rightPlan = planQueryGraphCollection(queryGraphCollection, predicates); - appendCrossProduct(AccumulateType::OPTIONAL_, leftPlan, *rightPlan); + if (leftPlan.hasUpdate()) { + appendCrossProduct(AccumulateType::OPTIONAL_, *rightPlan, leftPlan, leftPlan); + } else { + appendCrossProduct(AccumulateType::OPTIONAL_, leftPlan, *rightPlan, leftPlan); + } return; } - bool isInternalIDCorrelated = ExpressionUtil::isExpressionsWithDataType( - correlatedExpressions, LogicalTypeID::INTERNAL_ID); + bool isInternalIDCorrelated = + ExpressionUtil::isExpressionsWithDataType(corrExprs, LogicalTypeID::INTERNAL_ID); std::unique_ptr rightPlan; if (isInternalIDCorrelated) { // If all correlated expressions are node IDs. We can trivially unnest by scanning internal // ID in both outer and inner plan as these are fast in-memory operations. For node // properties, we only scan in the outer query. rightPlan = planQueryGraphCollectionInNewContext(SubqueryType::INTERNAL_ID_CORRELATED, - correlatedExpressions, leftPlan.getCardinality(), queryGraphCollection, predicates); + corrExprs, leftPlan.getCardinality(), queryGraphCollection, predicates); } else { // Unnest using ExpressionsScan which scans the accumulated table on probe side. - rightPlan = planQueryGraphCollectionInNewContext(SubqueryType::CORRELATED, - correlatedExpressions, leftPlan.getCardinality(), queryGraphCollection, predicates); - appendAccumulate(AccumulateType::REGULAR, correlatedExpressions, leftPlan); + rightPlan = planQueryGraphCollectionInNewContext(SubqueryType::CORRELATED, corrExprs, + leftPlan.getCardinality(), queryGraphCollection, predicates); + appendAccumulate(AccumulateType::REGULAR, corrExprs, leftPlan); + } + if (leftPlan.hasUpdate()) { + throw RuntimeException(stringFormat("Optional match after update is not supported. Missing " + "right outer join implementation.")); } - appendHashJoin(correlatedExpressions, JoinType::LEFT, leftPlan, *rightPlan); + appendHashJoin(corrExprs, JoinType::LEFT, leftPlan, *rightPlan, leftPlan); } void Planner::planRegularMatch(const QueryGraphCollection& queryGraphCollection, const expression_vector& predicates, LogicalPlan& leftPlan) { auto correlatedExpressions = - getCorrelatedExpressions(queryGraphCollection, predicates, leftPlan.getSchema()); + getCorrelatedExprs(queryGraphCollection, predicates, leftPlan.getSchema()); expression_vector predicatesToPushDown, predicatesToPullUp; // E.g. MATCH (a) WITH COUNT(*) AS s MATCH (b) WHERE b.age > s // "b.age > s" should be pulled up after both MATCH clauses are joined. @@ -74,20 +81,28 @@ void Planner::planRegularMatch(const QueryGraphCollection& queryGraphCollection, predicatesToPullUp.push_back(predicate); } } - auto joinNodeIDs = ExpressionUtil::getExpressionsWithDataType( - correlatedExpressions, LogicalTypeID::INTERNAL_ID); - std::unique_ptr rightPlan; + auto joinNodeIDs = ExpressionUtil::getExpressionsWithDataType(correlatedExpressions, + LogicalTypeID::INTERNAL_ID); if (joinNodeIDs.empty()) { - rightPlan = planQueryGraphCollectionInNewContext(SubqueryType::NONE, correlatedExpressions, - leftPlan.getCardinality(), queryGraphCollection, predicatesToPushDown); - appendCrossProduct(AccumulateType::REGULAR, leftPlan, *rightPlan); + auto rightPlan = + planQueryGraphCollectionInNewContext(SubqueryType::NONE, correlatedExpressions, + leftPlan.getCardinality(), queryGraphCollection, predicatesToPushDown); + if (leftPlan.hasUpdate()) { + appendCrossProduct(AccumulateType::REGULAR, *rightPlan, leftPlan, leftPlan); + } else { + appendCrossProduct(AccumulateType::REGULAR, leftPlan, *rightPlan, leftPlan); + } } else { // TODO(Xiyang): there is a question regarding if we want to plan as a correlated subquery // Multi-part query is actually CTE and CTE can be considered as a subquery but does not // scan from outer. - rightPlan = planQueryGraphCollectionInNewContext(SubqueryType::INTERNAL_ID_CORRELATED, + auto rightPlan = planQueryGraphCollectionInNewContext(SubqueryType::INTERNAL_ID_CORRELATED, joinNodeIDs, leftPlan.getCardinality(), queryGraphCollection, predicatesToPushDown); - appendHashJoin(joinNodeIDs, JoinType::INNER, leftPlan, *rightPlan); + if (leftPlan.hasUpdate()) { + appendHashJoin(joinNodeIDs, JoinType::INNER, *rightPlan, leftPlan, leftPlan); + } else { + appendHashJoin(joinNodeIDs, JoinType::INNER, leftPlan, *rightPlan, leftPlan); + } } for (auto& predicate : predicatesToPullUp) { appendFilter(predicate, leftPlan); @@ -105,18 +120,18 @@ void Planner::planSubquery(const std::shared_ptr& expression, Logica outerPlan.getCardinality(), *subquery->getQueryGraphCollection(), predicates); switch (subquery->getSubqueryType()) { case common::SubqueryType::EXISTS: { - appendAggregate( - expression_vector{}, expression_vector{subquery->getCountStarExpr()}, *innerPlan); + appendAggregate(expression_vector{}, expression_vector{subquery->getCountStarExpr()}, + *innerPlan); appendProjection(expression_vector{subquery->getProjectionExpr()}, *innerPlan); } break; case common::SubqueryType::COUNT: { - appendAggregate( - expression_vector{}, expression_vector{subquery->getProjectionExpr()}, *innerPlan); + appendAggregate(expression_vector{}, expression_vector{subquery->getProjectionExpr()}, + *innerPlan); } break; default: KU_UNREACHABLE; } - appendCrossProduct(AccumulateType::REGULAR, outerPlan, *innerPlan); + appendCrossProduct(AccumulateType::REGULAR, outerPlan, *innerPlan, outerPlan); } else { auto isInternalIDCorrelated = ExpressionUtil::isExpressionsWithDataType(correlatedExprs, LogicalTypeID::INTERNAL_ID); @@ -135,9 +150,10 @@ void Planner::planSubquery(const std::shared_ptr& expression, Logica appendMarkJoin(correlatedExprs, expression, outerPlan, *innerPlan); } break; case common::SubqueryType::COUNT: { - appendAggregate( - correlatedExprs, expression_vector{subquery->getProjectionExpr()}, *innerPlan); - appendHashJoin(correlatedExprs, common::JoinType::COUNT, outerPlan, *innerPlan); + appendAggregate(correlatedExprs, expression_vector{subquery->getProjectionExpr()}, + *innerPlan); + appendHashJoin(correlatedExprs, common::JoinType::COUNT, outerPlan, *innerPlan, + outerPlan); } break; default: KU_UNREACHABLE; @@ -145,8 +161,8 @@ void Planner::planSubquery(const std::shared_ptr& expression, Logica } } -void Planner::planSubqueryIfNecessary( - const std::shared_ptr& expression, LogicalPlan& plan) { +void Planner::planSubqueryIfNecessary(const std::shared_ptr& expression, + LogicalPlan& plan) { if (ExpressionVisitor::hasSubquery(*expression)) { auto expressionCollector = std::make_unique(); for (auto& expr : expressionCollector->collectTopLevelSubqueryExpressions(expression)) { diff --git a/src/planner/plan/plan_update.cpp b/src/planner/plan/plan_update.cpp index be64ccf2195..f544979f909 100644 --- a/src/planner/plan/plan_update.cpp +++ b/src/planner/plan/plan_update.cpp @@ -12,8 +12,8 @@ using namespace kuzu::binder; namespace kuzu { namespace planner { -void Planner::planUpdatingClause( - const BoundUpdatingClause* updatingClause, std::vector>& plans) { +void Planner::planUpdatingClause(const BoundUpdatingClause* updatingClause, + std::vector>& plans) { for (auto& plan : plans) { planUpdatingClause(updatingClause, *plan); } @@ -65,23 +65,18 @@ void Planner::planMergeClause(const BoundUpdatingClause* updatingClause, Logical if (mergeClause->hasPredicate()) { predicates = mergeClause->getPredicate()->splitOnAND(); } - planOptionalMatch(*mergeClause->getQueryGraphCollection(), predicates, plan); - std::shared_ptr mark; - auto& createInfos = mergeClause->getInsertInfosRef(); - KU_ASSERT(!createInfos.empty()); - auto& createInfo = createInfos[0]; - switch (createInfo.tableType) { - case TableType::NODE: { - auto node = (NodeExpression*)createInfo.pattern.get(); - mark = node->getInternalID(); - } break; - case TableType::REL: { - auto rel = (RelExpression*)createInfo.pattern.get(); - mark = rel->getInternalIDProperty(); - } break; - default: - KU_UNREACHABLE; + std::shared_ptr distinctMark = nullptr; + expression_vector corrExprs; + if (!plan.isEmpty()) { + distinctMark = mergeClause->getDistinctMark(); + corrExprs = getCorrelatedExprs(*mergeClause->getQueryGraphCollection(), predicates, + plan.getSchema()); + if (corrExprs.size() == 0) { + throw RuntimeException{"Constant key in merge clause is not supported yet."}; + } + appendMarkAccumulate(corrExprs, distinctMark, plan); } + planOptionalMatch(*mergeClause->getQueryGraphCollection(), predicates, corrExprs, plan); std::vector logicalInsertNodeInfos; if (mergeClause->hasInsertNodeInfo()) { auto boundInsertNodeInfos = mergeClause->getInsertNodeInfos(); @@ -119,10 +114,27 @@ void Planner::planMergeClause(const BoundUpdatingClause* updatingClause, Logical logicalOnMatchSetRelInfos.push_back(createLogicalSetPropertyInfo(info)); } } - auto merge = std::make_shared(mark, std::move(logicalInsertNodeInfos), - std::move(logicalInsertRelInfos), std::move(logicalOnCreateSetNodeInfos), - std::move(logicalOnCreateSetRelInfos), std::move(logicalOnMatchSetNodeInfos), - std::move(logicalOnMatchSetRelInfos), plan.getLastOperator()); + std::shared_ptr existenceMark; + auto& createInfos = mergeClause->getInsertInfosRef(); + KU_ASSERT(!createInfos.empty()); + auto& createInfo = createInfos[0]; + switch (createInfo.tableType) { + case TableType::NODE: { + auto node = (NodeExpression*)createInfo.pattern.get(); + existenceMark = node->getInternalID(); + } break; + case TableType::REL: { + auto rel = (RelExpression*)createInfo.pattern.get(); + existenceMark = rel->getInternalIDProperty(); + } break; + default: + KU_UNREACHABLE; + } + auto merge = std::make_shared(existenceMark, distinctMark, + std::move(logicalInsertNodeInfos), std::move(logicalInsertRelInfos), + std::move(logicalOnCreateSetNodeInfos), std::move(logicalOnCreateSetRelInfos), + std::move(logicalOnMatchSetNodeInfos), std::move(logicalOnMatchSetRelInfos), + plan.getLastOperator()); appendFlattens(merge->getGroupsPosToFlatten(), plan); merge->setChild(0, plan.getLastOperator()); merge->computeFactorizedSchema(); diff --git a/src/planner/planner.cpp b/src/planner/planner.cpp index 087bd331d8b..40ad354ff8f 100644 --- a/src/planner/planner.cpp +++ b/src/planner/planner.cpp @@ -11,9 +11,9 @@ using namespace kuzu::storage; namespace kuzu { namespace planner { -Planner::Planner(Catalog* catalog, StorageManager* storageManager) : catalog{catalog} { - auto nStats = storageManager->getNodesStatisticsAndDeletedIDs(); - auto rStats = storageManager->getRelsStatistics(); +Planner::Planner(main::ClientContext* clientContext) : clientContext{clientContext} { + auto nStats = clientContext->getStorageManager()->getNodesStatisticsAndDeletedIDs(); + auto rStats = clientContext->getStorageManager()->getRelsStatistics(); cardinalityEstimator = CardinalityEstimator(nStats, rStats); context = JoinOrderEnumeratorContext(); } @@ -63,6 +63,12 @@ std::unique_ptr Planner::getBestPlan(const BoundStatement& statemen case StatementType::IMPORT_DATABASE: { plan = planImportDatabase(statement); } break; + case StatementType::ATTACH_DATABASE: { + appendAttachDatabase(statement, *plan); + } break; + case StatementType::DETACH_DATABASE: { + appendDetachDatabase(statement, *plan); + } break; default: KU_UNREACHABLE; } diff --git a/src/planner/query_planner.cpp b/src/planner/query_planner.cpp index 78b7b07d473..60b1af94ea5 100644 --- a/src/planner/query_planner.cpp +++ b/src/planner/query_planner.cpp @@ -76,8 +76,8 @@ std::unique_ptr Planner::createUnionPlan( children.push_back(childPlan->getLastOperator()); } // we compute the schema based on first child - auto union_ = make_shared( - childrenPlans[0]->getSchema()->getExpressionsInScope(), std::move(children)); + auto union_ = make_shared(childrenPlans[0]->getSchema()->getExpressionsInScope(), + std::move(children)); for (auto i = 0u; i < childrenPlans.size(); ++i) { appendFlattens(union_->getGroupsPosToFlatten(i), *childrenPlans[i]); union_->setChild(i, childrenPlans[i]->getLastOperator()); diff --git a/src/planner/subplans_table.cpp b/src/planner/subplans_table.cpp index 130e7466890..d51cf8a0fe5 100644 --- a/src/planner/subplans_table.cpp +++ b/src/planner/subplans_table.cpp @@ -59,8 +59,8 @@ std::vector DPLevel::getSubqueryGraphs() { return result; } -void DPLevel::addPlan( - const kuzu::binder::SubqueryGraph& subqueryGraph, std::unique_ptr plan) { +void DPLevel::addPlan(const kuzu::binder::SubqueryGraph& subqueryGraph, + std::unique_ptr plan) { if (subgraph2Plans.size() > MAX_NUM_SUBGRAPH) { return; } diff --git a/src/processor/map/CMakeLists.txt b/src/processor/map/CMakeLists.txt index 29cfa681293..c7aa880fcdc 100644 --- a/src/processor/map/CMakeLists.txt +++ b/src/processor/map/CMakeLists.txt @@ -7,6 +7,8 @@ add_library(kuzu_processor_mapper map_accumulate.cpp map_aggregate.cpp map_acc_hash_join.cpp + map_attach_database.cpp + map_detach_database.cpp map_standalone_call.cpp map_in_query_call.cpp map_comment_on.cpp @@ -31,6 +33,7 @@ add_library(kuzu_processor_mapper map_intersect.cpp map_label_filter.cpp map_limit.cpp + map_mark_accumulate.cpp map_merge.cpp map_multiplicity_reducer.cpp map_order_by.cpp diff --git a/src/processor/map/create_factorized_table_scan.cpp b/src/processor/map/create_factorized_table_scan.cpp index 7be22f159b4..2c839ebded3 100644 --- a/src/processor/map/create_factorized_table_scan.cpp +++ b/src/processor/map/create_factorized_table_scan.cpp @@ -1,6 +1,8 @@ #include #include "binder/expression/expression_util.h" +#include "catalog/catalog.h" +#include "function/built_in_function_utils.h" #include "processor/operator/call/in_query_call.h" #include "processor/operator/table_scan/ftable_scan_function.h" #include "processor/plan_mapper.h" @@ -13,45 +15,90 @@ using namespace kuzu::function; namespace kuzu { namespace processor { -std::unique_ptr PlanMapper::createFactorizedTableScan( - const expression_vector& expressions, std::vector colIndices, Schema* schema, - const std::shared_ptr& table, uint64_t maxMorselSize, - std::unique_ptr prevOperator) { +std::unique_ptr PlanMapper::createFTableScan(const expression_vector& exprs, + std::vector colIndices, std::shared_ptr offset, Schema* schema, + std::shared_ptr table, uint64_t maxMorselSize, + std::unique_ptr child) { std::vector outPosV; - outPosV.reserve(expressions.size()); - for (auto i = 0u; i < expressions.size(); ++i) { - outPosV.emplace_back(schema->getExpressionPos(*expressions[i])); + outPosV.reserve(exprs.size()); + for (auto i = 0u; i < exprs.size(); ++i) { + outPosV.emplace_back(schema->getExpressionPos(*exprs[i])); } auto bindData = std::make_unique(table, std::move(colIndices), maxMorselSize); - auto function = function::BuiltInFunctionsUtils::matchFunction( - READ_FTABLE_FUNC_NAME, catalog->getFunctions(clientContext->getTx())); + auto function = function::BuiltInFunctionsUtils::matchFunction(FTableScan::name, + clientContext->getCatalog()->getFunctions(clientContext->getTx())); auto info = InQueryCallInfo(); - info.function = ku_dynamic_cast(function); + info.function = *ku_dynamic_cast(function); info.bindData = std::move(bindData); info.outPosV = std::move(outPosV); - info.rowOffsetPos = DataPos(); // Invalid data pos. + if (offset != nullptr) { + info.rowOffsetPos = getDataPos(*offset, *schema); + } else { + info.rowOffsetPos = DataPos::getInvalidPos(); // Invalid data pos. + } info.outputType = TableScanOutputType::MULTI_DATA_CHUNK; auto sharedState = std::make_shared(); - if (prevOperator == nullptr) { - return std::make_unique( - std::move(info), sharedState, getOperatorID(), ExpressionUtil::toString(expressions)); + if (child == nullptr) { + return std::make_unique(std::move(info), sharedState, getOperatorID(), + ExpressionUtil::toString(exprs)); } - return std::make_unique(std::move(info), sharedState, std::move(prevOperator), - getOperatorID(), ExpressionUtil::toString(expressions)); -} - -std::unique_ptr PlanMapper::createFactorizedTableScanAligned( - const expression_vector& expressions, Schema* schema, - const std::shared_ptr& table, uint64_t maxMorselSize, - std::unique_ptr prevOperator) { - std::vector columnIndices; - columnIndices.reserve(expressions.size()); - for (auto i = 0u; i < expressions.size(); ++i) { - columnIndices.push_back(i); + return std::make_unique(std::move(info), sharedState, std::move(child), + getOperatorID(), ExpressionUtil::toString(exprs)); +} + +std::unique_ptr PlanMapper::createFTableScan(const expression_vector& exprs, + std::vector colIndices, Schema* schema, std::shared_ptr table, + uint64_t maxMorselSize, std::unique_ptr child) { + return createFTableScan(exprs, colIndices, nullptr /* offset */, schema, std::move(table), + maxMorselSize, std::move(child)); +} + +std::unique_ptr PlanMapper::createFTableScan(const expression_vector& exprs, + std::vector colIndices, Schema* schema, std::shared_ptr table, + uint64_t maxMorselSize) { + return createFTableScan(exprs, colIndices, nullptr /* offset */, schema, std::move(table), + maxMorselSize, nullptr /* child */); +} + +std::unique_ptr PlanMapper::createEmptyFTableScan( + std::shared_ptr table, uint64_t maxMorselSize, + std::unique_ptr child) { + return createFTableScan(expression_vector{}, std::vector{}, nullptr /* offset */, + std::move(table), maxMorselSize, std::move(child)); +} + +std::unique_ptr PlanMapper::createEmptyFTableScan( + std::shared_ptr table, uint64_t maxMorselSize) { + return createFTableScan(expression_vector{}, std::vector{}, nullptr /* offset */, + std::move(table), maxMorselSize, nullptr /* child */); +} + +std::unique_ptr PlanMapper::createFTableScanAligned( + const expression_vector& exprs, Schema* schema, std::shared_ptr offset, + std::shared_ptr table, uint64_t maxMorselSize, + std::unique_ptr child) { + std::vector colIndices; + colIndices.reserve(exprs.size()); + for (auto i = 0u; i < exprs.size(); ++i) { + colIndices.push_back(i); } - return createFactorizedTableScan(expressions, std::move(columnIndices), schema, table, - maxMorselSize, std::move(prevOperator)); + return createFTableScan(exprs, std::move(colIndices), std::move(offset), schema, table, + maxMorselSize, std::move(child)); +} + +std::unique_ptr PlanMapper::createFTableScanAligned( + const expression_vector& exprs, Schema* schema, std::shared_ptr table, + uint64_t maxMorselSize, std::unique_ptr child) { + return createFTableScanAligned(exprs, schema, nullptr /* offset*/, std::move(table), + maxMorselSize, std::move(child)); +} + +std::unique_ptr PlanMapper::createFTableScanAligned( + const expression_vector& exprs, planner::Schema* schema, std::shared_ptr table, + uint64_t maxMorselSize) { + return createFTableScanAligned(exprs, schema, std::move(table), maxMorselSize, + nullptr /* child */); } } // namespace processor diff --git a/src/processor/map/create_result_collector.cpp b/src/processor/map/create_result_collector.cpp index 8dd58eb0f9d..029db31faa0 100644 --- a/src/processor/map/create_result_collector.cpp +++ b/src/processor/map/create_result_collector.cpp @@ -20,13 +20,14 @@ std::unique_ptr PlanMapper::createResultCollector(AccumulateTyp columnSchema = std::make_unique(false /* isUnFlat */, dataPos.dataChunkPos, LogicalTypeUtils::getRowLayoutSize(expression->dataType)); } else { - columnSchema = std::make_unique( - true /* isUnFlat */, dataPos.dataChunkPos, (uint32_t)sizeof(overflow_value_t)); + columnSchema = std::make_unique(true /* isUnFlat */, dataPos.dataChunkPos, + (uint32_t)sizeof(overflow_value_t)); } tableSchema->appendColumn(std::move(columnSchema)); payloadsPos.push_back(dataPos); } - auto table = std::make_shared(memoryManager, tableSchema->copy()); + auto table = + std::make_shared(clientContext->getMemoryManager(), tableSchema->copy()); auto sharedState = std::make_shared(std::move(table)); auto info = std::make_unique(accumulateType, std::move(tableSchema), payloadsPos); diff --git a/src/processor/map/expression_mapper.cpp b/src/processor/map/expression_mapper.cpp index 3b8c637f8a1..fda446c9d4d 100644 --- a/src/processor/map/expression_mapper.cpp +++ b/src/processor/map/expression_mapper.cpp @@ -70,8 +70,8 @@ std::unique_ptr ExpressionMapper::getEvaluator( return getFunctionEvaluator(expression, schema); } else { // LCOV_EXCL_START - throw NotImplementedException(stringFormat( - "Cannot evaluate expression with type {}.", expressionTypeToString(expressionType))); + throw NotImplementedException(stringFormat("Cannot evaluate expression with type {}.", + expressionTypeToString(expressionType))); // LCOV_EXCL_STOP } } @@ -88,8 +88,8 @@ std::unique_ptr ExpressionMapper::getConstantEvaluator( return getFunctionEvaluator(expression, nullptr); } else { // LCOV_EXCL_START - throw NotImplementedException(stringFormat( - "Cannot evaluate expression with type {}.", expressionTypeToString(expressionType))); + throw NotImplementedException(stringFormat("Cannot evaluate expression with type {}.", + expressionTypeToString(expressionType))); // LCOV_EXCL_STOP } } @@ -128,15 +128,15 @@ std::unique_ptr ExpressionMapper::getCaseEvaluator( std::move(whenEvaluator), std::move(thenEvaluator))); } auto elseEvaluator = getEvaluator(caseExpression->getElseExpression(), schema); - return std::make_unique( - std::move(expression), std::move(alternativeEvaluators), std::move(elseEvaluator)); + return std::make_unique(std::move(expression), + std::move(alternativeEvaluators), std::move(elseEvaluator)); } std::unique_ptr ExpressionMapper::getFunctionEvaluator( std::shared_ptr expression, const Schema* schema) { auto childrenEvaluators = getEvaluators(expression->getChildren(), schema); - return std::make_unique( - std::move(expression), std::move(childrenEvaluators)); + return std::make_unique(std::move(expression), + std::move(childrenEvaluators)); } std::unique_ptr ExpressionMapper::getNodeEvaluator( @@ -149,8 +149,8 @@ std::unique_ptr ExpressionMapper::getNodeEvaluator( children.push_back(property); } auto childrenEvaluators = getEvaluators(children, schema); - return std::make_unique( - std::move(expression), std::move(childrenEvaluators)); + return std::make_unique(std::move(expression), + std::move(childrenEvaluators)); } std::unique_ptr ExpressionMapper::getRelEvaluator( @@ -164,15 +164,15 @@ std::unique_ptr ExpressionMapper::getRelEvaluator( children.push_back(property); } auto childrenEvaluators = getEvaluators(children, schema); - return std::make_unique( - std::move(expression), std::move(childrenEvaluators)); + return std::make_unique(std::move(expression), + std::move(childrenEvaluators)); } std::unique_ptr ExpressionMapper::getPathEvaluator( std::shared_ptr expression, const Schema* schema) { auto childrenEvaluators = getEvaluators(expression->getChildren(), schema); - return std::make_unique( - std::move(expression), std::move(childrenEvaluators)); + return std::make_unique(std::move(expression), + std::move(childrenEvaluators)); } std::vector> ExpressionMapper::getEvaluators( diff --git a/src/processor/map/map_accumulate.cpp b/src/processor/map/map_accumulate.cpp index 9785f8fc6d4..3870e8bee19 100644 --- a/src/processor/map/map_accumulate.cpp +++ b/src/processor/map/map_accumulate.cpp @@ -9,17 +9,17 @@ namespace kuzu { namespace processor { std::unique_ptr PlanMapper::mapAccumulate(LogicalOperator* logicalOperator) { - auto logicalAccumulate = (LogicalAccumulate*)logicalOperator; - auto outSchema = logicalAccumulate->getSchema(); - auto inSchema = logicalAccumulate->getChild(0)->getSchema(); - auto prevOperator = mapOperator(logicalAccumulate->getChild(0).get()); - auto expressions = logicalAccumulate->getExpressionsToAccumulate(); - auto resultCollector = createResultCollector( - logicalAccumulate->getAccumulateType(), expressions, inSchema, std::move(prevOperator)); + auto acc = (LogicalAccumulate*)logicalOperator; + auto outSchema = acc->getSchema(); + auto inSchema = acc->getChild(0)->getSchema(); + auto prevOperator = mapOperator(acc->getChild(0).get()); + auto expressions = acc->getPayloads(); + auto resultCollector = createResultCollector(acc->getAccumulateType(), expressions, inSchema, + std::move(prevOperator)); auto table = resultCollector->getResultFactorizedTable(); auto maxMorselSize = table->hasUnflatCol() ? 1 : DEFAULT_VECTOR_CAPACITY; - return createFactorizedTableScanAligned( - expressions, outSchema, table, maxMorselSize, std::move(resultCollector)); + return createFTableScanAligned(expressions, outSchema, acc->getOffset(), table, maxMorselSize, + std::move(resultCollector)); } } // namespace processor diff --git a/src/processor/map/map_aggregate.cpp b/src/processor/map/map_aggregate.cpp index 9b5ffc39f6c..fc811f3809d 100644 --- a/src/processor/map/map_aggregate.cpp +++ b/src/processor/map/map_aggregate.cpp @@ -45,14 +45,14 @@ static std::vector> getAggregateInputInfos( multiplicityChunksPos.push_back(groupPos); } } - result.emplace_back(std::make_unique( - aggregateVectorPos, std::move(multiplicityChunksPos))); + result.emplace_back(std::make_unique(aggregateVectorPos, + std::move(multiplicityChunksPos))); } return result; } -static binder::expression_vector getKeyExpressions( - const binder::expression_vector& expressions, const Schema& schema, bool isFlat) { +static binder::expression_vector getKeyExpressions(const binder::expression_vector& expressions, + const Schema& schema, bool isFlat) { binder::expression_vector result; for (auto& expression : expressions) { if (schema.getGroup(schema.getGroupPos(*expression))->isFlat() == isFlat) { @@ -81,40 +81,78 @@ std::unique_ptr PlanMapper::mapAggregate(LogicalOperator* logi return createHashAggregate(logicalAggregate.getKeyExpressions(), logicalAggregate.getDependentKeyExpressions(), std::move(aggregateFunctions), std::move(aggregateInputInfos), std::move(aggregatesOutputPos), inSchema, outSchema, - std::move(prevOperator), paramsString); + std::move(prevOperator), paramsString, nullptr); } else { auto sharedState = make_shared(aggregateFunctions); auto aggregate = make_unique(std::make_unique(inSchema), sharedState, std::move(aggregateFunctions), std::move(aggregateInputInfos), std::move(prevOperator), getOperatorID(), paramsString); - return make_unique( - sharedState, aggregatesOutputPos, std::move(aggregate), getOperatorID(), paramsString); + return make_unique(sharedState, aggregatesOutputPos, + std::move(aggregate), getOperatorID(), paramsString); } } +static std::unique_ptr getFactorizedTableSchema( + const binder::expression_vector& flatKeys, const binder::expression_vector& unflatKeys, + const binder::expression_vector& payloads, + std::vector>& aggregateFunctions, + std::shared_ptr markExpression) { + auto isUnflat = false; + auto dataChunkPos = 0u; + std::unique_ptr tableSchema = std::make_unique(); + for (auto& flatKey : flatKeys) { + auto size = LogicalTypeUtils::getRowLayoutSize(flatKey->dataType); + tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, size)); + } + for (auto& unflatKey : unflatKeys) { + auto size = LogicalTypeUtils::getRowLayoutSize(unflatKey->dataType); + tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, size)); + } + for (auto& payload : payloads) { + auto size = LogicalTypeUtils::getRowLayoutSize(payload->dataType); + tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, size)); + } + for (auto& aggregateFunc : aggregateFunctions) { + tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, + aggregateFunc->getAggregateStateSize())); + } + if (markExpression != nullptr) { + tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, + LogicalTypeUtils::getRowLayoutSize(markExpression->dataType))); + } + tableSchema->appendColumn( + std::make_unique(isUnflat, dataChunkPos, sizeof(hash_t))); + return tableSchema; +} + std::unique_ptr PlanMapper::createHashAggregate( - const binder::expression_vector& keyExpressions, - const binder::expression_vector& dependentKeyExpressions, + const binder::expression_vector& keys, const binder::expression_vector& payloads, std::vector> aggregateFunctions, std::vector> aggregateInputInfos, std::vector aggregatesOutputPos, planner::Schema* inSchema, planner::Schema* outSchema, - std::unique_ptr prevOperator, const std::string& paramsString) { + std::unique_ptr prevOperator, const std::string& paramsString, + std::shared_ptr markExpression) { auto sharedState = make_shared(aggregateFunctions); - auto flatKeyExpressions = getKeyExpressions(keyExpressions, *inSchema, true /* isFlat */); - auto unFlatKeyExpressions = getKeyExpressions(keyExpressions, *inSchema, false /* isFlat */); + auto flatKeys = getKeyExpressions(keys, *inSchema, true /* isFlat */); + auto unFlatKeys = getKeyExpressions(keys, *inSchema, false /* isFlat */); + auto tableSchema = getFactorizedTableSchema(flatKeys, unFlatKeys, payloads, aggregateFunctions, + markExpression); + HashAggregateInfo aggregateInfo{getExpressionsDataPos(flatKeys, *inSchema), + getExpressionsDataPos(unFlatKeys, *inSchema), getExpressionsDataPos(payloads, *inSchema), + std::move(tableSchema), + markExpression == nullptr ? HashTableType::AGGREGATE_HASH_TABLE : + HashTableType::MARK_HASH_TABLE}; auto aggregate = make_unique(std::make_unique(inSchema), - sharedState, getExpressionsDataPos(flatKeyExpressions, *inSchema), - getExpressionsDataPos(unFlatKeyExpressions, *inSchema), - getExpressionsDataPos(dependentKeyExpressions, *inSchema), std::move(aggregateFunctions), + sharedState, std::move(aggregateInfo), std::move(aggregateFunctions), std::move(aggregateInputInfos), std::move(prevOperator), getOperatorID(), paramsString); binder::expression_vector outputExpressions; - outputExpressions.insert( - outputExpressions.end(), flatKeyExpressions.begin(), flatKeyExpressions.end()); - outputExpressions.insert( - outputExpressions.end(), unFlatKeyExpressions.begin(), unFlatKeyExpressions.end()); - outputExpressions.insert( - outputExpressions.end(), dependentKeyExpressions.begin(), dependentKeyExpressions.end()); + outputExpressions.insert(outputExpressions.end(), flatKeys.begin(), flatKeys.end()); + outputExpressions.insert(outputExpressions.end(), unFlatKeys.begin(), unFlatKeys.end()); + outputExpressions.insert(outputExpressions.end(), payloads.begin(), payloads.end()); + if (markExpression != nullptr) { + outputExpressions.emplace_back(markExpression); + } return std::make_unique(sharedState, getExpressionsDataPos(outputExpressions, *outSchema), std::move(aggregatesOutputPos), std::move(aggregate), getOperatorID(), paramsString); diff --git a/src/processor/map/map_attach_database.cpp b/src/processor/map/map_attach_database.cpp new file mode 100644 index 00000000000..c8dbd5d1c16 --- /dev/null +++ b/src/processor/map/map_attach_database.cpp @@ -0,0 +1,19 @@ +#include "planner/operator/logical_attach_database.h" +#include "processor/operator/attach_database.h" +#include "processor/plan_mapper.h" + +namespace kuzu { +namespace processor { + +using namespace kuzu::planner; + +std::unique_ptr PlanMapper::mapAttachDatabase( + planner::LogicalOperator* logicalOperator) { + auto attachDatabase = + common::ku_dynamic_cast(logicalOperator); + return std::make_unique(attachDatabase->getAttachInfo(), getOperatorID(), + attachDatabase->getExpressionsForPrinting()); +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/map/map_comment_on.cpp b/src/processor/map/map_comment_on.cpp index 57fa65e372f..a84b41ecb6b 100644 --- a/src/processor/map/map_comment_on.cpp +++ b/src/processor/map/map_comment_on.cpp @@ -16,9 +16,10 @@ std::unique_ptr PlanMapper::mapCommentOn( auto outputExpression = logicalCommentOn->getOutputExpression(); auto outputPos = DataPos(outSchema->getExpressionPos(*outputExpression)); auto commentOnInfo = std::make_unique(logicalCommentOn->getTableID(), - logicalCommentOn->getTableName(), logicalCommentOn->getComment(), outputPos, catalog); - return std::make_unique( - std::move(commentOnInfo), getOperatorID(), logicalCommentOn->getExpressionsForPrinting()); + logicalCommentOn->getTableName(), logicalCommentOn->getComment(), outputPos, + clientContext->getCatalog()); + return std::make_unique(std::move(commentOnInfo), getOperatorID(), + logicalCommentOn->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/map_copy_from.cpp b/src/processor/map/map_copy_from.cpp index 11af63835af..e5a053563b2 100644 --- a/src/processor/map/map_copy_from.cpp +++ b/src/processor/map/map_copy_from.cpp @@ -1,4 +1,3 @@ -#include "binder/expression/variable_expression.h" #include "catalog/catalog_entry/table_catalog_entry.h" #include "planner/operator/logical_partitioner.h" #include "planner/operator/persistent/logical_copy_from.h" @@ -10,6 +9,7 @@ #include "processor/operator/persistent/node_batch_insert.h" #include "processor/operator/persistent/rel_batch_insert.h" #include "processor/plan_mapper.h" +#include "storage/storage_manager.h" using namespace kuzu::binder; using namespace kuzu::catalog; @@ -27,15 +27,15 @@ std::unique_ptr PlanMapper::mapCopyFrom(LogicalOperator* logic auto op = mapCopyNodeFrom(logicalOperator); auto copy = ku_dynamic_cast(op.get()); auto table = copy->getSharedState()->fTable; - return createFactorizedTableScanAligned(copyFrom->getOutExprs(), copyFrom->getSchema(), - table, DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, std::move(op)); + return createFTableScanAligned(copyFrom->getOutExprs(), copyFrom->getSchema(), table, + DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, std::move(op)); } case TableType::REL: { auto ops = mapCopyRelFrom(logicalOperator); auto relBatchInsert = ku_dynamic_cast(ops[0].get()); auto fTable = relBatchInsert->getSharedState()->fTable; - auto scan = createFactorizedTableScanAligned(copyFrom->getOutExprs(), copyFrom->getSchema(), - fTable, DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, std::move(ops[0])); + auto scan = createFTableScanAligned(copyFrom->getOutExprs(), copyFrom->getSchema(), fTable, + DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, std::move(ops[0])); for (auto i = 1u; i < ops.size(); ++i) { scan->addChild(std::move(ops[i])); } @@ -49,34 +49,32 @@ std::unique_ptr PlanMapper::mapCopyFrom(LogicalOperator* logic } static void getNodeColumnsInCopyOrder(TableCatalogEntry* tableEntry, - std::vector& columnNames, logical_types_t& columnTypes) { + std::vector& columnNames, std::vector& columnTypes) { for (auto& property : tableEntry->getPropertiesRef()) { columnNames.push_back(property.getName()); - columnTypes.push_back(property.getDataType()->copy()); + columnTypes.push_back(*property.getDataType()->copy()); } } static void getRelColumnNamesInCopyOrder(TableCatalogEntry* tableEntry, - std::vector& columnNames, logical_types_t& columnTypes) { + std::vector& columnNames, std::vector& columnTypes) { columnNames.emplace_back(InternalKeyword::SRC_OFFSET); columnNames.emplace_back(InternalKeyword::DST_OFFSET); columnNames.emplace_back(InternalKeyword::ROW_OFFSET); - columnTypes.emplace_back(std::make_unique(LogicalTypeID::INT64)); - columnTypes.emplace_back(std::make_unique(LogicalTypeID::INT64)); - columnTypes.emplace_back(std::make_unique(LogicalTypeID::INT64)); + columnTypes.emplace_back(LogicalType(LogicalTypeID::INTERNAL_ID)); + columnTypes.emplace_back(LogicalType(LogicalTypeID::INTERNAL_ID)); + columnTypes.emplace_back(LogicalType(LogicalTypeID::INTERNAL_ID)); auto& properties = tableEntry->getPropertiesRef(); for (auto i = 1u; i < properties.size(); ++i) { // skip internal ID columnNames.push_back(properties[i].getName()); - columnTypes.push_back(properties[i].getDataType()->copy()); + columnTypes.push_back(*properties[i].getDataType()->copy()); } } -static std::shared_ptr matchColumnExpression( - const expression_vector& columnExpressions, const std::string& columnName) { +static std::shared_ptr matchColumnExpression(const expression_vector& columnExpressions, + const std::string& columnName) { for (auto& expression : columnExpressions) { - KU_ASSERT(expression->expressionType == ExpressionType::VARIABLE); - auto var = ku_dynamic_cast(expression.get()); - if (columnName == var->getVariableName()) { + if (columnName == expression->toString()) { return expression; } } @@ -98,6 +96,7 @@ static std::vector getColumnDataPositions(const std::vector PlanMapper::mapCopyNodeFrom(LogicalOperator* logicalOperator) { + auto storageManager = clientContext->getStorageManager(); auto copyFrom = ku_dynamic_cast(logicalOperator); auto copyFromInfo = copyFrom->getInfo(); auto outFSchema = copyFrom->getSchema(); @@ -105,9 +104,9 @@ std::unique_ptr PlanMapper::mapCopyNodeFrom(LogicalOperator* l ku_dynamic_cast(copyFromInfo->tableEntry); // Map reader. auto prevOperator = mapOperator(copyFrom->getChild(0).get()); - auto nodeTable = storageManager.getNodeTable(nodeTableEntry->getTableID()); - auto sharedState = std::make_shared( - nodeTable, getSingleStringColumnFTable(), storageManager.getWAL()); + auto nodeTable = storageManager->getTable(nodeTableEntry->getTableID()); + auto sharedState = std::make_shared(nodeTable, + getSingleStringColumnFTable(), storageManager->getWAL()); if (prevOperator->getOperatorType() == PhysicalOperatorType::IN_QUERY_CALL) { auto inQueryCall = ku_dynamic_cast(prevOperator.get()); sharedState->readerSharedState = inQueryCall->getSharedState(); @@ -121,22 +120,23 @@ std::unique_ptr PlanMapper::mapCopyNodeFrom(LogicalOperator* l sharedState->pkColumnIdx = nodeTableEntry->getColumnID(pk->getPropertyID()); sharedState->pkType = *pk->getDataType(); std::vector columnNames; - logical_types_t columnTypes; + std::vector columnTypes; getNodeColumnsInCopyOrder(nodeTableEntry, columnNames, columnTypes); std::vector columnNamesExcludingSerial; for (auto i = 0u; i < columnNames.size(); ++i) { - if (columnTypes[i]->getLogicalTypeID() == common::LogicalTypeID::SERIAL) { + if (columnTypes[i].getLogicalTypeID() == common::LogicalTypeID::SERIAL) { continue; } columnNamesExcludingSerial.push_back(columnNames[i]); } - auto inputColumns = copyFromInfo->fileScanInfo->columns; - inputColumns.push_back(copyFromInfo->fileScanInfo->offset); + auto inputColumns = copyFromInfo->source->getColumns(); + inputColumns.push_back(copyFromInfo->offset); auto columnPositions = getColumnDataPositions(columnNamesExcludingSerial, inputColumns, *outFSchema); + auto containsSerial = nodeTableEntry->containPropertyType(*LogicalType::SERIAL()); auto info = - std::make_unique(nodeTableEntry, storageManager.compressionEnabled(), - std::move(columnPositions), copyFromInfo->containsSerial, std::move(columnTypes)); + std::make_unique(nodeTableEntry, storageManager->compressionEnabled(), + std::move(columnPositions), containsSerial, std::move(columnTypes)); return std::make_unique(std::move(info), sharedState, std::make_unique(copyFrom->getSchema()), std::move(prevOperator), getOperatorID(), copyFrom->getExpressionsForPrinting()); @@ -153,13 +153,17 @@ std::unique_ptr PlanMapper::mapPartitioner(LogicalOperator* lo auto info = logicalPartitioner->getInfo(i); auto keyPos = getDataPos(*info->key, *outFSchema); std::vector columnNames; - logical_types_t columnTypes; + std::vector columnTypes; getRelColumnNamesInCopyOrder(info->tableEntry, columnNames, columnTypes); auto columnPositions = getColumnDataPositions(columnNames, info->payloads, *outFSchema); infos.push_back(std::make_unique(keyPos, columnPositions, std::move(columnTypes), PartitionerFunctions::partitionRelData)); } - auto sharedState = std::make_shared(memoryManager); + std::vector columnTypes; + for (auto& info : infos) { + columnTypes.push_back(info->columnTypes); + } + auto sharedState = std::make_shared(std::move(columnTypes)); return std::make_unique(std::make_unique(outFSchema), std::move(infos), std::move(sharedState), std::move(prevOperator), getOperatorID(), logicalPartitioner->getExpressionsForPrinting()); @@ -168,14 +172,14 @@ std::unique_ptr PlanMapper::mapPartitioner(LogicalOperator* lo std::unique_ptr PlanMapper::createCopyRel( std::shared_ptr partitionerSharedState, std::shared_ptr sharedState, LogicalCopyFrom* copyFrom, - RelDataDirection direction, std::vector> columnTypes) { + RelDataDirection direction, std::vector columnTypes) { auto copyFromInfo = copyFrom->getInfo(); auto outFSchema = copyFrom->getSchema(); auto partitioningIdx = direction == RelDataDirection::FWD ? 0 : 1; auto offsetVectorIdx = direction == RelDataDirection::FWD ? 0 : 1; auto relBatchInsertInfo = std::make_unique(copyFromInfo->tableEntry, - storageManager.compressionEnabled(), direction, partitioningIdx, offsetVectorIdx, - std::move(columnTypes)); + clientContext->getStorageManager()->compressionEnabled(), direction, partitioningIdx, + offsetVectorIdx, std::move(columnTypes)); return std::make_unique(std::move(relBatchInsertInfo), std::move(partitionerSharedState), std::move(sharedState), std::make_unique(outFSchema), getOperatorID(), @@ -187,22 +191,30 @@ physical_op_vector_t PlanMapper::mapCopyRelFrom(LogicalOperator* logicalOperator auto copyFromInfo = copyFrom->getInfo(); auto relTableEntry = ku_dynamic_cast(copyFromInfo->tableEntry); - auto prevOperator = mapOperator(copyFrom->getChild(0).get()); - KU_ASSERT(prevOperator->getOperatorType() == PhysicalOperatorType::PARTITIONER); - auto partitionerSharedState = dynamic_cast(prevOperator.get())->getSharedState(); - partitionerSharedState->srcNodeTable = - storageManager.getNodeTable(relTableEntry->getSrcTableID()); - partitionerSharedState->dstNodeTable = - storageManager.getNodeTable(relTableEntry->getDstTableID()); + auto partitioner = mapOperator(copyFrom->getChild(0).get()); + KU_ASSERT(partitioner->getOperatorType() == PhysicalOperatorType::PARTITIONER); + auto partitionerSharedState = dynamic_cast(partitioner.get())->getSharedState(); + auto storageManager = clientContext->getStorageManager(); + partitionerSharedState->srcNodeTable = ku_dynamic_cast( + storageManager->getTable(relTableEntry->getSrcTableID())); + partitionerSharedState->dstNodeTable = ku_dynamic_cast( + storageManager->getTable(relTableEntry->getDstTableID())); + // TODO(Guodong/Xiyang): This is a temp hack to set rel offset. + KU_ASSERT(partitioner->getChild(0)->getChild(0)->getOperatorType() == + PhysicalOperatorType::IN_QUERY_CALL); + auto scanFile = + ku_dynamic_cast(partitioner->getChild(0)->getChild(0)); + auto relTable = storageManager->getTable(relTableEntry->getTableID()); + scanFile->getSharedState()->nextRowIdx = + relTable->getNumTuples(&transaction::DUMMY_WRITE_TRANSACTION); // TODO(Xiyang): Move binding of column types to binder. - std::vector> columnTypes; - columnTypes.push_back(LogicalType::INTERNAL_ID()); // ADJ COLUMN. + std::vector columnTypes; + columnTypes.push_back(*LogicalType::INTERNAL_ID()); // NBR_ID COLUMN. for (auto& property : relTableEntry->getPropertiesRef()) { - columnTypes.push_back(property.getDataType()->copy()); + columnTypes.push_back(*property.getDataType()->copy()); } - auto batchInsertSharedState = std::make_shared( - storageManager.getRelTable(relTableEntry->getTableID()), getSingleStringColumnFTable(), - storageManager.getWAL()); + auto batchInsertSharedState = std::make_shared(relTable, + getSingleStringColumnFTable(), storageManager->getWAL()); auto copyRelFWD = createCopyRel(partitionerSharedState, batchInsertSharedState, copyFrom, RelDataDirection::FWD, LogicalType::copy(columnTypes)); auto copyRelBWD = createCopyRel(partitionerSharedState, batchInsertSharedState, copyFrom, @@ -210,7 +222,7 @@ physical_op_vector_t PlanMapper::mapCopyRelFrom(LogicalOperator* logicalOperator physical_op_vector_t result; result.push_back(std::move(copyRelBWD)); result.push_back(std::move(copyRelFWD)); - result.push_back(std::move(prevOperator)); + result.push_back(std::move(partitioner)); return result; } @@ -268,7 +280,7 @@ std::unique_ptr PlanMapper::mapCopyRdfFrom(LogicalOperator* lo if (scanChild != nullptr) { copyRdf->addChild(std::move(scanChild)); } - return createFactorizedTableScanAligned(copyFrom->getOutExprs(), copyFrom->getSchema(), fTable, + return createFTableScanAligned(copyFrom->getOutExprs(), copyFrom->getSchema(), fTable, DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, std::move(copyRdf)); } diff --git a/src/processor/map/map_copy_to.cpp b/src/processor/map/map_copy_to.cpp index 9b72adf05f3..044f40a920c 100644 --- a/src/processor/map/map_copy_to.cpp +++ b/src/processor/map/map_copy_to.cpp @@ -18,13 +18,15 @@ std::unique_ptr getCopyToInfo(Schema* childSchema, std::string fileP case FileType::PARQUET: { auto copyToSchema = std::make_unique(); auto copyToExpressions = childSchema->getExpressionsInScope(); + auto countingVecPos = DataPos(childSchema->getExpressionPos(*copyToExpressions[0])); for (auto& copyToExpression : copyToExpressions) { auto [dataChunkPos, vectorPos] = childSchema->getExpressionPos(*copyToExpression); std::unique_ptr columnSchema; if (!childSchema->getGroup(dataChunkPos)->isFlat()) { // payload is unFlat and not in the same group as keys - columnSchema = std::make_unique( - true /* isUnFlat */, dataChunkPos, sizeof(overflow_value_t)); + columnSchema = std::make_unique(true /* isUnFlat */, dataChunkPos, + sizeof(overflow_value_t)); + countingVecPos = DataPos(childSchema->getExpressionPos(*copyToExpression)); } else { columnSchema = std::make_unique(false /* isUnFlat */, dataChunkPos, LogicalTypeUtils::getRowLayoutSize(copyToExpression->getDataType())); @@ -32,7 +34,8 @@ std::unique_ptr getCopyToInfo(Schema* childSchema, std::string fileP copyToSchema->appendColumn(std::move(columnSchema)); } return std::make_unique(std::move(copyToSchema), std::move(columnsTypes), - std::move(columnNames), std::move(vectorsToCopyPos), std::move(filePath)); + std::move(columnNames), std::move(vectorsToCopyPos), std::move(filePath), + std::move(countingVecPos)); } case FileType::CSV: { return std::make_unique(std::move(columnNames), std::move(vectorsToCopyPos), @@ -85,9 +88,9 @@ std::unique_ptr PlanMapper::mapCopyTo(LogicalOperator* logical } std::shared_ptr fTable; auto ftTableSchema = std::make_unique(); - fTable = std::make_shared(memoryManager, std::move(ftTableSchema)); - return createFactorizedTableScan(binder::expression_vector{}, std::vector{}, - childSchema, fTable, 0, std::move(copyTo)); + fTable = std::make_shared(clientContext->getMemoryManager(), + std::move(ftTableSchema)); + return createEmptyFTableScan(fTable, 0, std::move(copyTo)); } } // namespace processor diff --git a/src/processor/map/map_create_macro.cpp b/src/processor/map/map_create_macro.cpp index 1e36a59ca8b..4bb5e20bcf2 100644 --- a/src/processor/map/map_create_macro.cpp +++ b/src/processor/map/map_create_macro.cpp @@ -13,8 +13,8 @@ std::unique_ptr PlanMapper::mapCreateMacro( auto outSchema = logicalCreateMacro->getSchema(); auto outputExpression = logicalCreateMacro->getOutputExpression(); auto outputPos = DataPos(outSchema->getExpressionPos(*outputExpression)); - auto createMacroInfo = std::make_unique( - logicalCreateMacro->getMacroName(), logicalCreateMacro->getMacro(), outputPos, catalog); + auto createMacroInfo = std::make_unique(logicalCreateMacro->getMacroName(), + logicalCreateMacro->getMacro(), outputPos, clientContext->getCatalog()); return std::make_unique(PhysicalOperatorType::CREATE_MACRO, std::move(createMacroInfo), getOperatorID(), logicalCreateMacro->getExpressionsForPrinting()); diff --git a/src/processor/map/map_ddl.cpp b/src/processor/map/map_ddl.cpp index d6d1155abfd..9737f5063cc 100644 --- a/src/processor/map/map_ddl.cpp +++ b/src/processor/map/map_ddl.cpp @@ -1,18 +1,10 @@ #include "planner/operator/ddl/logical_alter.h" #include "planner/operator/ddl/logical_create_table.h" #include "planner/operator/ddl/logical_drop_table.h" -#include "processor/operator/ddl/add_node_property.h" -#include "processor/operator/ddl/add_rel_property.h" -#include "processor/operator/ddl/create_node_table.h" -#include "processor/operator/ddl/create_rdf_graph.h" -#include "processor/operator/ddl/create_rel_table.h" -#include "processor/operator/ddl/create_rel_table_group.h" -#include "processor/operator/ddl/drop_property.h" +#include "processor/operator/ddl/alter.h" +#include "processor/operator/ddl/create_table.h" #include "processor/operator/ddl/drop_table.h" -#include "processor/operator/ddl/rename_property.h" -#include "processor/operator/ddl/rename_table.h" #include "processor/plan_mapper.h" -#include "transaction/transaction.h" using namespace kuzu::binder; using namespace kuzu::common; @@ -29,125 +21,29 @@ static DataPos getOutputPos(LogicalDDL* logicalDDL) { std::unique_ptr PlanMapper::mapCreateTable(LogicalOperator* logicalOperator) { auto createTable = (LogicalCreateTable*)logicalOperator; - switch (createTable->getInfo()->type) { - case TableType::NODE: { - return mapCreateNodeTable(logicalOperator); - } - case TableType::REL: { - return mapCreateRelTable(logicalOperator); - } - case TableType::REL_GROUP: { - return mapCreateRelTableGroup(logicalOperator); - } - case TableType::RDF: { - return mapCreateRdfGraph(logicalOperator); - } - default: - KU_UNREACHABLE; - } -} - -std::unique_ptr PlanMapper::mapCreateNodeTable(LogicalOperator* logicalOperator) { - auto createTable = (LogicalCreateTable*)logicalOperator; - return std::make_unique(catalog, &storageManager, - createTable->getInfo()->copy(), getOutputPos(createTable), getOperatorID(), - createTable->getExpressionsForPrinting()); -} - -std::unique_ptr PlanMapper::mapCreateRelTable(LogicalOperator* logicalOperator) { - auto createTable = (LogicalCreateTable*)logicalOperator; - return std::make_unique(catalog, &storageManager, - createTable->getInfo()->copy(), getOutputPos(createTable), getOperatorID(), - createTable->getExpressionsForPrinting()); -} - -std::unique_ptr PlanMapper::mapCreateRelTableGroup( - LogicalOperator* logicalOperator) { - auto createTable = (LogicalCreateTable*)logicalOperator; - return std::make_unique(catalog, &storageManager, - createTable->getInfo()->copy(), getOutputPos(createTable), getOperatorID(), - createTable->getExpressionsForPrinting()); -} - -std::unique_ptr PlanMapper::mapCreateRdfGraph(LogicalOperator* logicalOperator) { - auto createTable = (LogicalCreateTable*)logicalOperator; - return std::make_unique(catalog, &storageManager, - createTable->getInfo()->copy(), getOutputPos(createTable), getOperatorID(), - createTable->getExpressionsForPrinting()); + return std::make_unique(createTable->getInfo()->copy(), getOutputPos(createTable), + getOperatorID(), createTable->getExpressionsForPrinting()); } std::unique_ptr PlanMapper::mapDropTable(LogicalOperator* logicalOperator) { auto dropTable = (LogicalDropTable*)logicalOperator; - return std::make_unique(catalog, dropTable->getTableName(), dropTable->getTableID(), + return std::make_unique(dropTable->getTableName(), dropTable->getTableID(), getOutputPos(dropTable), getOperatorID(), dropTable->getExpressionsForPrinting()); } std::unique_ptr PlanMapper::mapAlter(LogicalOperator* logicalOperator) { auto alter = reinterpret_cast(logicalOperator); - switch (alter->getInfo()->alterType) { - case AlterType::RENAME_TABLE: { - return mapRenameTable(logicalOperator); - } - case AlterType::ADD_PROPERTY: { - return mapAddProperty(logicalOperator); - } - case AlterType::DROP_PROPERTY: { - return mapDropProperty(logicalOperator); - } - case AlterType::RENAME_PROPERTY: { - return mapRenameProperty(logicalOperator); - } - default: - KU_UNREACHABLE; - } -} - -std::unique_ptr PlanMapper::mapRenameTable(LogicalOperator* logicalOperator) { - auto alter = reinterpret_cast(logicalOperator); - auto info = alter->getInfo(); - auto extraInfo = reinterpret_cast(info->extraInfo.get()); - return std::make_unique(catalog, info->tableID, extraInfo->newName, + std::unique_ptr defaultValueEvaluator; + if (alter->getInfo()->alterType == AlterType::ADD_PROPERTY) { + auto& addPropInfo = + ku_dynamic_cast( + *alter->getInfo()->extraInfo); + defaultValueEvaluator = + ExpressionMapper::getEvaluator(addPropInfo.defaultValue, alter->getSchema()); + } + return std::make_unique(alter->getInfo()->copy(), std::move(defaultValueEvaluator), getOutputPos(alter), getOperatorID(), alter->getExpressionsForPrinting()); } -std::unique_ptr PlanMapper::mapAddProperty(LogicalOperator* logicalOperator) { - auto alter = reinterpret_cast(logicalOperator); - auto info = alter->getInfo(); - auto extraInfo = reinterpret_cast(info->extraInfo.get()); - auto expressionEvaluator = - ExpressionMapper::getEvaluator(extraInfo->defaultValue, alter->getSchema()); - auto tableSchema = - catalog->getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, info->tableID); - switch (tableSchema->getTableType()) { - case TableType::NODE: - return std::make_unique(catalog, info->tableID, extraInfo->propertyName, - extraInfo->dataType.copy(), std::move(expressionEvaluator), storageManager, - getOutputPos(alter), getOperatorID(), alter->getExpressionsForPrinting()); - case TableType::REL: - return std::make_unique(catalog, info->tableID, extraInfo->propertyName, - extraInfo->dataType.copy(), std::move(expressionEvaluator), storageManager, - getOutputPos(alter), getOperatorID(), alter->getExpressionsForPrinting()); - default: - KU_UNREACHABLE; - } -} - -std::unique_ptr PlanMapper::mapDropProperty(LogicalOperator* logicalOperator) { - auto alter = reinterpret_cast(logicalOperator); - auto info = alter->getInfo(); - auto extraInfo = reinterpret_cast(info->extraInfo.get()); - return std::make_unique(catalog, info->tableID, extraInfo->propertyID, - getOutputPos(alter), storageManager, getOperatorID(), alter->getExpressionsForPrinting()); -} - -std::unique_ptr PlanMapper::mapRenameProperty(LogicalOperator* logicalOperator) { - auto alter = reinterpret_cast(logicalOperator); - auto info = alter->getInfo(); - auto extraInfo = reinterpret_cast(info->extraInfo.get()); - return std::make_unique(catalog, info->tableID, extraInfo->propertyID, - extraInfo->newName, getOutputPos(alter), getOperatorID(), - alter->getExpressionsForPrinting()); -} - } // namespace processor } // namespace kuzu diff --git a/src/processor/map/map_delete.cpp b/src/processor/map/map_delete.cpp index 42db1351a21..30e436f5e0f 100644 --- a/src/processor/map/map_delete.cpp +++ b/src/processor/map/map_delete.cpp @@ -1,7 +1,7 @@ #include "planner/operator/persistent/logical_delete.h" #include "processor/operator/persistent/delete.h" #include "processor/plan_mapper.h" -#include "transaction/transaction.h" +#include "storage/storage_manager.h" using namespace kuzu::binder; using namespace kuzu::catalog; @@ -12,28 +12,31 @@ using namespace kuzu::storage; namespace kuzu { namespace processor { -static std::unique_ptr getNodeDeleteExecutor(Catalog* catalog, - StorageManager& storageManager, LogicalDeleteNodeInfo* info, const Schema& inSchema) { +static std::unique_ptr getNodeDeleteExecutor(LogicalDeleteNodeInfo* info, + const Schema& inSchema, main::ClientContext* clientContext) { auto nodeIDPos = DataPos(inSchema.getExpressionPos(*info->node->getInternalID())); + auto storageManager = clientContext->getStorageManager(); + auto catalog = clientContext->getCatalog(); if (info->node->isMultiLabeled()) { std::unordered_map tableIDToTableMap; std::unordered_map> tableIDToFwdRelTablesMap; std::unordered_map> tableIDToBwdRelTablesMap; for (auto tableID : info->node->getTableIDs()) { - auto tableEntry = - catalog->getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, tableID); + auto tableEntry = catalog->getTableCatalogEntry(clientContext->getTx(), tableID); auto nodeTableEntry = ku_dynamic_cast(tableEntry); - auto table = storageManager.getNodeTable(tableID); + auto table = ku_dynamic_cast(storageManager->getTable(tableID)); auto fwdRelTableIDs = nodeTableEntry->getFwdRelTableIDSet(); auto bwdRelTableIDs = nodeTableEntry->getBwdRelTableIDSet(); std::unordered_set fwdRelTables; std::unordered_set bwdRelTables; for (auto relTableID : fwdRelTableIDs) { - fwdRelTables.insert(storageManager.getRelTable(relTableID)); + fwdRelTables.insert( + ku_dynamic_cast(storageManager->getTable(relTableID))); } for (auto relTableID : bwdRelTableIDs) { - bwdRelTables.insert(storageManager.getRelTable(relTableID)); + bwdRelTables.insert( + ku_dynamic_cast(storageManager->getTable(relTableID))); } tableIDToTableMap.insert({tableID, table}); tableIDToFwdRelTablesMap[tableID] = fwdRelTables; @@ -43,9 +46,10 @@ static std::unique_ptr getNodeDeleteExecutor(Catalog* catalo std::move(tableIDToFwdRelTablesMap), std::move(tableIDToBwdRelTablesMap), info->deleteType, nodeIDPos); } else { - auto table = storageManager.getNodeTable(info->node->getSingleTableID()); - auto tableEntry = catalog->getTableCatalogEntry( - &transaction::DUMMY_READ_TRANSACTION, info->node->getSingleTableID()); + auto table = ku_dynamic_cast( + storageManager->getTable(info->node->getSingleTableID())); + auto tableEntry = catalog->getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, + info->node->getSingleTableID()); auto nodeTableEntry = ku_dynamic_cast(tableEntry); auto fwdRelTableIDs = nodeTableEntry->getFwdRelTableIDSet(); @@ -53,13 +57,15 @@ static std::unique_ptr getNodeDeleteExecutor(Catalog* catalo std::unordered_set fwdRelTables; std::unordered_set bwdRelTables; for (auto tableID : fwdRelTableIDs) { - fwdRelTables.insert(storageManager.getRelTable(tableID)); + fwdRelTables.insert( + ku_dynamic_cast(storageManager->getTable(tableID))); } for (auto tableID : bwdRelTableIDs) { - bwdRelTables.insert(storageManager.getRelTable(tableID)); + bwdRelTables.insert( + ku_dynamic_cast(storageManager->getTable(tableID))); } - return std::make_unique( - table, std::move(fwdRelTables), std::move(bwdRelTables), info->deleteType, nodeIDPos); + return std::make_unique(table, std::move(fwdRelTables), + std::move(bwdRelTables), info->deleteType, nodeIDPos); } } @@ -69,7 +75,7 @@ std::unique_ptr PlanMapper::mapDeleteNode(LogicalOperator* log auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); std::vector> executors; for (auto deleteInfo : logicalDeleteNode->getInfos()) { - executors.push_back(getNodeDeleteExecutor(catalog, storageManager, deleteInfo, *inSchema)); + executors.push_back(getNodeDeleteExecutor(deleteInfo, *inSchema, clientContext)); } return std::make_unique(std::move(executors), std::move(prevOperator), getOperatorID(), logicalDeleteNode->getExpressionsForPrinting()); @@ -84,15 +90,16 @@ static std::unique_ptr getRelDeleteExecutor( if (rel.isMultiLabeled()) { std::unordered_map tableIDToTableMap; for (auto tableID : rel.getTableIDs()) { - auto table = storageManager.getRelTable(tableID); + auto table = ku_dynamic_cast(storageManager.getTable(tableID)); tableIDToTableMap.insert({tableID, table}); } - return std::make_unique( - std::move(tableIDToTableMap), srcNodePos, dstNodePos, relIDPos); + return std::make_unique(std::move(tableIDToTableMap), + srcNodePos, dstNodePos, relIDPos); } else { - auto table = storageManager.getRelTable(rel.getSingleTableID()); - return std::make_unique( - table, srcNodePos, dstNodePos, relIDPos); + auto table = + ku_dynamic_cast(storageManager.getTable(rel.getSingleTableID())); + return std::make_unique(table, srcNodePos, dstNodePos, + relIDPos); } } @@ -102,7 +109,8 @@ std::unique_ptr PlanMapper::mapDeleteRel(LogicalOperator* logi auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); std::vector> Executors; for (auto& rel : logicalDeleteRel->getRelsRef()) { - Executors.push_back(getRelDeleteExecutor(storageManager, *rel, *inSchema)); + Executors.push_back( + getRelDeleteExecutor(*clientContext->getStorageManager(), *rel, *inSchema)); } return std::make_unique(std::move(Executors), std::move(prevOperator), getOperatorID(), logicalOperator->getExpressionsForPrinting()); diff --git a/src/processor/map/map_detach_database.cpp b/src/processor/map/map_detach_database.cpp new file mode 100644 index 00000000000..be70e803e90 --- /dev/null +++ b/src/processor/map/map_detach_database.cpp @@ -0,0 +1,19 @@ +#include "planner/operator/logical_detach_database.h" +#include "processor/operator/detach_database.h" +#include "processor/plan_mapper.h" + +namespace kuzu { +namespace processor { + +using namespace kuzu::planner; + +std::unique_ptr PlanMapper::mapDetachDatabase( + planner::LogicalOperator* logicalOperator) { + auto detachDatabase = + common::ku_dynamic_cast(logicalOperator); + return std::make_unique(detachDatabase->getDBName(), getOperatorID(), + detachDatabase->getExpressionsForPrinting()); +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/map/map_distinct.cpp b/src/processor/map/map_distinct.cpp index 67eb1ab37c4..a1de19d1a49 100644 --- a/src/processor/map/map_distinct.cpp +++ b/src/processor/map/map_distinct.cpp @@ -16,10 +16,10 @@ std::unique_ptr PlanMapper::mapDistinct(LogicalOperator* logic std::vector> emptyAggFunctions; std::vector> emptyAggInputInfos; std::vector emptyAggregatesOutputPos; - return createHashAggregate(logicalDistinct.getKeyExpressions(), - logicalDistinct.getDependentKeyExpressions(), std::move(emptyAggFunctions), - std::move(emptyAggInputInfos), std::move(emptyAggregatesOutputPos), inSchema, outSchema, - std::move(prevOperator), logicalDistinct.getExpressionsForPrinting()); + return createHashAggregate(logicalDistinct.getKeys(), logicalDistinct.getPayloads(), + std::move(emptyAggFunctions), std::move(emptyAggInputInfos), + std::move(emptyAggregatesOutputPos), inSchema, outSchema, std::move(prevOperator), + logicalDistinct.getExpressionsForPrinting(), nullptr /* markExpression */); } } // namespace processor diff --git a/src/processor/map/map_dummy_scan.cpp b/src/processor/map/map_dummy_scan.cpp index cd622babfdd..3cd85ae07b0 100644 --- a/src/processor/map/map_dummy_scan.cpp +++ b/src/processor/map/map_dummy_scan.cpp @@ -18,6 +18,7 @@ std::unique_ptr PlanMapper::mapDummyScan(LogicalOperator* /*lo std::make_unique(false, 0 /* all expressions are in the same datachunk */, LogicalTypeUtils::getRowLayoutSize(expression->dataType))); auto expressionEvaluator = ExpressionMapper::getEvaluator(expression, inSchema.get()); + auto memoryManager = clientContext->getMemoryManager(); // expression can be evaluated statically and does not require an actual resultset to init expressionEvaluator->init(ResultSet(0) /* dummy resultset */, memoryManager); expressionEvaluator->evaluate(clientContext); @@ -25,8 +26,7 @@ std::unique_ptr PlanMapper::mapDummyScan(LogicalOperator* /*lo vectorsToAppend.push_back(expressionEvaluator->resultVector.get()); auto table = std::make_shared(memoryManager, std::move(tableSchema)); table->append(vectorsToAppend); - return createFactorizedTableScan(binder::expression_vector{}, std::vector{}, - inSchema.get(), table, 1 /* maxMorselSize */, nullptr /* child */); + return createEmptyFTableScan(table, 1 /* maxMorselSize */); } } // namespace processor diff --git a/src/processor/map/map_explain.cpp b/src/processor/map/map_explain.cpp index a0043d141c0..9e3b54903e5 100644 --- a/src/processor/map/map_explain.cpp +++ b/src/processor/map/map_explain.cpp @@ -6,12 +6,12 @@ using namespace kuzu::common; using namespace kuzu::planner; +using namespace kuzu::binder; namespace kuzu { namespace processor { -std::unique_ptr PlanMapper::mapExplain( - planner::LogicalOperator* logicalOperator) { +std::unique_ptr PlanMapper::mapExplain(LogicalOperator* logicalOperator) { auto logicalExplain = (LogicalExplain*)logicalOperator; auto outSchema = logicalExplain->getSchema(); auto inSchema = logicalExplain->getChild(0)->getSchema(); @@ -30,10 +30,10 @@ std::unique_ptr PlanMapper::mapExplain( auto planPrinter = std::make_unique(physicalPlanToExplain.get(), profiler.get()); auto explainStr = planPrinter->printPlanToOstream().str(); - auto factorizedTable = - FactorizedTableUtils::getFactorizedTableForOutputMsg(explainStr, memoryManager); - return createFactorizedTableScanAligned(binder::expression_vector{outputExpression}, - outSchema, factorizedTable, DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, nullptr); + auto factorizedTable = FactorizedTableUtils::getFactorizedTableForOutputMsg(explainStr, + clientContext->getMemoryManager()); + return createFTableScanAligned(expression_vector{outputExpression}, outSchema, + factorizedTable, DEFAULT_VECTOR_CAPACITY /* maxMorselSize */); } } diff --git a/src/processor/map/map_expressions_scan.cpp b/src/processor/map/map_expressions_scan.cpp index 6c1b5462b55..4a6558ee012 100644 --- a/src/processor/map/map_expressions_scan.cpp +++ b/src/processor/map/map_expressions_scan.cpp @@ -14,7 +14,7 @@ std::unique_ptr PlanMapper::mapExpressionsScan( auto expressionsScan = (planner::LogicalExpressionsScan*)logicalOperator; auto outerAccumulate = (planner::LogicalAccumulate*)expressionsScan->getOuterAccumulate(); expression_map materializedExpressionToColIdx; - auto materializedExpressions = outerAccumulate->getExpressionsToAccumulate(); + auto materializedExpressions = outerAccumulate->getPayloads(); for (auto i = 0u; i < materializedExpressions.size(); ++i) { materializedExpressionToColIdx.insert({materializedExpressions[i], i}); } @@ -31,8 +31,8 @@ std::unique_ptr PlanMapper::mapExpressionsScan( KU_ASSERT(physicalOp->getChild(0)->getOperatorType() == PhysicalOperatorType::RESULT_COLLECTOR); auto resultCollector = (ResultCollector*)physicalOp->getChild(0); auto table = resultCollector->getResultFactorizedTable(); - return createFactorizedTableScan(expressionsToScan, colIndicesToScan, schema, table, - DEFAULT_VECTOR_CAPACITY /* maxMorselSize */, nullptr); + return createFTableScan(expressionsToScan, colIndicesToScan, schema, table, + DEFAULT_VECTOR_CAPACITY /* maxMorselSize */); } } // namespace processor diff --git a/src/processor/map/map_extend.cpp b/src/processor/map/map_extend.cpp index e95fab1af13..7263f62ff76 100644 --- a/src/processor/map/map_extend.cpp +++ b/src/processor/map/map_extend.cpp @@ -3,7 +3,7 @@ #include "processor/operator/scan/scan_multi_rel_tables.h" #include "processor/operator/scan/scan_rel_table.h" #include "processor/plan_mapper.h" -#include "transaction/transaction.h" +#include "storage/storage_manager.h" using namespace kuzu::binder; using namespace kuzu::common; @@ -15,10 +15,10 @@ namespace kuzu { namespace processor { static std::unique_ptr getRelTableScanInfo(TableCatalogEntry* tableCatalogEntry, - RelDataDirection direction, StorageManager& storageManager, + RelDataDirection direction, StorageManager* storageManager, const expression_vector& properties) { auto relTableID = tableCatalogEntry->getTableID(); - auto relTable = storageManager.getRelTable(relTableID); + auto relTable = ku_dynamic_cast(storageManager->getTable(relTableID)); std::vector columnIDs; for (auto& property : properties) { auto propertyExpression = ku_dynamic_cast(property.get()); @@ -32,16 +32,18 @@ static std::unique_ptr getRelTableScanInfo(TableCatalogEntry* static std::unique_ptr populateRelTableCollectionScanner( table_id_t boundNodeTableID, const RelExpression& rel, ExtendDirection extendDirection, - const expression_vector& properties, StorageManager& storageManager, const Catalog& catalog) { + const expression_vector& properties, const main::ClientContext& clientContext) { std::vector> scanInfos; + auto catalog = clientContext.getCatalog(); + auto storageManager = clientContext.getStorageManager(); for (auto relTableID : rel.getTableIDs()) { auto relTableEntry = ku_dynamic_cast( - catalog.getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, relTableID)); + catalog->getTableCatalogEntry(clientContext.getTx(), relTableID)); switch (extendDirection) { case ExtendDirection::FWD: { if (relTableEntry->getBoundTableID(RelDataDirection::FWD) == boundNodeTableID) { - auto scanInfo = getRelTableScanInfo( - relTableEntry, RelDataDirection::FWD, storageManager, properties); + auto scanInfo = getRelTableScanInfo(relTableEntry, RelDataDirection::FWD, + storageManager, properties); if (scanInfo != nullptr) { scanInfos.push_back(std::move(scanInfo)); } @@ -49,8 +51,8 @@ static std::unique_ptr populateRelTableCollectionScan } break; case ExtendDirection::BWD: { if (relTableEntry->getBoundTableID(RelDataDirection::BWD) == boundNodeTableID) { - auto scanInfo = getRelTableScanInfo( - relTableEntry, RelDataDirection::BWD, storageManager, properties); + auto scanInfo = getRelTableScanInfo(relTableEntry, RelDataDirection::BWD, + storageManager, properties); if (scanInfo != nullptr) { scanInfos.push_back(std::move(scanInfo)); } @@ -58,15 +60,15 @@ static std::unique_ptr populateRelTableCollectionScan } break; case ExtendDirection::BOTH: { if (relTableEntry->getBoundTableID(RelDataDirection::FWD) == boundNodeTableID) { - auto scanInfoFWD = getRelTableScanInfo( - relTableEntry, RelDataDirection::FWD, storageManager, properties); + auto scanInfoFWD = getRelTableScanInfo(relTableEntry, RelDataDirection::FWD, + storageManager, properties); if (scanInfoFWD != nullptr) { scanInfos.push_back(std::move(scanInfoFWD)); } } if (relTableEntry->getBoundTableID(RelDataDirection::BWD) == boundNodeTableID) { - auto scanInfoBWD = getRelTableScanInfo( - relTableEntry, RelDataDirection::BWD, storageManager, properties); + auto scanInfoBWD = getRelTableScanInfo(relTableEntry, RelDataDirection::BWD, + storageManager, properties); if (scanInfoBWD != nullptr) { scanInfos.push_back(std::move(scanInfoBWD)); } @@ -101,18 +103,18 @@ std::unique_ptr PlanMapper::mapExtend(LogicalOperator* logical if (!rel->isMultiLabeled() && !boundNode->isMultiLabeled() && extendDirection != ExtendDirection::BOTH) { auto relTableEntry = ku_dynamic_cast( - catalog->getTableCatalogEntry( - &transaction::DUMMY_READ_TRANSACTION, rel->getSingleTableID())); + clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), + rel->getSingleTableID())); auto relDataDirection = ExtendDirectionUtils::getRelDataDirection(extendDirection); - auto scanInfo = getRelTableScanInfo( - relTableEntry, relDataDirection, storageManager, extend->getProperties()); + auto scanInfo = getRelTableScanInfo(relTableEntry, relDataDirection, + clientContext->getStorageManager(), extend->getProperties()); return std::make_unique(std::move(scanInfo), inNodeVectorPos, outVectorsPos, std::move(prevOperator), getOperatorID(), extend->getExpressionsForPrinting()); } else { // map to generic extend std::unordered_map> scanners; for (auto boundNodeTableID : boundNode->getTableIDs()) { auto scanner = populateRelTableCollectionScanner(boundNodeTableID, *rel, - extendDirection, extend->getProperties(), storageManager, *catalog); + extendDirection, extend->getProperties(), *clientContext); if (scanner != nullptr) { scanners.insert({boundNodeTableID, std::move(scanner)}); } diff --git a/src/processor/map/map_hash_join.cpp b/src/processor/map/map_hash_join.cpp index 669c4d8ee09..f13837b821a 100644 --- a/src/processor/map/map_hash_join.cpp +++ b/src/processor/map/map_hash_join.cpp @@ -10,8 +10,8 @@ using namespace kuzu::common; namespace kuzu { namespace processor { -std::unique_ptr PlanMapper::createHashBuildInfo( - const Schema& buildSchema, const expression_vector& keys, const expression_vector& payloads) { +std::unique_ptr PlanMapper::createHashBuildInfo(const Schema& buildSchema, + const expression_vector& keys, const expression_vector& payloads) { planner::f_group_pos_set keyGroupPosSet; std::vector keysPos; std::vector fStateTypes; @@ -41,18 +41,20 @@ std::unique_ptr PlanMapper::createHashBuildInfo( columnSchema = std::make_unique(false /* isUnFlat */, pos.dataChunkPos, LogicalTypeUtils::getRowLayoutSize(payload->dataType)); } else { - columnSchema = std::make_unique( - true /* isUnFlat */, pos.dataChunkPos, (uint32_t)sizeof(overflow_value_t)); + columnSchema = std::make_unique(true /* isUnFlat */, pos.dataChunkPos, + (uint32_t)sizeof(overflow_value_t)); } tableSchema->appendColumn(std::move(columnSchema)); payloadsPos.push_back(pos); } - auto pointerType = LogicalType(LogicalTypeID::INT64); + auto hashValueColumn = std::make_unique(false /* isUnFlat */, + INVALID_DATA_CHUNK_POS, LogicalTypeUtils::getRowLayoutSize(*LogicalType::HASH())); + tableSchema->appendColumn(std::move(hashValueColumn)); auto pointerColumn = std::make_unique(false /* isUnFlat */, - INVALID_DATA_CHUNK_POS, LogicalTypeUtils::getRowLayoutSize(pointerType)); + INVALID_DATA_CHUNK_POS, LogicalTypeUtils::getRowLayoutSize(*LogicalType::INT64())); tableSchema->appendColumn(std::move(pointerColumn)); - return std::make_unique( - std::move(keysPos), std::move(fStateTypes), std::move(payloadsPos), std::move(tableSchema)); + return std::make_unique(std::move(keysPos), std::move(fStateTypes), + std::move(payloadsPos), std::move(tableSchema)); } std::unique_ptr PlanMapper::mapHashJoin(LogicalOperator* logicalOperator) { @@ -81,8 +83,8 @@ std::unique_ptr PlanMapper::mapHashJoin(LogicalOperator* logic ExpressionUtil::excludeExpressions(hashJoin->getExpressionsToMaterialize(), probeKeys); // Create build auto buildInfo = createHashBuildInfo(*buildSchema, buildKeys, payloads); - auto globalHashTable = std::make_unique( - *memoryManager, LogicalType::copy(buildKeyTypes), buildInfo->getTableSchema()->copy()); + auto globalHashTable = std::make_unique(*clientContext->getMemoryManager(), + LogicalType::copy(buildKeyTypes), buildInfo->getTableSchema()->copy()); auto sharedState = std::make_shared(std::move(globalHashTable)); auto hashJoinBuild = make_unique(std::make_unique(buildSchema), sharedState, diff --git a/src/processor/map/map_in_query_call.cpp b/src/processor/map/map_in_query_call.cpp index 0402488be53..59ca20c9301 100644 --- a/src/processor/map/map_in_query_call.cpp +++ b/src/processor/map/map_in_query_call.cpp @@ -23,8 +23,8 @@ std::unique_ptr PlanMapper::mapInQueryCall(LogicalOperator* lo info.outputType = outPosV.empty() ? TableScanOutputType::EMPTY : TableScanOutputType::SINGLE_DATA_CHUNK; auto sharedState = std::make_shared(); - return std::make_unique( - std::move(info), sharedState, getOperatorID(), call->getExpressionsForPrinting()); + return std::make_unique(std::move(info), sharedState, getOperatorID(), + call->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/map_index_scan_node.cpp b/src/processor/map/map_index_scan_node.cpp index 88b43e0b231..7af7630ece9 100644 --- a/src/processor/map/map_index_scan_node.cpp +++ b/src/processor/map/map_index_scan_node.cpp @@ -2,6 +2,8 @@ #include "processor/operator/index_lookup.h" #include "processor/operator/index_scan.h" #include "processor/plan_mapper.h" +#include "storage/storage_manager.h" +#include "storage/store/node_table.h" using namespace kuzu::planner; @@ -15,21 +17,25 @@ std::unique_ptr PlanMapper::mapIndexScan( auto outSchema = logicalIndexScan->getSchema(); auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); // TODO(Xiyang): potentially we should merge IndexScan and IndexLook + auto storageManager = clientContext->getStorageManager(); if (logicalIndexScan->getNumInfos() > 1) { std::vector> indexLookupInfos; for (auto i = 0u; i < logicalIndexScan->getNumInfos(); ++i) { auto info = logicalIndexScan->getInfo(i); - auto storageIndex = storageManager.getNodeTable(info->nodeTableID)->getPKIndex(); + auto storageIndex = common::ku_dynamic_cast( + storageManager->getTable(info->nodeTableID)) + ->getPKIndex(); auto offsetPos = DataPos(outSchema->getExpressionPos(*info->offset)); auto keyPos = DataPos(outSchema->getExpressionPos(*info->key)); - indexLookupInfos.push_back(std::make_unique( - info->indexType.copy(), storageIndex, keyPos, offsetPos)); + indexLookupInfos.push_back(std::make_unique(info->indexType.copy(), + storageIndex, keyPos, offsetPos)); } return std::make_unique(std::move(indexLookupInfos), std::move(prevOperator), getOperatorID(), logicalIndexScan->getExpressionsForPrinting()); } else { auto info = logicalIndexScan->getInfo(0); - auto nodeTable = storageManager.getNodeTable(info->nodeTableID); + auto nodeTable = common::ku_dynamic_cast( + storageManager->getTable(info->nodeTableID)); auto evaluator = ExpressionMapper::getEvaluator(info->key, inSchema); auto outDataPos = DataPos(outSchema->getExpressionPos(*info->offset)); return make_unique(nodeTable->getTableID(), nodeTable->getPKIndex(), diff --git a/src/processor/map/map_insert.cpp b/src/processor/map/map_insert.cpp index b63a37feaf0..66c9a48b2f5 100644 --- a/src/processor/map/map_insert.cpp +++ b/src/processor/map/map_insert.cpp @@ -3,7 +3,7 @@ #include "planner/operator/persistent/logical_insert.h" #include "processor/operator/persistent/insert.h" #include "processor/plan_mapper.h" -#include "transaction/transaction.h" +#include "storage/storage_manager.h" using namespace kuzu::evaluator; using namespace kuzu::planner; @@ -15,8 +15,8 @@ using namespace kuzu::binder; namespace kuzu { namespace processor { -static std::vector populateReturnVectorsPos( - const LogicalInsertInfo& info, const Schema& schema) { +static std::vector populateReturnVectorsPos(const LogicalInsertInfo& info, + const Schema& schema) { std::vector result; for (auto i = 0u; i < info.columnDataExprs.size(); ++i) { if (info.isReturnColumnExprs[i]) { @@ -28,24 +28,27 @@ static std::vector populateReturnVectorsPos( return result; } -std::unique_ptr PlanMapper::getNodeInsertExecutor( - const LogicalInsertInfo* info, const Schema& inSchema, const Schema& outSchema) const { +std::unique_ptr PlanMapper::getNodeInsertExecutor(const LogicalInsertInfo* info, + const Schema& inSchema, const Schema& outSchema) const { + auto storageManager = clientContext->getStorageManager(); auto node = ku_dynamic_cast(info->pattern.get()); auto nodeTableID = node->getSingleTableID(); - auto table = storageManager.getNodeTable(nodeTableID); + auto table = ku_dynamic_cast(storageManager->getTable(nodeTableID)); std::unordered_set fwdRelTablesToInit; std::unordered_set bwdRelTablesToInit; auto tableCatalogEntry = - catalog->getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, nodeTableID); + clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), nodeTableID); auto nodeTableSchema = ku_dynamic_cast(tableCatalogEntry); auto fwdRelTableIDs = nodeTableSchema->getFwdRelTableIDSet(); auto bwdRelTableIDs = nodeTableSchema->getBwdRelTableIDSet(); for (auto relTableID : fwdRelTableIDs) { - fwdRelTablesToInit.insert(storageManager.getRelTable(relTableID)); + fwdRelTablesToInit.insert( + ku_dynamic_cast(storageManager->getTable(relTableID))); } for (auto relTableID : bwdRelTableIDs) { - bwdRelTablesToInit.insert(storageManager.getRelTable(relTableID)); + bwdRelTablesToInit.insert( + ku_dynamic_cast(storageManager->getTable(relTableID))); } auto nodeIDPos = DataPos(outSchema.getExpressionPos(*node->getInternalID())); auto returnVectorsPos = populateReturnVectorsPos(*info, outSchema); @@ -61,10 +64,11 @@ std::unique_ptr PlanMapper::getNodeInsertExecutor( std::unique_ptr PlanMapper::getRelInsertExecutor( const planner::LogicalInsertInfo* info, const planner::Schema& inSchema, - const planner::Schema& outSchema) { + const planner::Schema& outSchema) const { + auto storageManager = clientContext->getStorageManager(); auto rel = ku_dynamic_cast(info->pattern.get()); auto relTableID = rel->getSingleTableID(); - auto table = storageManager.getRelTable(relTableID); + auto table = ku_dynamic_cast(storageManager->getTable(relTableID)); auto srcNode = rel->getSrcNode(); auto dstNode = rel->getDstNode(); auto srcNodePos = DataPos(inSchema.getExpressionPos(*srcNode->getInternalID())); @@ -75,7 +79,7 @@ std::unique_ptr PlanMapper::getRelInsertExecutor( for (auto& expr : info->columnDataExprs) { evaluators.push_back(ExpressionMapper::getEvaluator(expr, &outSchema)); } - return std::make_unique(storageManager.getRelsStatistics(), table, + return std::make_unique(storageManager->getRelsStatistics(), table, srcNodePos, dstNodePos, std::move(returnVectorsPos), std::move(evaluators)); } diff --git a/src/processor/map/map_intersect.cpp b/src/processor/map/map_intersect.cpp index a2910833747..2c1b5a7cb83 100644 --- a/src/processor/map/map_intersect.cpp +++ b/src/processor/map/map_intersect.cpp @@ -23,14 +23,13 @@ std::unique_ptr PlanMapper::mapIntersect(LogicalOperator* logi for (auto i = 1u; i < logicalIntersect->getNumChildren(); i++) { auto keyNodeID = logicalIntersect->getKeyNodeID(i - 1); auto keys = expression_vector{keyNodeID}; - auto keyTypes = ExpressionUtil::getDataTypes(keys); auto buildSchema = logicalIntersect->getChild(i)->getSchema(); auto buildPrevOperator = mapOperator(logicalIntersect->getChild(i).get()); auto payloadExpressions = binder::ExpressionUtil::excludeExpressions(buildSchema->getExpressionsInScope(), keys); auto buildInfo = createHashBuildInfo(*buildSchema, keys, payloadExpressions); - auto globalHashTable = std::make_unique( - *memoryManager, LogicalType::copy(keyTypes), buildInfo->getTableSchema()->copy()); + auto globalHashTable = std::make_unique(*clientContext->getMemoryManager(), + ExpressionUtil::getDataTypes(keys), buildInfo->getTableSchema()->copy()); auto sharedState = std::make_shared(std::move(globalHashTable)); sharedStates.push_back(sharedState); children[i] = make_unique( diff --git a/src/processor/map/map_label_filter.cpp b/src/processor/map/map_label_filter.cpp index 5fac14fac92..ddf4acab562 100644 --- a/src/processor/map/map_label_filter.cpp +++ b/src/processor/map/map_label_filter.cpp @@ -12,8 +12,8 @@ std::unique_ptr PlanMapper::mapNodeLabelFilter(LogicalOperator auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); auto schema = logicalOperator->getSchema(); auto nbrNodeVectorPos = DataPos(schema->getExpressionPos(*logicalLabelFilter->getNodeID())); - auto filterInfo = std::make_unique( - nbrNodeVectorPos, logicalLabelFilter->getTableIDSet()); + auto filterInfo = std::make_unique(nbrNodeVectorPos, + logicalLabelFilter->getTableIDSet()); return std::make_unique(std::move(filterInfo), std::move(prevOperator), getOperatorID(), logicalLabelFilter->getExpressionsForPrinting()); } diff --git a/src/processor/map/map_mark_accumulate.cpp b/src/processor/map/map_mark_accumulate.cpp new file mode 100644 index 00000000000..96268c08c7d --- /dev/null +++ b/src/processor/map/map_mark_accumulate.cpp @@ -0,0 +1,26 @@ +#include "planner/operator/logical_mark_accmulate.h" +#include "processor/operator/aggregate/aggregate_input.h" +#include "processor/plan_mapper.h" + +using namespace kuzu::planner; +using namespace kuzu::common; + +namespace kuzu { +namespace processor { + +std::unique_ptr PlanMapper::mapMarkAccumulate(LogicalOperator* op) { + auto logicalMarkAccumulate = ku_dynamic_cast(op); + auto keys = logicalMarkAccumulate->getKeys(); + auto payloads = logicalMarkAccumulate->getPayloads(); + auto outSchema = logicalMarkAccumulate->getSchema(); + auto inSchema = logicalMarkAccumulate->getChild(0)->getSchema(); + auto prevOperator = mapOperator(logicalMarkAccumulate->getChild(0).get()); + return createHashAggregate(keys, payloads, + std::vector>{}, + std::vector>{}, std::vector{}, inSchema, + outSchema, std::move(prevOperator), logicalMarkAccumulate->getExpressionsForPrinting(), + logicalMarkAccumulate->getMark()); +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/map/map_merge.cpp b/src/processor/map/map_merge.cpp index 2bcc375946f..4b1b4ed3a83 100644 --- a/src/processor/map/map_merge.cpp +++ b/src/processor/map/map_merge.cpp @@ -12,7 +12,12 @@ std::unique_ptr PlanMapper::mapMerge(planner::LogicalOperator* auto outSchema = logicalMerge->getSchema(); auto inSchema = logicalMerge->getChild(0)->getSchema(); auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); - auto markPos = DataPos(inSchema->getExpressionPos(*logicalMerge->getMark())); + auto existenceMarkPos = getDataPos(*logicalMerge->getExistenceMark(), *inSchema); + auto distinctMarkPos = DataPos(); + if (logicalMerge + ->hasDistinctMark()) { // If there is no distinct mark, then every input is distinct. + distinctMarkPos = getDataPos(*logicalMerge->getDistinctMark(), *inSchema); + } std::vector nodeInsertExecutors; for (auto& info : logicalMerge->getInsertNodeInfosRef()) { nodeInsertExecutors.push_back(getNodeInsertExecutor(&info, *inSchema, *outSchema)->copy()); @@ -37,11 +42,11 @@ std::unique_ptr PlanMapper::mapMerge(planner::LogicalOperator* for (auto& info : logicalMerge->getOnMatchSetRelInfosRef()) { onMatchRelSetExecutors.push_back(getRelSetExecutor(info.get(), *inSchema)); } - return std::make_unique(markPos, std::move(nodeInsertExecutors), - std::move(relInsertExecutors), std::move(onCreateNodeSetExecutors), - std::move(onCreateRelSetExecutors), std::move(onMatchNodeSetExecutors), - std::move(onMatchRelSetExecutors), std::move(prevOperator), getOperatorID(), - logicalMerge->getExpressionsForPrinting()); + return std::make_unique(existenceMarkPos, distinctMarkPos, + std::move(nodeInsertExecutors), std::move(relInsertExecutors), + std::move(onCreateNodeSetExecutors), std::move(onCreateRelSetExecutors), + std::move(onMatchNodeSetExecutors), std::move(onMatchRelSetExecutors), + std::move(prevOperator), getOperatorID(), logicalMerge->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/map_multiplicity_reducer.cpp b/src/processor/map/map_multiplicity_reducer.cpp index d3e8abbc729..810781f12d4 100644 --- a/src/processor/map/map_multiplicity_reducer.cpp +++ b/src/processor/map/map_multiplicity_reducer.cpp @@ -9,8 +9,8 @@ namespace processor { std::unique_ptr PlanMapper::mapMultiplicityReducer( LogicalOperator* logicalOperator) { auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); - return make_unique( - std::move(prevOperator), getOperatorID(), logicalOperator->getExpressionsForPrinting()); + return make_unique(std::move(prevOperator), getOperatorID(), + logicalOperator->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/map_order_by.cpp b/src/processor/map/map_order_by.cpp index 2e963422503..ae68ae5bf89 100644 --- a/src/processor/map/map_order_by.cpp +++ b/src/processor/map/map_order_by.cpp @@ -33,8 +33,8 @@ std::unique_ptr PlanMapper::mapOrderBy(LogicalOperator* logica std::unique_ptr columnSchema; if (!inSchema->getGroup(dataChunkPos)->isFlat() && !mayContainUnFlatKey) { // payload is unFlat and not in the same group as keys - columnSchema = std::make_unique( - true /* isUnFlat */, dataChunkPos, sizeof(overflow_value_t)); + columnSchema = std::make_unique(true /* isUnFlat */, dataChunkPos, + sizeof(overflow_value_t)); } else { columnSchema = std::make_unique(false /* isUnFlat */, dataChunkPos, LogicalTypeUtils::getRowLayoutSize(expression->getDataType())); @@ -63,8 +63,8 @@ std::unique_ptr PlanMapper::mapOrderBy(LogicalOperator* logica auto topK = make_unique(std::make_unique(inSchema), std::move(orderByDataInfo), topKSharedState, logicalOrderBy->getSkipNum(), logicalOrderBy->getLimitNum(), std::move(prevOperator), getOperatorID(), paramsString); - return make_unique( - outPos, topKSharedState, std::move(topK), getOperatorID(), paramsString); + return make_unique(outPos, topKSharedState, std::move(topK), getOperatorID(), + paramsString); } else { auto orderBySharedState = std::make_shared(); auto orderBy = make_unique(std::make_unique(inSchema), @@ -73,8 +73,8 @@ std::unique_ptr PlanMapper::mapOrderBy(LogicalOperator* logica auto dispatcher = std::make_shared(); auto orderByMerge = make_unique(orderBySharedState, std::move(dispatcher), std::move(orderBy), getOperatorID(), paramsString); - return make_unique( - outPos, orderBySharedState, std::move(orderByMerge), getOperatorID(), paramsString); + return make_unique(outPos, orderBySharedState, std::move(orderByMerge), + getOperatorID(), paramsString); } } diff --git a/src/processor/map/map_path_property_probe.cpp b/src/processor/map/map_path_property_probe.cpp index 66ef428332f..303a545efaf 100644 --- a/src/processor/map/map_path_property_probe.cpp +++ b/src/processor/map/map_path_property_probe.cpp @@ -57,15 +57,15 @@ std::unique_ptr PlanMapper::mapPathPropertyProbe( auto nodePayloads = ExpressionUtil::excludeExpressions(nodeBuildSchema->getExpressionsInScope(), nodeKeys); auto nodeBuildInfo = createHashBuildInfo(*nodeBuildSchema, nodeKeys, nodePayloads); - auto nodeHashTable = std::make_unique( - *memoryManager, std::move(nodeKeyTypes), nodeBuildInfo->getTableSchema()->copy()); + auto nodeHashTable = std::make_unique(*clientContext->getMemoryManager(), + std::move(nodeKeyTypes), nodeBuildInfo->getTableSchema()->copy()); nodeBuildSharedState = std::make_shared(std::move(nodeHashTable)); nodeBuild = make_unique( std::make_unique(nodeBuildSchema), nodeBuildSharedState, std::move(nodeBuildInfo), std::move(nodeBuildPrevOperator), getOperatorID(), ""); auto relDataType = rel->getDataType(); auto nodesField = StructType::getField(&relDataType, InternalKeyword::NODES); - auto nodeStructType = VarListType::getChildType(nodesField->getType()); + auto nodeStructType = ListType::getChildType(nodesField->getType()); auto [fieldIndices, columnIndices] = getColIdxToScan(nodePayloads, nodeKeys.size(), *nodeStructType); nodeFieldIndices = std::move(fieldIndices); @@ -84,15 +84,15 @@ std::unique_ptr PlanMapper::mapPathPropertyProbe( auto relPayloads = ExpressionUtil::excludeExpressions(relBuildSchema->getExpressionsInScope(), relKeys); auto relBuildInfo = createHashBuildInfo(*relBuildSchema, relKeys, relPayloads); - auto relHashTable = std::make_unique( - *memoryManager, std::move(relKeyTypes), relBuildInfo->getTableSchema()->copy()); + auto relHashTable = std::make_unique(*clientContext->getMemoryManager(), + std::move(relKeyTypes), relBuildInfo->getTableSchema()->copy()); relBuildSharedState = std::make_shared(std::move(relHashTable)); relBuild = std::make_unique( std::make_unique(relBuildSchema), relBuildSharedState, std::move(relBuildInfo), std::move(relBuildPrvOperator), getOperatorID(), ""); auto relDataType = rel->getDataType(); auto relsField = StructType::getField(&relDataType, InternalKeyword::RELS); - auto relStructType = VarListType::getChildType(relsField->getType()); + auto relStructType = ListType::getChildType(relsField->getType()); auto [fieldIndices, columnIndices] = getColIdxToScan(relPayloads, relKeys.size(), *relStructType); relFieldIndices = std::move(fieldIndices); @@ -115,8 +115,8 @@ std::unique_ptr PlanMapper::mapPathPropertyProbe( if (relBuild != nullptr) { children.push_back(std::move(relBuild)); } - auto pathPropertyProbe = std::make_unique( - std::move(pathProbeInfo), pathProbeSharedState, std::move(children), getOperatorID(), ""); + auto pathPropertyProbe = std::make_unique(std::move(pathProbeInfo), + pathProbeSharedState, std::move(children), getOperatorID(), ""); if (logicalProbe->getSIP() == planner::SidewaysInfoPassing::PROBE_TO_BUILD) { mapSIPJoin(pathPropertyProbe.get()); } diff --git a/src/processor/map/map_port_db.cpp b/src/processor/map/map_port_db.cpp index 83909ec25ac..2dbd6b506f1 100644 --- a/src/processor/map/map_port_db.cpp +++ b/src/processor/map/map_port_db.cpp @@ -1,3 +1,4 @@ +#include "common/file_system/virtual_file_system.h" #include "planner/operator/persistent/logical_export_db.h" #include "planner/operator/persistent/logical_import_db.h" #include "processor/operator/persistent/export_db.h" @@ -20,6 +21,17 @@ std::unique_ptr PlanMapper::mapExportDatabase( auto childPhysicalOperator = mapOperator(childCopyTo.get()); children.push_back(std::move(childPhysicalOperator)); } + // Ideally we should create directory inside operator but ExportDatabase is executed before + // CopyTo which requires the directory to exist. So we create directory in mapper inside. + auto fs = clientContext->getVFSUnsafe(); + auto boundFileInfo = exportDatabase->getBoundFileInfo(); + KU_ASSERT(boundFileInfo->filePaths.size() == 1); + auto filePath = boundFileInfo->filePaths[0]; + if (!fs->fileOrPathExists(filePath)) { + fs->createDir(filePath); + } else { + throw RuntimeException(stringFormat("Directory {} already exists.", filePath)); + } std::unique_ptr resultSetDescriptor; return std::make_unique(exportDatabase->getBoundFileInfo()->copy(), getOperatorID(), exportDatabase->getExpressionsForPrinting(), std::move(children)); @@ -30,8 +42,8 @@ std::unique_ptr PlanMapper::mapImportDatabase( auto importDatabase = ku_dynamic_cast(logicalOperator); std::unique_ptr resultSetDescriptor; - return std::make_unique( - importDatabase->getQuery(), getOperatorID(), importDatabase->getExpressionsForPrinting()); + return std::make_unique(importDatabase->getQuery(), getOperatorID(), + importDatabase->getExpressionsForPrinting()); } } // namespace processor } // namespace kuzu diff --git a/src/processor/map/map_recursive_extend.cpp b/src/processor/map/map_recursive_extend.cpp index 4f14e3b5253..135823c696e 100644 --- a/src/processor/map/map_recursive_extend.cpp +++ b/src/processor/map/map_recursive_extend.cpp @@ -1,7 +1,7 @@ #include "planner/operator/extend/logical_recursive_extend.h" #include "processor/operator/recursive_extend/recursive_join.h" #include "processor/plan_mapper.h" -#include "transaction/transaction.h" +#include "storage/storage_manager.h" using namespace kuzu::binder; using namespace kuzu::planner; @@ -13,7 +13,8 @@ static std::shared_ptr createSharedState( const binder::NodeExpression& nbrNode, const storage::StorageManager& storageManager) { std::vector> semiMasks; for (auto tableID : nbrNode.getTableIDs()) { - auto nodeTable = storageManager.getNodeTable(tableID); + auto nodeTable = common::ku_dynamic_cast( + storageManager.getTable(tableID)); semiMasks.push_back(std::make_unique(nodeTable)); } return std::make_shared(std::move(semiMasks)); @@ -43,13 +44,13 @@ std::unique_ptr PlanMapper::mapRecursiveExtend( auto boundNodeIDPos = DataPos(inSchema->getExpressionPos(*boundNode->getInternalID())); auto nbrNodeIDPos = DataPos(outSchema->getExpressionPos(*nbrNode->getInternalID())); auto lengthPos = DataPos(outSchema->getExpressionPos(*lengthExpression)); - auto sharedState = createSharedState(*nbrNode, storageManager); + auto sharedState = createSharedState(*nbrNode, *clientContext->getStorageManager()); auto pathPos = DataPos(); if (extend->getJoinType() == planner::RecursiveJoinType::TRACK_PATH) { pathPos = DataPos(outSchema->getExpressionPos(*rel)); } std::unordered_map tableIDToName; - for (auto& entry : catalog->getTableEntries(&transaction::DUMMY_READ_TRANSACTION)) { + for (auto& entry : clientContext->getCatalog()->getTableEntries(clientContext->getTx())) { tableIDToName.insert({entry->getTableID(), entry->getName()}); } auto dataInfo = std::make_unique(boundNodeIDPos, nbrNodeIDPos, diff --git a/src/processor/map/map_scan_file.cpp b/src/processor/map/map_scan_file.cpp index b1d70b0489e..27e5d0d2962 100644 --- a/src/processor/map/map_scan_file.cpp +++ b/src/processor/map/map_scan_file.cpp @@ -19,15 +19,19 @@ std::unique_ptr PlanMapper::mapScanFile(LogicalOperator* logic outPosV.emplace_back(getDataPos(*expr, *outSchema)); } auto info = InQueryCallInfo(); - info.function = scanFileInfo->copyFunc; + info.function = scanFileInfo->func; info.bindData = scanFileInfo->bindData->copy(); info.outPosV = outPosV; - info.rowOffsetPos = getDataPos(*scanFileInfo->offset, *outSchema); + if (scanFile->hasOffset()) { + info.rowOffsetPos = getDataPos(*scanFile->getOffset(), *outSchema); + } else { + info.rowOffsetPos = DataPos::getInvalidPos(); + } info.outputType = outPosV.empty() ? TableScanOutputType::EMPTY : TableScanOutputType::SINGLE_DATA_CHUNK; auto sharedState = std::make_shared(); - return std::make_unique( - std::move(info), sharedState, getOperatorID(), scanFile->getExpressionsForPrinting()); + return std::make_unique(std::move(info), sharedState, getOperatorID(), + scanFile->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/map_scan_frontier.cpp b/src/processor/map/map_scan_frontier.cpp index a031ca7e7e7..d38cdcd6d8e 100644 --- a/src/processor/map/map_scan_frontier.cpp +++ b/src/processor/map/map_scan_frontier.cpp @@ -14,8 +14,8 @@ std::unique_ptr PlanMapper::mapScanFrontier( auto nodeIDPos = DataPos(schema->getExpressionPos(*scanFrontier->getNodeID())); auto flagPos = DataPos(schema->getExpressionPos(*scanFrontier->getNodePredicateExecutionFlag())); - return std::make_unique( - ScanFrontierInfo{nodeIDPos, flagPos}, getOperatorID(), std::string()); + return std::make_unique(ScanFrontierInfo{nodeIDPos, flagPos}, getOperatorID(), + std::string()); } } // namespace processor diff --git a/src/processor/map/map_scan_node.cpp b/src/processor/map/map_scan_node.cpp index 982e6c7f4fa..7ca29df23ce 100644 --- a/src/processor/map/map_scan_node.cpp +++ b/src/processor/map/map_scan_node.cpp @@ -2,6 +2,7 @@ #include "planner/operator/scan/logical_scan_internal_id.h" #include "processor/operator/scan_node_id.h" #include "processor/plan_mapper.h" +#include "storage/storage_manager.h" using namespace kuzu::planner; @@ -14,11 +15,12 @@ std::unique_ptr PlanMapper::mapScanInternalID(LogicalOperator* auto dataPos = DataPos(outSchema->getExpressionPos(*scan->getInternalID())); auto sharedState = std::make_shared(); for (auto& tableID : scan->getTableIDs()) { - auto nodeTable = storageManager.getNodeTable(tableID); + auto nodeTable = common::ku_dynamic_cast( + clientContext->getStorageManager()->getTable(tableID)); sharedState->addTableState(nodeTable); } - return std::make_unique( - dataPos, sharedState, getOperatorID(), scan->getExpressionsForPrinting()); + return std::make_unique(dataPos, sharedState, getOperatorID(), + scan->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/map_scan_node_property.cpp b/src/processor/map/map_scan_node_property.cpp index 238e0999125..bc8f3d7f4dc 100644 --- a/src/processor/map/map_scan_node_property.cpp +++ b/src/processor/map/map_scan_node_property.cpp @@ -2,7 +2,7 @@ #include "planner/operator/scan/logical_scan_node_property.h" #include "processor/operator/scan/scan_multi_node_tables.h" #include "processor/plan_mapper.h" -#include "transaction/transaction.h" +#include "storage/storage_manager.h" using namespace kuzu::binder; using namespace kuzu::common; @@ -32,13 +32,15 @@ std::unique_ptr PlanMapper::mapScanNodeProperty( if (!property->hasPropertyID(tableID)) { columns.push_back(UINT32_MAX); } else { - columns.push_back( - catalog->getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, tableID) - ->getColumnID(property->getPropertyID(tableID))); + columns.push_back(clientContext->getCatalog() + ->getTableCatalogEntry(clientContext->getTx(), tableID) + ->getColumnID(property->getPropertyID(tableID))); } } tables.insert({tableID, std::make_unique( - storageManager.getNodeTable(tableID), std::move(columns))}); + ku_dynamic_cast( + clientContext->getStorageManager()->getTable(tableID)), + std::move(columns))}); } return std::make_unique(inputNodeIDVectorPos, std::move(outVectorsPos), std::move(tables), std::move(prevOperator), getOperatorID(), @@ -46,7 +48,7 @@ std::unique_ptr PlanMapper::mapScanNodeProperty( } else { auto tableID = tableIDs[0]; auto tableSchema = - catalog->getTableCatalogEntry(&transaction::DUMMY_READ_TRANSACTION, tableID); + clientContext->getCatalog()->getTableCatalogEntry(clientContext->getTx(), tableID); std::vector columnIDs; for (auto& expression : scanProperty.getProperties()) { auto property = static_pointer_cast(expression); @@ -57,7 +59,9 @@ std::unique_ptr PlanMapper::mapScanNodeProperty( } } auto info = std::make_unique( - storageManager.getNodeTable(tableID), std::move(columnIDs)); + ku_dynamic_cast( + clientContext->getStorageManager()->getTable(tableID)), + std::move(columnIDs)); return std::make_unique(std::move(info), inputNodeIDVectorPos, std::move(outVectorsPos), std::move(prevOperator), getOperatorID(), scanProperty.getExpressionsForPrinting()); diff --git a/src/processor/map/map_semi_masker.cpp b/src/processor/map/map_semi_masker.cpp index 0ed05958774..24deabbdf35 100644 --- a/src/processor/map/map_semi_masker.cpp +++ b/src/processor/map/map_semi_masker.cpp @@ -27,8 +27,8 @@ std::unique_ptr PlanMapper::mapSemiMasker(LogicalOperator* log for (auto i = 0u; i < scanNodeID->getSharedState()->getNumTableStates(); ++i) { auto tableState = scanNodeID->getSharedState()->getTableState(i); auto tableID = tableState->getTable()->getTableID(); - masksPerTable.at(tableID).emplace_back( - tableState->getSemiMask(), 0 /* initial mask idx */); + masksPerTable.at(tableID).emplace_back(tableState->getSemiMask(), + 0 /* initial mask idx */); } } break; case PhysicalOperatorType::RECURSIVE_JOIN: { diff --git a/src/processor/map/map_set.cpp b/src/processor/map/map_set.cpp index 722c0d84c34..ecca5996213 100644 --- a/src/processor/map/map_set.cpp +++ b/src/processor/map/map_set.cpp @@ -3,6 +3,8 @@ #include "planner/operator/persistent/logical_set.h" #include "processor/operator/persistent/set.h" #include "processor/plan_mapper.h" +#include "storage/storage_manager.h" +#include "storage/store/table.h" #include "transaction/transaction.h" using namespace kuzu::binder; @@ -10,12 +12,15 @@ using namespace kuzu::common; using namespace kuzu::planner; using namespace kuzu::evaluator; using namespace kuzu::transaction; +using namespace kuzu::storage; namespace kuzu { namespace processor { std::unique_ptr PlanMapper::getNodeSetExecutor( planner::LogicalSetPropertyInfo* info, const planner::Schema& inSchema) const { + auto storageManager = clientContext->getStorageManager(); + auto catalog = clientContext->getCatalog(); auto node = (NodeExpression*)info->nodeOrRel.get(); auto nodeIDPos = DataPos(inSchema.getExpressionPos(*node->getInternalID())); auto property = (PropertyExpression*)info->setItem.first.get(); @@ -31,24 +36,24 @@ std::unique_ptr PlanMapper::getNodeSetExecutor( continue; } auto propertyID = property->getPropertyID(tableID); - auto table = storageManager.getNodeTable(tableID); + auto table = ku_dynamic_cast(storageManager->getTable(tableID)); auto columnID = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID) ->getColumnID(propertyID); tableIDToSetInfo.insert({tableID, NodeSetInfo{table, columnID}}); } - return std::make_unique( - std::move(tableIDToSetInfo), nodeIDPos, propertyPos, std::move(evaluator)); + return std::make_unique(std::move(tableIDToSetInfo), nodeIDPos, + propertyPos, std::move(evaluator)); } else { auto tableID = node->getSingleTableID(); - auto table = storageManager.getNodeTable(tableID); + auto table = ku_dynamic_cast(storageManager->getTable(tableID)); auto columnID = INVALID_COLUMN_ID; if (property->hasPropertyID(tableID)) { auto propertyID = property->getPropertyID(tableID); - columnID = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID) + columnID = catalog->getTableCatalogEntry(clientContext->getTx(), tableID) ->getColumnID(propertyID); } - return std::make_unique( - NodeSetInfo{table, columnID}, nodeIDPos, propertyPos, std::move(evaluator)); + return std::make_unique(NodeSetInfo{table, columnID}, nodeIDPos, + propertyPos, std::move(evaluator)); } } @@ -64,8 +69,10 @@ std::unique_ptr PlanMapper::mapSetNodeProperty(LogicalOperator getOperatorID(), logicalSetNodeProperty.getExpressionsForPrinting()); } -std::unique_ptr PlanMapper::getRelSetExecutor( - planner::LogicalSetPropertyInfo* info, const planner::Schema& inSchema) const { +std::unique_ptr PlanMapper::getRelSetExecutor(planner::LogicalSetPropertyInfo* info, + const planner::Schema& inSchema) const { + auto storageManager = clientContext->getStorageManager(); + auto catalog = clientContext->getCatalog(); auto rel = (RelExpression*)info->nodeOrRel.get(); auto srcNodePos = DataPos(inSchema.getExpressionPos(*rel->getSrcNode()->getInternalID())); auto dstNodePos = DataPos(inSchema.getExpressionPos(*rel->getDstNode()->getInternalID())); @@ -77,15 +84,14 @@ std::unique_ptr PlanMapper::getRelSetExecutor( } auto evaluator = ExpressionMapper::getEvaluator(info->setItem.second, &inSchema); if (rel->isMultiLabeled()) { - std::unordered_map> - tableIDToTableAndColumnID; + std::unordered_map> tableIDToTableAndColumnID; for (auto tableID : rel->getTableIDs()) { if (!property->hasPropertyID(tableID)) { continue; } - auto table = storageManager.getRelTable(tableID); + auto table = ku_dynamic_cast(storageManager->getTable(tableID)); auto propertyID = property->getPropertyID(tableID); - auto columnID = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID) + auto columnID = catalog->getTableCatalogEntry(clientContext->getTx(), tableID) ->getColumnID(propertyID); tableIDToTableAndColumnID.insert({tableID, std::make_pair(table, columnID)}); } @@ -93,15 +99,15 @@ std::unique_ptr PlanMapper::getRelSetExecutor( srcNodePos, dstNodePos, relIDPos, propertyPos, std::move(evaluator)); } else { auto tableID = rel->getSingleTableID(); - auto table = storageManager.getRelTable(tableID); + auto table = ku_dynamic_cast(storageManager->getTable(tableID)); auto columnID = common::INVALID_COLUMN_ID; if (property->hasPropertyID(tableID)) { auto propertyID = property->getPropertyID(tableID); - columnID = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID) + columnID = catalog->getTableCatalogEntry(clientContext->getTx(), tableID) ->getColumnID(propertyID); } - return std::make_unique( - table, columnID, srcNodePos, dstNodePos, relIDPos, propertyPos, std::move(evaluator)); + return std::make_unique(table, columnID, srcNodePos, dstNodePos, + relIDPos, propertyPos, std::move(evaluator)); } } diff --git a/src/processor/map/map_unwind.cpp b/src/processor/map/map_unwind.cpp index 1a6d5ebaa7b..8ab3a89fc85 100644 --- a/src/processor/map/map_unwind.cpp +++ b/src/processor/map/map_unwind.cpp @@ -14,11 +14,14 @@ std::unique_ptr PlanMapper::mapUnwind(LogicalOperator* logical auto outSchema = unwind->getSchema(); auto inSchema = unwind->getChild(0)->getSchema(); auto prevOperator = mapOperator(logicalOperator->getChild(0).get()); - auto dataPos = DataPos(outSchema->getExpressionPos(*unwind->getAliasExpression())); - auto expressionEvaluator = ExpressionMapper::getEvaluator(unwind->getExpression(), inSchema); - return std::make_unique(*VarListType::getChildType(&unwind->getExpression()->dataType), - dataPos, std::move(expressionEvaluator), std::move(prevOperator), getOperatorID(), - unwind->getExpressionsForPrinting()); + auto dataPos = DataPos(outSchema->getExpressionPos(*unwind->getOutExpr())); + auto expressionEvaluator = ExpressionMapper::getEvaluator(unwind->getInExpr(), inSchema); + DataPos idPos; + if (unwind->hasIDExpr()) { + idPos = getDataPos(*unwind->getIDExpr(), *outSchema); + } + return std::make_unique(dataPos, idPos, std::move(expressionEvaluator), + std::move(prevOperator), getOperatorID(), unwind->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/map/plan_mapper.cpp b/src/processor/map/plan_mapper.cpp index 5167a1636db..4103f73afbd 100644 --- a/src/processor/map/plan_mapper.cpp +++ b/src/processor/map/plan_mapper.cpp @@ -8,16 +8,16 @@ using namespace kuzu::planner; namespace kuzu { namespace processor { -static void setPhysicalPlanIfProfile( - planner::LogicalPlan* logicalPlan, PhysicalPlan* physicalPlan) { +static void setPhysicalPlanIfProfile(planner::LogicalPlan* logicalPlan, + PhysicalPlan* physicalPlan) { if (logicalPlan->isProfile()) { ku_dynamic_cast(physicalPlan->lastOperator->getChild(0)) ->setPhysicalPlan(physicalPlan); } } -std::unique_ptr PlanMapper::mapLogicalPlanToPhysical( - LogicalPlan* logicalPlan, const binder::expression_vector& expressionsToCollect) { +std::unique_ptr PlanMapper::mapLogicalPlanToPhysical(LogicalPlan* logicalPlan, + const binder::expression_vector& expressionsToCollect) { auto lastOperator = mapOperator(logicalPlan->getLastOperator().get()); lastOperator = createResultCollector(AccumulateType::REGULAR, expressionsToCollect, logicalPlan->getSchema(), std::move(lastOperator)); @@ -108,6 +108,9 @@ std::unique_ptr PlanMapper::mapOperator(LogicalOperator* logic case LogicalOperatorType::ACCUMULATE: { physicalOperator = mapAccumulate(logicalOperator); } break; + case LogicalOperatorType::MARK_ACCUMULATE: { + physicalOperator = mapMarkAccumulate(logicalOperator); + } break; case LogicalOperatorType::DUMMY_SCAN: { physicalOperator = mapDummyScan(logicalOperator); } break; @@ -174,6 +177,12 @@ std::unique_ptr PlanMapper::mapOperator(LogicalOperator* logic case LogicalOperatorType::IMPORT_DATABASE: { physicalOperator = mapImportDatabase(logicalOperator); } break; + case LogicalOperatorType::ATTACH_DATABASE: { + physicalOperator = mapAttachDatabase(logicalOperator); + } break; + case LogicalOperatorType::DETACH_DATABASE: { + physicalOperator = mapDetachDatabase(logicalOperator); + } break; default: KU_UNREACHABLE; } @@ -181,8 +190,8 @@ std::unique_ptr PlanMapper::mapOperator(LogicalOperator* logic return physicalOperator; } -std::vector PlanMapper::getExpressionsDataPos( - const binder::expression_vector& expressions, const planner::Schema& schema) { +std::vector PlanMapper::getExpressionsDataPos(const binder::expression_vector& expressions, + const planner::Schema& schema) { std::vector result; for (auto& expression : expressions) { result.emplace_back(schema.getExpressionPos(*expression)); @@ -190,12 +199,13 @@ std::vector PlanMapper::getExpressionsDataPos( return result; } -std::shared_ptr PlanMapper::getSingleStringColumnFTable() { +std::shared_ptr PlanMapper::getSingleStringColumnFTable() const { auto ftTableSchema = std::make_unique(); ftTableSchema->appendColumn( std::make_unique(false /* flat */, 0 /* dataChunkPos */, LogicalTypeUtils::getRowLayoutSize(LogicalType{LogicalTypeID::STRING}))); - return std::make_shared(memoryManager, std::move(ftTableSchema)); + return std::make_shared(clientContext->getMemoryManager(), + std::move(ftTableSchema)); } } // namespace processor diff --git a/src/processor/operator/CMakeLists.txt b/src/processor/operator/CMakeLists.txt index 992e9375184..4fd828a49d6 100644 --- a/src/processor/operator/CMakeLists.txt +++ b/src/processor/operator/CMakeLists.txt @@ -12,6 +12,8 @@ add_subdirectory(macro) add_library(kuzu_processor_operator OBJECT + attach_database.cpp + detach_database.cpp comment_on.cpp cross_product.cpp empty_result.cpp diff --git a/src/processor/operator/aggregate/aggregate_hash_table.cpp b/src/processor/operator/aggregate/aggregate_hash_table.cpp index 32b9eb39c16..a7a8fa4643b 100644 --- a/src/processor/operator/aggregate/aggregate_hash_table.cpp +++ b/src/processor/operator/aggregate/aggregate_hash_table.cpp @@ -1,8 +1,6 @@ #include "processor/operator/aggregate/aggregate_hash_table.h" -#include "common/null_buffer.h" #include "common/utils.h" -#include "function/comparison/comparison_functions.h" #include "function/hash/vector_hash_functions.h" using namespace kuzu::common; @@ -15,13 +13,13 @@ namespace processor { AggregateHashTable::AggregateHashTable(MemoryManager& memoryManager, std::vector keyDataTypes, std::vector dependentKeyDataTypes, const std::vector>& aggregateFunctions, - uint64_t numEntriesToAllocate) - : BaseHashTable{memoryManager}, keyDataTypes{std::move(keyDataTypes)}, + uint64_t numEntriesToAllocate, std::unique_ptr tableSchema) + : BaseHashTable{memoryManager, std::move(keyDataTypes)}, dependentKeyDataTypes{std::move(dependentKeyDataTypes)} { - initializeFT(aggregateFunctions); + initializeFT(aggregateFunctions, std::move(tableSchema)); initializeHashTable(numEntriesToAllocate); - distinctHashTables = AggregateHashTableUtils::createDistinctHashTables( - memoryManager, this->keyDataTypes, this->aggregateFunctions); + distinctHashTables = AggregateHashTableUtils::createDistinctHashTables(memoryManager, + this->keyTypes, this->aggregateFunctions); initializeTmpVectors(); } @@ -53,8 +51,8 @@ bool AggregateHashTable::isAggregateValueDistinctForGroupByKeys( auto tmpHashCombineResultVector = std::make_unique(LogicalTypeID::INT64, &memoryManager); VectorHashFunction::computeHash(aggregateVector, tmpHashResultVector.get()); - VectorHashFunction::combineHash( - hashVector.get(), tmpHashResultVector.get(), tmpHashCombineResultVector.get()); + VectorHashFunction::combineHash(hashVector.get(), tmpHashResultVector.get(), + tmpHashCombineResultVector.get()); hashVector = std::move(tmpHashResultVector); } hash_t hash = hashVector->getValue(hashVector->state->selVector->selectedPositions[0]); @@ -68,13 +66,13 @@ bool AggregateHashTable::isAggregateValueDistinctForGroupByKeys( void AggregateHashTable::merge(AggregateHashTable& other) { std::shared_ptr vectorsToScanState = std::make_shared(); - std::vector vectorsToScan(keyDataTypes.size() + dependentKeyDataTypes.size()); - std::vector groupByHashVectors(keyDataTypes.size()); + std::vector vectorsToScan(keyTypes.size() + dependentKeyDataTypes.size()); + std::vector groupByHashVectors(keyTypes.size()); std::vector groupByNonHashVectors(dependentKeyDataTypes.size()); - std::vector> hashKeyVectors(keyDataTypes.size()); + std::vector> hashKeyVectors(keyTypes.size()); std::vector> nonHashKeyVectors(groupByNonHashVectors.size()); - for (auto i = 0u; i < keyDataTypes.size(); i++) { - auto hashKeyVec = std::make_unique(keyDataTypes[i], &memoryManager); + for (auto i = 0u; i < keyTypes.size(); i++) { + auto hashKeyVec = std::make_unique(keyTypes[i], &memoryManager); hashKeyVec->state = vectorsToScanState; vectorsToScan[i] = hashKeyVec.get(); groupByHashVectors[i] = hashKeyVec.get(); @@ -84,7 +82,7 @@ void AggregateHashTable::merge(AggregateHashTable& other) { auto nonHashKeyVec = std::make_unique(dependentKeyDataTypes[i], &memoryManager); nonHashKeyVec->state = vectorsToScanState; - vectorsToScan[i + keyDataTypes.size()] = nonHashKeyVec.get(); + vectorsToScan[i + keyTypes.size()] = nonHashKeyVec.get(); groupByNonHashVectors[i] = nonHashKeyVec.get(); nonHashKeyVectors[i] = std::move(nonHashKeyVec); } @@ -98,16 +96,16 @@ void AggregateHashTable::merge(AggregateHashTable& other) { colIdxesToScan.push_back(factorizedTable->getTableSchema()->getNumColumns() - 1); uint64_t startTupleIdx = 0; while (startTupleIdx < other.factorizedTable->getNumTuples()) { - auto numTuplesToScan = std::min( - other.factorizedTable->getNumTuples() - startTupleIdx, DEFAULT_VECTOR_CAPACITY); + auto numTuplesToScan = std::min(other.factorizedTable->getNumTuples() - startTupleIdx, + DEFAULT_VECTOR_CAPACITY); other.factorizedTable->scan(vectorsToScan, startTupleIdx, numTuplesToScan, colIdxesToScan); findHashSlots(std::vector(), groupByHashVectors, groupByNonHashVectors, vectorsToScanState.get()); auto aggregateStateOffset = aggStateColOffsetInFT; for (auto& aggregateFunction : aggregateFunctions) { for (auto i = 0u; i < numTuplesToScan; i++) { - aggregateFunction->combineState( - hashSlotsToUpdateAggState[i]->entry + aggregateStateOffset, + aggregateFunction->combineState(hashSlotsToUpdateAggState[i]->entry + + aggregateStateOffset, other.factorizedTable->getTuple(startTupleIdx + i) + aggregateStateOffset, &memoryManager); } @@ -129,25 +127,14 @@ void AggregateHashTable::finalizeAggregateStates() { } void AggregateHashTable::initializeFT( - const std::vector>& aggFuncs) { - auto isUnflat = false; - auto dataChunkPos = 0u; - std::unique_ptr tableSchema = std::make_unique(); - aggStateColIdxInFT = keyDataTypes.size() + dependentKeyDataTypes.size(); - compareFuncs.resize(keyDataTypes.size()); - auto colIdx = 0u; - for (auto& dataType : keyDataTypes) { - auto size = LogicalTypeUtils::getRowLayoutSize(dataType); - tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, size)); - getCompareEntryWithKeysFunc(dataType, compareFuncs[colIdx]); - numBytesForKeys += size; - colIdx++; + const std::vector>& aggFuncs, + std::unique_ptr tableSchema) { + aggStateColIdxInFT = keyTypes.size() + dependentKeyDataTypes.size(); + for (auto& dataType : keyTypes) { + numBytesForKeys += LogicalTypeUtils::getRowLayoutSize(dataType); } for (auto& dataType : dependentKeyDataTypes) { - auto size = LogicalTypeUtils::getRowLayoutSize(dataType); - tableSchema->appendColumn(std::make_unique(isUnflat, dataChunkPos, size)); - numBytesForDependentKeys += size; - colIdx++; + numBytesForDependentKeys += LogicalTypeUtils::getRowLayoutSize(dataType); } aggStateColOffsetInFT = numBytesForKeys + numBytesForDependentKeys; @@ -155,16 +142,12 @@ void AggregateHashTable::initializeFT( updateAggFuncs.reserve(aggFuncs.size()); for (auto i = 0u; i < aggFuncs.size(); i++) { auto& aggFunc = aggFuncs[i]; - tableSchema->appendColumn(std::make_unique( - isUnflat, dataChunkPos, aggFunc->getAggregateStateSize())); aggregateFunctions.push_back(aggFunc->clone()); updateAggFuncs.push_back(aggFunc->isFunctionDistinct() ? &AggregateHashTable::updateDistinctAggState : &AggregateHashTable::updateAggState); } - tableSchema->appendColumn( - std::make_unique(isUnflat, dataChunkPos, sizeof(hash_t))); - hashColIdxInFT = aggStateColIdxInFT + aggFuncs.size(); + hashColIdxInFT = tableSchema->getNumColumns() - 1; hashColOffsetInFT = tableSchema->getColOffset(hashColIdxInFT); factorizedTable = std::make_unique(&memoryManager, std::move(tableSchema)); } @@ -182,10 +165,6 @@ void AggregateHashTable::initializeHashTable(uint64_t numEntriesToAllocate) { } void AggregateHashTable::initializeTmpVectors() { - hashState = std::make_shared(); - hashState->setToFlat(); - hashVector = std::make_unique(LogicalTypeID::INT64, &memoryManager); - hashVector->state = hashState; hashSlotsToUpdateAggState = std::make_unique(DEFAULT_VECTOR_CAPACITY); tmpValueIdxes = std::make_unique(DEFAULT_VECTOR_CAPACITY); entryIdxesToInitialize = std::make_unique(DEFAULT_VECTOR_CAPACITY); @@ -223,8 +202,142 @@ void AggregateHashTable::resize(uint64_t newSize) { } } -void AggregateHashTable::initializeFTEntryWithFlatVec( - ValueVector* flatVector, uint64_t numEntriesToInitialize, uint32_t colIdx) { +uint64_t AggregateHashTable::matchFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, uint64_t numMayMatches, + uint64_t numNoMatches) { + auto colIdx = 0u; + for (auto& flatKeyVector : flatKeyVectors) { + numMayMatches = + matchFlatVecWithFTColumn(flatKeyVector, numMayMatches, numNoMatches, colIdx++); + } + for (auto& unFlatKeyVector : unFlatKeyVectors) { + numMayMatches = + matchUnFlatVecWithFTColumn(unFlatKeyVector, numMayMatches, numNoMatches, colIdx++); + } + return numNoMatches; +} + +void AggregateHashTable::initializeFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, + const std::vector& dependentKeyVectors, uint64_t numFTEntriesToInitialize) { + auto colIdx = 0u; + for (auto flatKeyVector : flatKeyVectors) { + initializeFTEntryWithFlatVec(flatKeyVector, numFTEntriesToInitialize, colIdx++); + } + for (auto unFlatKeyVector : unFlatKeyVectors) { + initializeFTEntryWithUnFlatVec(unFlatKeyVector, numFTEntriesToInitialize, colIdx++); + } + for (auto dependentKeyVector : dependentKeyVectors) { + if (dependentKeyVector->state->isFlat()) { + initializeFTEntryWithFlatVec(dependentKeyVector, numFTEntriesToInitialize, colIdx++); + } else { + initializeFTEntryWithUnFlatVec(dependentKeyVector, numFTEntriesToInitialize, colIdx++); + } + } + for (auto i = 0u; i < numFTEntriesToInitialize; i++) { + auto entryIdx = entryIdxesToInitialize[i]; + auto entry = hashSlotsToUpdateAggState[entryIdx]->entry; + fillEntryWithInitialNullAggregateState(entry); + // Fill the hashValue in the ftEntry. + factorizedTable->updateFlatCellNoNull(entry, hashColIdxInFT, + hashVector->getData() + hashVector->getNumBytesPerValue() * entryIdx); + } +} + +uint64_t AggregateHashTable::matchUnFlatVecWithFTColumn(ValueVector* vector, uint64_t numMayMatches, + uint64_t& numNoMatches, uint32_t colIdx) { + KU_ASSERT(!vector->state->isFlat()); + auto colOffset = factorizedTable->getTableSchema()->getColOffset(colIdx); + uint64_t mayMatchIdx = 0; + if (vector->hasNoNullsGuarantee()) { + if (factorizedTable->hasNoNullGuarantee(colIdx)) { + for (auto i = 0u; i < numMayMatches; i++) { + auto idx = mayMatchIdxes[i]; + if (compareEntryFuncs[colIdx](vector, idx, + hashSlotsToUpdateAggState[idx]->entry + colOffset)) { + mayMatchIdxes[mayMatchIdx++] = idx; + } else { + noMatchIdxes[numNoMatches++] = idx; + } + } + } else { + for (auto i = 0u; i < numMayMatches; i++) { + auto idx = mayMatchIdxes[i]; + auto isEntryKeyNull = factorizedTable->isNonOverflowColNull( + hashSlotsToUpdateAggState[idx]->entry + + factorizedTable->getTableSchema()->getNullMapOffset(), + colIdx); + if (isEntryKeyNull) { + noMatchIdxes[numNoMatches++] = idx; + continue; + } + if (compareEntryFuncs[colIdx](vector, idx, + hashSlotsToUpdateAggState[idx]->entry + colOffset)) { + mayMatchIdxes[mayMatchIdx++] = idx; + } else { + noMatchIdxes[numNoMatches++] = idx; + } + } + } + } else { + for (auto i = 0u; i < numMayMatches; i++) { + auto idx = mayMatchIdxes[i]; + auto isKeyVectorNull = vector->isNull(idx); + auto isEntryKeyNull = factorizedTable->isNonOverflowColNull( + hashSlotsToUpdateAggState[idx]->entry + + factorizedTable->getTableSchema()->getNullMapOffset(), + colIdx); + if (isKeyVectorNull && isEntryKeyNull) { + mayMatchIdxes[mayMatchIdx++] = idx; + continue; + } else if (isKeyVectorNull != isEntryKeyNull) { + noMatchIdxes[numNoMatches++] = idx; + continue; + } + + if (compareEntryFuncs[colIdx](vector, idx, + hashSlotsToUpdateAggState[idx]->entry + colOffset)) { + mayMatchIdxes[mayMatchIdx++] = idx; + } else { + noMatchIdxes[numNoMatches++] = idx; + } + } + } + return mayMatchIdx; +} + +uint64_t AggregateHashTable::matchFlatVecWithFTColumn(ValueVector* vector, uint64_t numMayMatches, + uint64_t& numNoMatches, uint32_t colIdx) { + KU_ASSERT(vector->state->isFlat()); + auto colOffset = factorizedTable->getTableSchema()->getColOffset(colIdx); + uint64_t mayMatchIdx = 0; + auto pos = vector->state->selVector->selectedPositions[0]; + auto isVectorNull = vector->isNull(pos); + for (auto i = 0u; i < numMayMatches; i++) { + auto idx = mayMatchIdxes[i]; + auto isEntryKeyNull = factorizedTable->isNonOverflowColNull( + hashSlotsToUpdateAggState[idx]->entry + + factorizedTable->getTableSchema()->getNullMapOffset(), + colIdx); + if (isEntryKeyNull && isVectorNull) { + mayMatchIdxes[mayMatchIdx++] = idx; + continue; + } else if (isEntryKeyNull != isVectorNull) { + noMatchIdxes[numNoMatches++] = idx; + continue; + } + if (compareEntryFuncs[colIdx](vector, pos, + hashSlotsToUpdateAggState[idx]->entry + colOffset)) { + mayMatchIdxes[mayMatchIdx++] = idx; + } else { + noMatchIdxes[numNoMatches++] = idx; + } + } + return mayMatchIdx; +} + +void AggregateHashTable::initializeFTEntryWithFlatVec(ValueVector* flatVector, + uint64_t numEntriesToInitialize, uint32_t colIdx) { KU_ASSERT(flatVector->state->isFlat()); auto colOffset = factorizedTable->getTableSchema()->getColOffset(colIdx); auto pos = flatVector->state->selVector->selectedPositions[0]; @@ -239,14 +352,14 @@ void AggregateHashTable::initializeFTEntryWithFlatVec( for (auto i = 0u; i < numEntriesToInitialize; i++) { auto idx = entryIdxesToInitialize[i]; auto entry = hashSlotsToUpdateAggState[idx]->entry; - flatVector->copyToRowData( - pos, entry + colOffset, factorizedTable->getInMemOverflowBuffer()); + flatVector->copyToRowData(pos, entry + colOffset, + factorizedTable->getInMemOverflowBuffer()); } } } -void AggregateHashTable::initializeFTEntryWithUnFlatVec( - ValueVector* unFlatVector, uint64_t numEntriesToInitialize, uint32_t colIdx) { +void AggregateHashTable::initializeFTEntryWithUnFlatVec(ValueVector* unFlatVector, + uint64_t numEntriesToInitialize, uint32_t colIdx) { KU_ASSERT(!unFlatVector->state->isFlat()); auto colOffset = factorizedTable->getTableSchema()->getColOffset(colIdx); if (unFlatVector->hasNoNullsGuarantee()) { @@ -259,37 +372,10 @@ void AggregateHashTable::initializeFTEntryWithUnFlatVec( } else { for (auto i = 0u; i < numEntriesToInitialize; i++) { auto entryIdx = entryIdxesToInitialize[i]; - factorizedTable->updateFlatCell( - hashSlotsToUpdateAggState[entryIdx]->entry, colIdx, unFlatVector, entryIdx); - } - } -} - -void AggregateHashTable::initializeFTEntries(const std::vector& flatKeyVectors, - const std::vector& unFlatKeyVectors, - const std::vector& dependentKeyVectors, uint64_t numFTEntriesToInitialize) { - auto colIdx = 0u; - for (auto flatKeyVector : flatKeyVectors) { - initializeFTEntryWithFlatVec(flatKeyVector, numFTEntriesToInitialize, colIdx++); - } - for (auto unFlatKeyVector : unFlatKeyVectors) { - initializeFTEntryWithUnFlatVec(unFlatKeyVector, numFTEntriesToInitialize, colIdx++); - } - for (auto dependentKeyVector : dependentKeyVectors) { - if (dependentKeyVector->state->isFlat()) { - initializeFTEntryWithFlatVec(dependentKeyVector, numFTEntriesToInitialize, colIdx++); - } else { - initializeFTEntryWithUnFlatVec(dependentKeyVector, numFTEntriesToInitialize, colIdx++); + factorizedTable->updateFlatCell(hashSlotsToUpdateAggState[entryIdx]->entry, colIdx, + unFlatVector, entryIdx); } } - for (auto i = 0u; i < numFTEntriesToInitialize; i++) { - auto entryIdx = entryIdxesToInitialize[i]; - auto entry = hashSlotsToUpdateAggState[entryIdx]->entry; - fillEntryWithInitialNullAggregateState(entry); - // Fill the hashValue in the ftEntry. - factorizedTable->updateFlatCellNoNull(entry, hashColIdxInFT, - hashVector->getData() + hashVector->getNumBytesPerValue() * entryIdx); - } } uint8_t* AggregateHashTable::createEntryInDistinctHT( @@ -359,8 +445,8 @@ void AggregateHashTable::findHashSlots(const std::vector& flatKeyV noMatchIdxes[numNoMatches++] = idx; } } - initializeFTEntries( - flatKeyVectors, unFlatKeyVectors, dependentKeyVectors, numFTEntriesToUpdate); + initializeFTEntries(flatKeyVectors, unFlatKeyVectors, dependentKeyVectors, + numFTEntriesToUpdate); numNoMatches = matchFTEntries(flatKeyVectors, unFlatKeyVectors, numMayMatches, numNoMatches); increaseHashSlotIdxes(numNoMatches); @@ -369,33 +455,6 @@ void AggregateHashTable::findHashSlots(const std::vector& flatKeyV } } -void AggregateHashTable::computeAndCombineVecHash( - const std::vector& unFlatKeyVectors, uint32_t startVecIdx) { - for (; startVecIdx < unFlatKeyVectors.size(); startVecIdx++) { - auto keyVector = unFlatKeyVectors[startVecIdx]; - auto tmpHashResultVector = - std::make_unique(LogicalTypeID::INT64, &memoryManager); - auto tmpHashCombineResultVector = - std::make_unique(LogicalTypeID::INT64, &memoryManager); - VectorHashFunction::computeHash(keyVector, tmpHashResultVector.get()); - VectorHashFunction::combineHash( - hashVector.get(), tmpHashResultVector.get(), tmpHashCombineResultVector.get()); - hashVector = std::move(tmpHashCombineResultVector); - } -} - -void AggregateHashTable::computeVectorHashes(const std::vector& flatKeyVectors, - const std::vector& unFlatKeyVectors) { - if (!flatKeyVectors.empty()) { - VectorHashFunction::computeHash(flatKeyVectors[0], hashVector.get()); - computeAndCombineVecHash(flatKeyVectors, 1 /* startVecIdx */); - computeAndCombineVecHash(unFlatKeyVectors, 0 /* startVecIdx */); - } else { - VectorHashFunction::computeHash(unFlatKeyVectors[0], hashVector.get()); - computeAndCombineVecHash(unFlatKeyVectors, 1 /* startVecIdx */); - } -} - void AggregateHashTable::updateDistinctAggState(const std::vector& flatKeyVectors, const std::vector& /*unFlatKeyVectors*/, std::unique_ptr& aggregateFunction, ValueVector* aggregateVector, @@ -425,17 +484,17 @@ void AggregateHashTable::updateAggState(const std::vector& flatKey std::unique_ptr& aggregateFunction, ValueVector* aggVector, uint64_t multiplicity, uint32_t /*colIdx*/, uint32_t aggStateOffset) { if (!aggVector) { - updateNullAggVectorState( - flatKeyVectors, unFlatKeyVectors, aggregateFunction, multiplicity, aggStateOffset); + updateNullAggVectorState(flatKeyVectors, unFlatKeyVectors, aggregateFunction, multiplicity, + aggStateOffset); } else if (aggVector->state->isFlat() && unFlatKeyVectors.empty()) { - updateBothFlatAggVectorState( - flatKeyVectors, aggregateFunction, aggVector, multiplicity, aggStateOffset); + updateBothFlatAggVectorState(flatKeyVectors, aggregateFunction, aggVector, multiplicity, + aggStateOffset); } else if (aggVector->state->isFlat()) { updateFlatUnFlatKeyFlatAggVectorState(flatKeyVectors, unFlatKeyVectors, aggregateFunction, aggVector, multiplicity, aggStateOffset); } else if (unFlatKeyVectors.empty()) { - updateFlatKeyUnFlatAggVectorState( - flatKeyVectors, aggregateFunction, aggVector, multiplicity, aggStateOffset); + updateFlatKeyUnFlatAggVectorState(flatKeyVectors, aggregateFunction, aggVector, + multiplicity, aggStateOffset); } else if (!unFlatKeyVectors.empty() && (aggVector->state == unFlatKeyVectors[0]->state)) { updateBothUnFlatSameDCAggVectorState(flatKeyVectors, unFlatKeyVectors, aggregateFunction, aggVector, multiplicity, aggStateOffset); @@ -461,8 +520,8 @@ void AggregateHashTable::updateAggStates(const std::vector& flatKe } } -bool AggregateHashTable::matchFlatGroupByKeys( - const std::vector& keyVectors, uint8_t* entry) { +bool AggregateHashTable::matchFlatGroupByKeys(const std::vector& keyVectors, + uint8_t* entry) { for (auto i = 0u; i < keyVectors.size(); i++) { auto keyVector = keyVectors[i]; KU_ASSERT(keyVector->state->isFlat()); @@ -477,120 +536,14 @@ bool AggregateHashTable::matchFlatGroupByKeys( } else if (isKeyVectorNull != isEntryKeyNull) { return false; } - if (!compareFuncs[i]( - keyVector, pos, entry + factorizedTable->getTableSchema()->getColOffset(i))) { + if (!compareEntryFuncs[i](keyVector, pos, + entry + factorizedTable->getTableSchema()->getColOffset(i))) { return false; } } return true; } -uint64_t AggregateHashTable::matchUnFlatVecWithFTColumn( - ValueVector* vector, uint64_t numMayMatches, uint64_t& numNoMatches, uint32_t colIdx) { - KU_ASSERT(!vector->state->isFlat()); - auto colOffset = factorizedTable->getTableSchema()->getColOffset(colIdx); - uint64_t mayMatchIdx = 0; - if (vector->hasNoNullsGuarantee()) { - if (factorizedTable->hasNoNullGuarantee(colIdx)) { - for (auto i = 0u; i < numMayMatches; i++) { - auto idx = mayMatchIdxes[i]; - if (compareFuncs[colIdx]( - vector, idx, hashSlotsToUpdateAggState[idx]->entry + colOffset)) { - mayMatchIdxes[mayMatchIdx++] = idx; - } else { - noMatchIdxes[numNoMatches++] = idx; - } - } - } else { - for (auto i = 0u; i < numMayMatches; i++) { - auto idx = mayMatchIdxes[i]; - auto isEntryKeyNull = factorizedTable->isNonOverflowColNull( - hashSlotsToUpdateAggState[idx]->entry + - factorizedTable->getTableSchema()->getNullMapOffset(), - colIdx); - if (isEntryKeyNull) { - noMatchIdxes[numNoMatches++] = idx; - continue; - } - if (compareFuncs[colIdx]( - vector, idx, hashSlotsToUpdateAggState[idx]->entry + colOffset)) { - mayMatchIdxes[mayMatchIdx++] = idx; - } else { - noMatchIdxes[numNoMatches++] = idx; - } - } - } - } else { - for (auto i = 0u; i < numMayMatches; i++) { - auto idx = mayMatchIdxes[i]; - auto isKeyVectorNull = vector->isNull(idx); - auto isEntryKeyNull = factorizedTable->isNonOverflowColNull( - hashSlotsToUpdateAggState[idx]->entry + - factorizedTable->getTableSchema()->getNullMapOffset(), - colIdx); - if (isKeyVectorNull && isEntryKeyNull) { - mayMatchIdxes[mayMatchIdx++] = idx; - continue; - } else if (isKeyVectorNull != isEntryKeyNull) { - noMatchIdxes[numNoMatches++] = idx; - continue; - } - - if (compareFuncs[colIdx]( - vector, idx, hashSlotsToUpdateAggState[idx]->entry + colOffset)) { - mayMatchIdxes[mayMatchIdx++] = idx; - } else { - noMatchIdxes[numNoMatches++] = idx; - } - } - } - return mayMatchIdx; -} - -uint64_t AggregateHashTable::matchFlatVecWithFTColumn( - ValueVector* vector, uint64_t numMayMatches, uint64_t& numNoMatches, uint32_t colIdx) { - KU_ASSERT(vector->state->isFlat()); - auto colOffset = factorizedTable->getTableSchema()->getColOffset(colIdx); - uint64_t mayMatchIdx = 0; - auto pos = vector->state->selVector->selectedPositions[0]; - auto isVectorNull = vector->isNull(pos); - for (auto i = 0u; i < numMayMatches; i++) { - auto idx = mayMatchIdxes[i]; - auto isEntryKeyNull = factorizedTable->isNonOverflowColNull( - hashSlotsToUpdateAggState[idx]->entry + - factorizedTable->getTableSchema()->getNullMapOffset(), - colIdx); - if (isEntryKeyNull && isVectorNull) { - mayMatchIdxes[mayMatchIdx++] = idx; - continue; - } else if (isEntryKeyNull != isVectorNull) { - noMatchIdxes[numNoMatches++] = idx; - continue; - } - if (compareFuncs[colIdx](vector, pos, hashSlotsToUpdateAggState[idx]->entry + colOffset)) { - mayMatchIdxes[mayMatchIdx++] = idx; - } else { - noMatchIdxes[numNoMatches++] = idx; - } - } - return mayMatchIdx; -} - -uint64_t AggregateHashTable::matchFTEntries(const std::vector& flatKeyVectors, - const std::vector& unFlatKeyVectors, uint64_t numMayMatches, - uint64_t numNoMatches) { - auto colIdx = 0u; - for (auto& flatKeyVector : flatKeyVectors) { - numMayMatches = - matchFlatVecWithFTColumn(flatKeyVector, numMayMatches, numNoMatches, colIdx++); - } - for (auto& unFlatKeyVector : unFlatKeyVectors) { - numMayMatches = - matchUnFlatVecWithFTColumn(unFlatKeyVector, numMayMatches, numNoMatches, colIdx++); - } - return numNoMatches; -} - void AggregateHashTable::fillEntryWithInitialNullAggregateState(uint8_t* entry) { for (auto i = 0u; i < aggregateFunctions.size(); i++) { factorizedTable->updateFlatCellNoNull(entry, aggStateColIdxInFT + i, @@ -630,166 +583,6 @@ void AggregateHashTable::resizeHashTableIfNecessary(uint32_t maxNumDistinctHashK } } -template -static bool compareEntry(common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { - uint8_t result; - auto key = vector->getData() + vectorPos * vector->getNumBytesPerValue(); - function::Equals::operation( - *(T*)key, *(T*)entry, result, nullptr /* leftVector */, nullptr /* rightVector */); - return result != 0; -} - -template<> -bool compareEntry( - common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { - auto dataVector = ListVector::getDataVector(vector); - auto listToCompare = vector->getValue(vectorPos); - auto listEntry = reinterpret_cast(entry); - auto entryNullBytes = reinterpret_cast(listEntry->overflowPtr); - auto entryValues = entryNullBytes + NullBuffer::getNumBytesForNullValues(listEntry->size); - auto rowLayoutSize = LogicalTypeUtils::getRowLayoutSize(dataVector->dataType); - compare_function_t compareFunc; - AggregateHashTable::getCompareEntryWithKeysFunc(dataVector->dataType, compareFunc); - if (listToCompare.size != listEntry->size) { - return false; - } - for (auto i = 0u; i < listEntry->size; i++) { - if (!compareFunc(dataVector, listToCompare.offset + i, entryValues)) { - return false; - } - entryValues += rowLayoutSize; - } - return true; -} - -template<> -bool compareEntry( - common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { - auto numFields = StructType::getNumFields(&vector->dataType); - auto entryToCompare = entry + NullBuffer::getNumBytesForNullValues(numFields); - for (auto i = 0u; i < numFields; i++) { - auto isNullInEntry = NullBuffer::isNull(entry, i); - auto fieldVector = StructVector::getFieldVector(vector, i); - compare_function_t compareFunc; - AggregateHashTable::getCompareEntryWithKeysFunc(fieldVector->dataType, compareFunc); - // Firstly check null on left and right side. - if (isNullInEntry != fieldVector->isNull(vectorPos)) { - return false; - } - // If both not null, compare the value. - if (!isNullInEntry && !compareFunc(fieldVector.get(), vectorPos, entryToCompare)) { - return false; - } - entryToCompare += LogicalTypeUtils::getRowLayoutSize(fieldVector->dataType); - } - return true; -} - -static bool compareNodeEntry( - common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { - KU_ASSERT(0 == common::StructType::getFieldIdx(&vector->dataType, common::InternalKeyword::ID)); - auto idVector = common::StructVector::getFieldVector(vector, 0).get(); - return compareEntry(idVector, vectorPos, - entry + common::NullBuffer::getNumBytesForNullValues( - common::StructType::getNumFields(&vector->dataType))); -} - -static bool compareRelEntry(common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { - KU_ASSERT(3 == common::StructType::getFieldIdx(&vector->dataType, common::InternalKeyword::ID)); - auto idVector = common::StructVector::getFieldVector(vector, 3).get(); - return compareEntry(idVector, vectorPos, - entry + sizeof(common::internalID_t) * 2 + sizeof(common::ku_string_t) + - common::NullBuffer::getNumBytesForNullValues( - common::StructType::getNumFields(&vector->dataType))); -} - -void AggregateHashTable::getCompareEntryWithKeysFunc( - const LogicalType& logicalType, compare_function_t& func) { - switch (logicalType.getPhysicalType()) { - case PhysicalTypeID::INTERNAL_ID: { - func = compareEntry; - return; - } - case PhysicalTypeID::BOOL: { - func = compareEntry; - return; - } - case PhysicalTypeID::INT64: { - func = compareEntry; - return; - } - case PhysicalTypeID::INT32: { - func = compareEntry; - return; - } - case PhysicalTypeID::INT16: { - func = compareEntry; - return; - } - case PhysicalTypeID::INT8: { - func = compareEntry; - return; - } - case PhysicalTypeID::UINT64: { - func = compareEntry; - return; - } - case PhysicalTypeID::UINT32: { - func = compareEntry; - return; - } - case PhysicalTypeID::UINT16: { - func = compareEntry; - return; - } - case PhysicalTypeID::UINT8: { - func = compareEntry; - return; - } - case PhysicalTypeID::INT128: { - func = compareEntry; - return; - } - case PhysicalTypeID::DOUBLE: { - func = compareEntry; - return; - } - case PhysicalTypeID::FLOAT: { - func = compareEntry; - return; - } - case PhysicalTypeID::STRING: { - func = compareEntry; - return; - } - case PhysicalTypeID::INTERVAL: { - func = compareEntry; - return; - } - case PhysicalTypeID::STRUCT: { - if (logicalType.getLogicalTypeID() == LogicalTypeID::NODE) { - func = compareNodeEntry; - return; - } else if (logicalType.getLogicalTypeID() == LogicalTypeID::REL) { - func = compareRelEntry; - return; - } else { - func = compareEntry; - return; - } - } - case PhysicalTypeID::VAR_LIST: { - func = compareEntry; - return; - } - default: { - throw RuntimeException( - "Cannot compare data type " + - PhysicalTypeUtils::physicalTypeToString(logicalType.getPhysicalType())); - } - } -} - void AggregateHashTable::updateNullAggVectorState(const std::vector& flatKeyVectors, const std::vector& unFlatKeyVectors, std::unique_ptr& aggregateFunction, uint64_t multiplicity, @@ -808,9 +601,9 @@ void AggregateHashTable::updateNullAggVectorState(const std::vectorstate->selVector->selectedSize; for (auto i = 0u; i < selectedSize; i++) { auto pos = unFlatKeyVectors[0]->state->selVector->selectedPositions[i]; - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[pos]->entry + aggStateOffset, nullptr, multiplicity, - 0 /* dummy pos */, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[pos]->entry + + aggStateOffset, + nullptr, multiplicity, 0 /* dummy pos */, &memoryManager); } } } @@ -838,16 +631,16 @@ void AggregateHashTable::updateFlatUnFlatKeyFlatAggVectorState( if (!aggVector->isNull(aggPos)) { if (unFlatKeyVectors[0]->state->selVector->isUnfiltered()) { for (auto i = 0u; i < selectedSize; i++) { - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[i]->entry + aggStateOffset, aggVector, multiplicity, - aggPos, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[i]->entry + + aggStateOffset, + aggVector, multiplicity, aggPos, &memoryManager); } } else { for (auto i = 0u; i < selectedSize; i++) { auto pos = unFlatKeyVectors[0]->state->selVector->selectedPositions[i]; - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[pos]->entry + aggStateOffset, aggVector, multiplicity, - aggPos, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[pos]->entry + + aggStateOffset, + aggVector, multiplicity, aggPos, &memoryManager); } } } @@ -862,16 +655,16 @@ void AggregateHashTable::updateFlatKeyUnFlatAggVectorState( if (aggVector->hasNoNullsGuarantee()) { if (aggVector->state->selVector->isUnfiltered()) { for (auto i = 0u; i < aggVecSelectedSize; i++) { - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[groupByKeyPos]->entry + aggStateOffset, aggVector, - multiplicity, aggVector->state->selVector->selectedPositions[i], + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[groupByKeyPos]->entry + + aggStateOffset, + aggVector, multiplicity, aggVector->state->selVector->selectedPositions[i], &memoryManager); } } else { for (auto i = 0u; i < aggVecSelectedSize; i++) { - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[groupByKeyPos]->entry + aggStateOffset, aggVector, - multiplicity, aggVector->state->selVector->selectedPositions[i], + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[groupByKeyPos]->entry + + aggStateOffset, + aggVector, multiplicity, aggVector->state->selVector->selectedPositions[i], &memoryManager); } } @@ -880,7 +673,7 @@ void AggregateHashTable::updateFlatKeyUnFlatAggVectorState( for (auto i = 0u; i < aggVecSelectedSize; i++) { if (!aggVector->isNull(i)) { aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[0]->entry + aggStateOffset, aggVector, + hashSlotsToUpdateAggState[groupByKeyPos]->entry + aggStateOffset, aggVector, multiplicity, i, &memoryManager); } } @@ -889,7 +682,7 @@ void AggregateHashTable::updateFlatKeyUnFlatAggVectorState( auto pos = aggVector->state->selVector->selectedPositions[i]; if (!aggVector->isNull(pos)) { aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[0]->entry + aggStateOffset, aggVector, + hashSlotsToUpdateAggState[groupByKeyPos]->entry + aggStateOffset, aggVector, multiplicity, pos, &memoryManager); } } @@ -905,34 +698,34 @@ void AggregateHashTable::updateBothUnFlatSameDCAggVectorState( if (aggVector->hasNoNullsGuarantee()) { if (aggVector->state->selVector->isUnfiltered()) { for (auto i = 0u; i < aggVector->state->selVector->selectedSize; i++) { - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[i]->entry + aggStateOffset, aggVector, multiplicity, - i, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[i]->entry + + aggStateOffset, + aggVector, multiplicity, i, &memoryManager); } } else { for (auto i = 0u; i < aggVector->state->selVector->selectedSize; i++) { auto pos = aggVector->state->selVector->selectedPositions[i]; - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[pos]->entry + aggStateOffset, aggVector, multiplicity, - pos, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[pos]->entry + + aggStateOffset, + aggVector, multiplicity, pos, &memoryManager); } } } else { if (aggVector->state->selVector->isUnfiltered()) { for (auto i = 0u; i < aggVector->state->selVector->selectedSize; i++) { if (!aggVector->isNull(i)) { - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[i]->entry + aggStateOffset, aggVector, - multiplicity, i, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[i]->entry + + aggStateOffset, + aggVector, multiplicity, i, &memoryManager); } } } else { for (auto i = 0u; i < aggVector->state->selVector->selectedSize; i++) { auto pos = aggVector->state->selVector->selectedPositions[i]; if (!aggVector->isNull(pos)) { - aggregateFunction->updatePosState( - hashSlotsToUpdateAggState[pos]->entry + aggStateOffset, aggVector, - multiplicity, pos, &memoryManager); + aggregateFunction->updatePosState(hashSlotsToUpdateAggState[pos]->entry + + aggStateOffset, + aggVector, multiplicity, pos, &memoryManager); } } } @@ -953,9 +746,9 @@ void AggregateHashTable::updateBothUnFlatDifferentDCAggVectorState( } else { for (auto i = 0u; i < selectedSize; i++) { auto pos = unFlatKeyVectors[0]->state->selVector->selectedPositions[i]; - aggregateFunction->updateAllState( - hashSlotsToUpdateAggState[pos]->entry + aggStateOffset, aggVector, multiplicity, - &memoryManager); + aggregateFunction->updateAllState(hashSlotsToUpdateAggState[pos]->entry + + aggStateOffset, + aggVector, multiplicity, &memoryManager); } } } @@ -963,18 +756,30 @@ void AggregateHashTable::updateBothUnFlatDifferentDCAggVectorState( std::vector> AggregateHashTableUtils::createDistinctHashTables( MemoryManager& memoryManager, const std::vector& groupByKeyDataTypes, const std::vector>& aggregateFunctions) { + // TODO(Xiyang): move the creation of distinct hashtable schema to mapper. std::vector> distinctHTs; for (auto& aggregateFunction : aggregateFunctions) { if (aggregateFunction->isFunctionDistinct()) { std::vector distinctKeysDataTypes(groupByKeyDataTypes.size() + 1); + auto tableSchema = std::make_unique(); for (auto i = 0u; i < groupByKeyDataTypes.size(); i++) { distinctKeysDataTypes[i] = groupByKeyDataTypes[i]; + auto size = LogicalTypeUtils::getRowLayoutSize(distinctKeysDataTypes[i]); + tableSchema->appendColumn(std::make_unique(false /* isUnflat */, + 0 /* dataChunkPos */, size)); } distinctKeysDataTypes[groupByKeyDataTypes.size()] = LogicalType{aggregateFunction->parameterTypeIDs[0]}; + tableSchema->appendColumn( + std::make_unique(false /* isUnflat */, 0 /* dataChunkPos */, + LogicalTypeUtils::getRowLayoutSize( + LogicalType{aggregateFunction->parameterTypeIDs[0]}))); + tableSchema->appendColumn(std::make_unique(false /* isUnflat */, + 0 /* dataChunkPos */, sizeof(hash_t))); std::vector> emptyFunctions; auto ht = std::make_unique(memoryManager, - std::move(distinctKeysDataTypes), emptyFunctions, 0 /* numEntriesToAllocate */); + std::move(distinctKeysDataTypes), emptyFunctions, 0 /* numEntriesToAllocate */, + std::move(tableSchema)); distinctHTs.push_back(std::move(ht)); } else { distinctHTs.push_back(nullptr); diff --git a/src/processor/operator/aggregate/base_aggregate_scan.cpp b/src/processor/operator/aggregate/base_aggregate_scan.cpp index b8dc1d6781f..94fc3995982 100644 --- a/src/processor/operator/aggregate/base_aggregate_scan.cpp +++ b/src/processor/operator/aggregate/base_aggregate_scan.cpp @@ -6,16 +6,16 @@ using namespace kuzu::function; namespace kuzu { namespace processor { -void BaseAggregateScan::initLocalStateInternal( - ResultSet* resultSet, ExecutionContext* /*context*/) { +void BaseAggregateScan::initLocalStateInternal(ResultSet* resultSet, + ExecutionContext* /*context*/) { for (auto& dataPos : aggregatesPos) { auto valueVector = resultSet->getValueVector(dataPos); aggregateVectors.push_back(valueVector); } } -void BaseAggregateScan::writeAggregateResultToVector( - ValueVector& vector, uint64_t pos, AggregateState* aggregateState) { +void BaseAggregateScan::writeAggregateResultToVector(ValueVector& vector, uint64_t pos, + AggregateState* aggregateState) { if (aggregateState->isNull) { vector.setNull(pos, true); } else { diff --git a/src/processor/operator/aggregate/hash_aggregate.cpp b/src/processor/operator/aggregate/hash_aggregate.cpp index 3fa4647fae0..9c88638a131 100644 --- a/src/processor/operator/aggregate/hash_aggregate.cpp +++ b/src/processor/operator/aggregate/hash_aggregate.cpp @@ -1,5 +1,8 @@ #include "processor/operator/aggregate/hash_aggregate.h" +#include "common/utils.h" +#include "processor/result/mark_hash_table.h" + using namespace kuzu::common; using namespace kuzu::function; using namespace kuzu::storage; @@ -41,44 +44,76 @@ std::pair HashAggregateSharedState::getNextRangeToRead() { return std::make_pair(currentOffset, currentOffset); } auto startOffset = currentOffset; - auto range = std::min( - DEFAULT_VECTOR_CAPACITY, globalAggregateHashTable->getNumEntries() - currentOffset); + auto range = std::min(DEFAULT_VECTOR_CAPACITY, + globalAggregateHashTable->getNumEntries() - currentOffset); currentOffset += range; return std::make_pair(startOffset, startOffset + range); } -void HashAggregate::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { - BaseAggregate::initLocalStateInternal(resultSet, context); +HashAggregateInfo::HashAggregateInfo(std::vector flatKeysPos, + std::vector unFlatKeysPos, std::vector dependentKeysPos, + std::unique_ptr tableSchema, HashTableType hashTableType) + : flatKeysPos{std::move(flatKeysPos)}, unFlatKeysPos{std::move(unFlatKeysPos)}, + dependentKeysPos{std::move(dependentKeysPos)}, tableSchema{std::move(tableSchema)}, + hashTableType{hashTableType} {} + +HashAggregateInfo::HashAggregateInfo(const HashAggregateInfo& other) + : flatKeysPos{other.flatKeysPos}, unFlatKeysPos{other.unFlatKeysPos}, + dependentKeysPos{other.dependentKeysPos}, tableSchema{other.tableSchema->copy()}, + hashTableType{other.hashTableType} {} + +void HashAggregateLocalState::init(ResultSet& resultSet, main::ClientContext* context, + HashAggregateInfo& info, + std::vector>& aggregateFunctions) { std::vector keyDataTypes; - for (auto& pos : flatKeysPos) { - auto vector = resultSet->getValueVector(pos).get(); + for (auto& pos : info.flatKeysPos) { + auto vector = resultSet.getValueVector(pos).get(); flatKeyVectors.push_back(vector); keyDataTypes.push_back(vector->dataType); } - for (auto& pos : unFlatKeysPos) { - auto vector = resultSet->getValueVector(pos).get(); + for (auto& pos : info.unFlatKeysPos) { + auto vector = resultSet.getValueVector(pos).get(); unFlatKeyVectors.push_back(vector); keyDataTypes.push_back(vector->dataType); } std::vector payloadDataTypes; - for (auto& pos : dependentKeysPos) { - auto vector = resultSet->getValueVector(pos).get(); + for (auto& pos : info.dependentKeysPos) { + auto vector = resultSet.getValueVector(pos).get(); dependentKeyVectors.push_back(vector); payloadDataTypes.push_back(vector->dataType); } leadingState = unFlatKeyVectors.empty() ? flatKeyVectors[0]->state.get() : unFlatKeyVectors[0]->state.get(); - localAggregateHashTable = - make_unique(*context->clientContext->getMemoryManager(), keyDataTypes, - payloadDataTypes, aggregateFunctions, 0); + switch (info.hashTableType) { + case HashTableType::AGGREGATE_HASH_TABLE: + aggregateHashTable = std::make_unique(*context->getMemoryManager(), + keyDataTypes, payloadDataTypes, aggregateFunctions, 0, std::move(info.tableSchema)); + break; + case HashTableType::MARK_HASH_TABLE: + aggregateHashTable = std::make_unique(*context->getMemoryManager(), + keyDataTypes, payloadDataTypes, aggregateFunctions, 0, std::move(info.tableSchema)); + break; + default: + KU_UNREACHABLE; + } +} + +void HashAggregateLocalState::append(std::vector>& aggregateInputs, + uint64_t multiplicity) const { + aggregateHashTable->append(flatKeyVectors, unFlatKeyVectors, dependentKeyVectors, leadingState, + aggregateInputs, multiplicity); +} + +void HashAggregate::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { + BaseAggregate::initLocalStateInternal(resultSet, context); + localState.init(*resultSet, context->clientContext, aggregateInfo, aggregateFunctions); } void HashAggregate::executeInternal(ExecutionContext* context) { while (children[0]->getNextTuple(context)) { - localAggregateHashTable->append(flatKeyVectors, unFlatKeyVectors, dependentKeyVectors, - leadingState, aggregateInputs, resultSet->multiplicity); + localState.append(aggregateInputs, resultSet->multiplicity); } - sharedState->appendAggregateHashTable(std::move(localAggregateHashTable)); + sharedState->appendAggregateHashTable(std::move(localState.aggregateHashTable)); } void HashAggregate::finalize(ExecutionContext* context) { diff --git a/src/processor/operator/aggregate/hash_aggregate_scan.cpp b/src/processor/operator/aggregate/hash_aggregate_scan.cpp index d6f2454e87a..e1e84bfdf58 100644 --- a/src/processor/operator/aggregate/hash_aggregate_scan.cpp +++ b/src/processor/operator/aggregate/hash_aggregate_scan.cpp @@ -21,8 +21,8 @@ bool HashAggregateScan::getNextTuplesInternal(ExecutionContext* /*context*/) { return false; } auto numRowsToScan = endOffset - startOffset; - sharedState->getFactorizedTable()->scan( - groupByKeyVectors, startOffset, numRowsToScan, groupByKeyVectorsColIdxes); + sharedState->getFactorizedTable()->scan(groupByKeyVectors, startOffset, numRowsToScan, + groupByKeyVectorsColIdxes); for (auto pos = 0u; pos < numRowsToScan; ++pos) { auto entry = sharedState->getRow(startOffset + pos); auto offset = sharedState->getFactorizedTable()->getTableSchema()->getColOffset( @@ -37,5 +37,15 @@ bool HashAggregateScan::getNextTuplesInternal(ExecutionContext* /*context*/) { return true; } +double HashAggregateScan::getProgress(ExecutionContext* /*context*/) const { + uint64_t totalNumTuples = sharedState->getFactorizedTable()->getNumTuples(); + if (totalNumTuples == 0) { + return 0.0; + } else if (sharedState->getCurrentOffset() == totalNumTuples) { + return 1.0; + } + return static_cast(sharedState->getCurrentOffset()) / totalNumTuples; +} + } // namespace processor } // namespace kuzu diff --git a/src/processor/operator/aggregate/simple_aggregate.cpp b/src/processor/operator/aggregate/simple_aggregate.cpp index 69f82481ca4..f39a1ac2c17 100644 --- a/src/processor/operator/aggregate/simple_aggregate.cpp +++ b/src/processor/operator/aggregate/simple_aggregate.cpp @@ -73,12 +73,12 @@ void SimpleAggregate::computeDistinctAggregate(AggregateHashTable* distinctHT, function::AggregateFunction* function, AggregateInput* input, function::AggregateState* state, storage::MemoryManager* memoryManager) { auto multiplicity = 1; // Distinct aggregate should ignore multiplicity. - if (distinctHT->isAggregateValueDistinctForGroupByKeys( - std::vector{}, input->aggregateVector)) { + if (distinctHT->isAggregateValueDistinctForGroupByKeys(std::vector{}, + input->aggregateVector)) { auto pos = input->aggregateVector->state->selVector->selectedPositions[0]; if (!input->aggregateVector->isNull(pos)) { - function->updatePosState( - (uint8_t*)state, input->aggregateVector, multiplicity, pos, memoryManager); + function->updatePosState((uint8_t*)state, input->aggregateVector, multiplicity, pos, + memoryManager); } } } @@ -92,12 +92,12 @@ void SimpleAggregate::computeAggregate(function::AggregateFunction* function, Ag if (input->aggregateVector && input->aggregateVector->state->isFlat()) { auto pos = input->aggregateVector->state->selVector->selectedPositions[0]; if (!input->aggregateVector->isNull(pos)) { - function->updatePosState( - (uint8_t*)state, input->aggregateVector, multiplicity, pos, memoryManager); + function->updatePosState((uint8_t*)state, input->aggregateVector, multiplicity, pos, + memoryManager); } } else { - function->updateAllState( - (uint8_t*)state, input->aggregateVector, multiplicity, memoryManager); + function->updateAllState((uint8_t*)state, input->aggregateVector, multiplicity, + memoryManager); } } diff --git a/src/processor/operator/aggregate/simple_aggregate_scan.cpp b/src/processor/operator/aggregate/simple_aggregate_scan.cpp index 3ae7fc36779..922cd1c4e78 100644 --- a/src/processor/operator/aggregate/simple_aggregate_scan.cpp +++ b/src/processor/operator/aggregate/simple_aggregate_scan.cpp @@ -21,8 +21,8 @@ bool SimpleAggregateScan::getNextTuplesInternal(ExecutionContext* /*context*/) { // Output of simple aggregate is guaranteed to be a single value for each aggregate. KU_ASSERT(startOffset == 0 && endOffset == 1); for (auto i = 0u; i < aggregateVectors.size(); i++) { - writeAggregateResultToVector( - *aggregateVectors[i], 0 /* position to write */, sharedState->getAggregateState(i)); + writeAggregateResultToVector(*aggregateVectors[i], 0 /* position to write */, + sharedState->getAggregateState(i)); } KU_ASSERT(!aggregatesPos.empty()); outDataChunk->state->initOriginalAndSelectedSize(1); diff --git a/src/processor/operator/attach_database.cpp b/src/processor/operator/attach_database.cpp new file mode 100644 index 00000000000..a924ba07109 --- /dev/null +++ b/src/processor/operator/attach_database.cpp @@ -0,0 +1,25 @@ +#include "processor/operator/attach_database.h" + +#include "main/database.h" +#include "main/database_manager.h" +#include "storage/storage_extension.h" + +namespace kuzu { +namespace processor { + +bool AttachDatabase::getNextTuplesInternal(kuzu::processor::ExecutionContext* context) { + for (auto& [name, storageExtension] : + context->clientContext->getDatabase()->getStorageExtensions()) { + if (storageExtension->canHandleDB(attachInfo.dbType)) { + auto db = storageExtension->attach(attachInfo.dbAlias, attachInfo.dbPath, + context->clientContext); + context->clientContext->getDatabase() + ->getDatabaseManagerUnsafe() + ->registerAttachedDatabase(std::move(db)); + } + } + return false; +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/operator/call/in_query_call.cpp b/src/processor/operator/call/in_query_call.cpp index 52cc0970cc7..5f8a897686f 100644 --- a/src/processor/operator/call/in_query_call.cpp +++ b/src/processor/operator/call/in_query_call.cpp @@ -40,21 +40,21 @@ void InQueryCall::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* } // Init table function input. function::TableFunctionInitInput tableFunctionInitInput{info.bindData.get()}; - localState.funcState = info.function->initLocalStateFunc(tableFunctionInitInput, + localState.funcState = info.function.initLocalStateFunc(tableFunctionInitInput, sharedState->funcState.get(), context->clientContext->getMemoryManager()); - localState.funcInput = function::TableFuncInput{ - info.bindData.get(), localState.funcState.get(), sharedState->funcState.get()}; + localState.funcInput = function::TableFuncInput{info.bindData.get(), localState.funcState.get(), + sharedState->funcState.get()}; } void InQueryCall::initGlobalStateInternal(ExecutionContext*) { function::TableFunctionInitInput tableFunctionInitInput{info.bindData.get()}; - sharedState->funcState = info.function->initSharedStateFunc(tableFunctionInitInput); + sharedState->funcState = info.function.initSharedStateFunc(tableFunctionInitInput); } bool InQueryCall::getNextTuplesInternal(ExecutionContext*) { localState.funcOutput.dataChunk.state->selVector->selectedSize = 0; localState.funcOutput.dataChunk.resetAuxiliaryBuffer(); - auto numTuplesScanned = info.function->tableFunc(localState.funcInput, localState.funcOutput); + auto numTuplesScanned = info.function.tableFunc(localState.funcInput, localState.funcOutput); localState.funcOutput.dataChunk.state->selVector->selectedSize = numTuplesScanned; if (localState.rowOffsetVector != nullptr) { auto rowIdx = sharedState->getAndIncreaseRowIdx(numTuplesScanned); @@ -65,5 +65,9 @@ bool InQueryCall::getNextTuplesInternal(ExecutionContext*) { return numTuplesScanned != 0; } +double InQueryCall::getProgress(ExecutionContext* /*context*/) const { + return info.function.progressFunc(sharedState->funcState.get()); +} + } // namespace processor } // namespace kuzu diff --git a/src/processor/operator/call/standalone_call.cpp b/src/processor/operator/call/standalone_call.cpp index 890ba16b696..2664029358a 100644 --- a/src/processor/operator/call/standalone_call.cpp +++ b/src/processor/operator/call/standalone_call.cpp @@ -19,8 +19,8 @@ bool StandaloneCall::getNextTuplesInternal(kuzu::processor::ExecutionContext* co break; } case main::OptionType::EXTENSION: - context->clientContext->setExtensionOption( - standaloneCallInfo->option->name, standaloneCallInfo->optionValue); + context->clientContext->setExtensionOption(standaloneCallInfo->option->name, + standaloneCallInfo->optionValue); break; } metrics->numOutputTuple.increase(1); diff --git a/src/processor/operator/comment_on.cpp b/src/processor/operator/comment_on.cpp index 95096422858..0b484c27bea 100644 --- a/src/processor/operator/comment_on.cpp +++ b/src/processor/operator/comment_on.cpp @@ -8,6 +8,7 @@ using namespace kuzu::common; namespace kuzu { namespace processor { +// TODO(Xiyang/Ziyi): Should move this operator into Alter. bool CommentOn::getNextTuplesInternal(kuzu::processor::ExecutionContext* /*context*/) { if (commentOnInfo->hasExecuted) { return false; diff --git a/src/processor/operator/ddl/CMakeLists.txt b/src/processor/operator/ddl/CMakeLists.txt index 0349e6816f1..f929222bcc1 100644 --- a/src/processor/operator/ddl/CMakeLists.txt +++ b/src/processor/operator/ddl/CMakeLists.txt @@ -1,14 +1,8 @@ add_library(kuzu_processor_operator_ddl OBJECT - add_node_property.cpp - add_property.cpp - add_rel_property.cpp - create_node_table.cpp - create_rdf_graph.cpp - create_rel_table_group.cpp - create_rel_table.cpp + alter.cpp + create_table.cpp ddl.cpp - drop_property.cpp drop_table.cpp) set(ALL_OBJECT_FILES diff --git a/src/processor/operator/ddl/add_node_property.cpp b/src/processor/operator/ddl/add_node_property.cpp deleted file mode 100644 index 5131fd1b0f9..00000000000 --- a/src/processor/operator/ddl/add_node_property.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "processor/operator/ddl/add_node_property.h" - -namespace kuzu { -namespace processor { - -void AddNodeProperty::executeDDLInternal(ExecutionContext* context) { - catalog->addNodeProperty(tableID, propertyName, std::move(dataType)); - auto schema = catalog->getTableCatalogEntry(context->clientContext->getTx(), tableID); - auto addedPropID = schema->getPropertyID(propertyName); - auto addedProp = schema->getProperty(addedPropID); - storageManager.getNodeTable(tableID)->addColumn( - transaction, *addedProp, getDefaultValVector(context)); - storageManager.getWAL()->logAddPropertyRecord(tableID, addedProp->getPropertyID()); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/add_property.cpp b/src/processor/operator/ddl/add_property.cpp deleted file mode 100644 index 5986ea59c5c..00000000000 --- a/src/processor/operator/ddl/add_property.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "processor/operator/ddl/add_property.h" - -namespace kuzu { -namespace processor { - -common::ValueVector* AddProperty::getDefaultValVector(ExecutionContext* context) { - defaultValueEvaluator->evaluate(context->clientContext); - return defaultValueEvaluator->resultVector.get(); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/add_rel_property.cpp b/src/processor/operator/ddl/add_rel_property.cpp deleted file mode 100644 index 4779e712d58..00000000000 --- a/src/processor/operator/ddl/add_rel_property.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "processor/operator/ddl/add_rel_property.h" - -using namespace kuzu::catalog; -using namespace kuzu::storage; -using namespace kuzu::common; - -namespace kuzu { -namespace processor { - -void AddRelProperty::executeDDLInternal(ExecutionContext* context) { - catalog->addRelProperty(tableID, propertyName, dataType->copy()); - auto tableSchema = catalog->getTableCatalogEntry(context->clientContext->getTx(), tableID); - auto addedPropertyID = tableSchema->getPropertyID(propertyName); - auto addedProp = tableSchema->getProperty(addedPropertyID); - storageManager.getRelTable(tableID)->addColumn( - transaction, *addedProp, getDefaultValVector(context)); - storageManager.getWAL()->logAddPropertyRecord(tableID, addedProp->getPropertyID()); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/alter.cpp b/src/processor/operator/ddl/alter.cpp new file mode 100644 index 00000000000..6f05120d704 --- /dev/null +++ b/src/processor/operator/ddl/alter.cpp @@ -0,0 +1,55 @@ +#include "processor/operator/ddl/alter.h" + +#include "catalog/catalog.h" +#include "common/enums/alter_type.h" +#include "storage/storage_manager.h" + +namespace kuzu { +namespace processor { + +void Alter::executeDDLInternal(ExecutionContext* context) { + switch (info.alterType) { + case common::AlterType::ADD_PROPERTY: { + context->clientContext->getCatalog()->alterTableSchema(info); + auto& boundAddPropInfo = common::ku_dynamic_cast(*info.extraInfo); + KU_ASSERT(defaultValueEvaluator); + auto schema = context->clientContext->getCatalog()->getTableCatalogEntry( + context->clientContext->getTx(), info.tableID); + auto addedPropID = schema->getPropertyID(boundAddPropInfo.propertyName); + auto addedProp = schema->getProperty(addedPropID); + defaultValueEvaluator->evaluate(context->clientContext); + auto storageManager = context->clientContext->getStorageManager(); + storageManager->getTable(info.tableID) + ->addColumn(context->clientContext->getTx(), *addedProp, + defaultValueEvaluator->resultVector.get()); + } break; + case common::AlterType::DROP_PROPERTY: { + auto& boundDropPropInfo = common::ku_dynamic_cast(*info.extraInfo); + auto tableEntry = context->clientContext->getCatalog()->getTableCatalogEntry( + context->clientContext->getTx(), info.tableID); + auto columnID = tableEntry->getColumnID(boundDropPropInfo.propertyID); + context->clientContext->getCatalog()->alterTableSchema(info); + if (tableEntry->getTableType() == common::TableType::NODE) { + auto nodesStats = + context->clientContext->getStorageManager()->getNodesStatisticsAndDeletedIDs(); + nodesStats->removeMetadataDAHInfo(info.tableID, columnID); + } else { + auto relsStats = context->clientContext->getStorageManager()->getRelsStatistics(); + relsStats->removeMetadataDAHInfo(info.tableID, columnID); + } + } break; + default: { + context->clientContext->getCatalog()->alterTableSchema(info); + // DO NOTHING. + } + } +} + +std::string Alter::getOutputMsg() { + return common::stringFormat("Table {} altered.", info.tableName); +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/operator/ddl/create_node_table.cpp b/src/processor/operator/ddl/create_node_table.cpp deleted file mode 100644 index 074b31dcf98..00000000000 --- a/src/processor/operator/ddl/create_node_table.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "processor/operator/ddl/create_node_table.h" - -#include "catalog/catalog_entry/node_table_catalog_entry.h" -#include "common/string_format.h" -#include "storage/storage_manager.h" - -using namespace kuzu::catalog; -using namespace kuzu::common; - -namespace kuzu { -namespace processor { - -void CreateNodeTable::executeDDLInternal(ExecutionContext* context) { - auto newTableID = catalog->addNodeTableSchema(info); - auto newNodeTableEntry = ku_dynamic_cast( - catalog->getTableCatalogEntry(context->clientContext->getTx(), newTableID)); - storageManager->getNodesStatisticsAndDeletedIDs()->addNodeStatisticsAndDeletedIDs( - newNodeTableEntry); - storageManager->createTable(newTableID, catalog, context->clientContext->getTx()); - storageManager->getWAL()->logCreateNodeTableRecord(newTableID); -} - -std::string CreateNodeTable::getOutputMsg() { - return stringFormat("Node table: {} has been created.", info.tableName); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/create_rdf_graph.cpp b/src/processor/operator/ddl/create_rdf_graph.cpp deleted file mode 100644 index 844f07d40ae..00000000000 --- a/src/processor/operator/ddl/create_rdf_graph.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "processor/operator/ddl/create_rdf_graph.h" - -#include "catalog/catalog_entry/rdf_graph_catalog_entry.h" -#include "common/cast.h" -#include "common/string_format.h" -#include "storage/storage_manager.h" - -using namespace kuzu::catalog; - -namespace kuzu { -namespace processor { - -using namespace kuzu::common; - -void CreateRdfGraph::executeDDLInternal(ExecutionContext* context) { - auto tx = context->clientContext->getTx(); - auto newRdfGraphID = catalog->addRdfGraphSchema(info); - auto rdfGraphEntry = common::ku_dynamic_cast( - catalog->getTableCatalogEntry(tx, newRdfGraphID)); - auto resourceTableID = rdfGraphEntry->getResourceTableID(); - auto resourceTableEntry = common::ku_dynamic_cast( - catalog->getTableCatalogEntry(tx, resourceTableID)); - nodesStatistics->addNodeStatisticsAndDeletedIDs(resourceTableEntry); - storageManager->createTable(resourceTableID, catalog, tx); - auto literalTableID = rdfGraphEntry->getLiteralTableID(); - auto literalTableEntry = common::ku_dynamic_cast( - catalog->getTableCatalogEntry(tx, literalTableID)); - nodesStatistics->addNodeStatisticsAndDeletedIDs(literalTableEntry); - storageManager->createTable(literalTableID, catalog, tx); - auto resourceTripleTableID = rdfGraphEntry->getResourceTripleTableID(); - auto resourceTripleTableEntry = - common::ku_dynamic_cast( - catalog->getTableCatalogEntry(tx, resourceTripleTableID)); - relsStatistics->addTableStatistic(resourceTripleTableEntry); - storageManager->createTable(resourceTripleTableID, catalog, tx); - auto literalTripleTableID = rdfGraphEntry->getLiteralTripleTableID(); - auto literalTripleTableEntry = - common::ku_dynamic_cast( - catalog->getTableCatalogEntry(tx, literalTripleTableID)); - relsStatistics->addTableStatistic(literalTripleTableEntry); - storageManager->createTable(literalTripleTableID, catalog, tx); - storageManager->getWAL()->logRdfGraphRecord(newRdfGraphID, resourceTableID, literalTableID, - resourceTripleTableID, literalTripleTableID); -} - -std::string CreateRdfGraph::getOutputMsg() { - return common::stringFormat("RDF graph {} has been created.", info.tableName); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/create_rel_table.cpp b/src/processor/operator/ddl/create_rel_table.cpp deleted file mode 100644 index 9217f88692f..00000000000 --- a/src/processor/operator/ddl/create_rel_table.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "processor/operator/ddl/create_rel_table.h" - -#include "catalog/catalog_entry/rel_table_catalog_entry.h" -#include "common/string_format.h" -#include "storage/storage_manager.h" - -using namespace kuzu::catalog; -using namespace kuzu::common; -using namespace kuzu::binder; - -namespace kuzu { -namespace processor { - -void CreateRelTable::executeDDLInternal(ExecutionContext* context) { - auto newTableID = catalog->addRelTableSchema(info); - auto newRelTableEntry = ku_dynamic_cast( - catalog->getTableCatalogEntry(context->clientContext->getTx(), newTableID)); - storageManager->getRelsStatistics()->addTableStatistic(newRelTableEntry); - storageManager->createTable(newTableID, catalog, context->clientContext->getTx()); - storageManager->getWAL()->logCreateRelTableRecord(newTableID); -} - -std::string CreateRelTable::getOutputMsg() { - return stringFormat("Rel table: {} has been created.", info.tableName); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/create_rel_table_group.cpp b/src/processor/operator/ddl/create_rel_table_group.cpp deleted file mode 100644 index 55cac558302..00000000000 --- a/src/processor/operator/ddl/create_rel_table_group.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "processor/operator/ddl/create_rel_table_group.h" - -#include "catalog/catalog_entry/rel_group_catalog_entry.h" -#include "catalog/catalog_entry/rel_table_catalog_entry.h" -#include "common/string_format.h" -#include "storage/storage_manager.h" - -using namespace kuzu::common; -using namespace kuzu::catalog; - -namespace kuzu { -namespace processor { - -void CreateRelTableGroup::executeDDLInternal(ExecutionContext* context) { - auto newRelTableGroupID = catalog->addRelTableGroupSchema(info); - auto tx = context->clientContext->getTx(); - auto newRelGroupEntry = ku_dynamic_cast( - catalog->getTableCatalogEntry(tx, newRelTableGroupID)); - for (auto& relTableID : newRelGroupEntry->getRelTableIDs()) { - auto newRelTableEntry = catalog->getTableCatalogEntry(tx, relTableID); - storageManager->getRelsStatistics()->addTableStatistic( - ku_dynamic_cast(newRelTableEntry)); - storageManager->createTable(relTableID, catalog, tx); - } - // TODO(Ziyi): remove this when we can log variable size record. See also wal_record.h - for (auto relTableID : newRelGroupEntry->getRelTableIDs()) { - storageManager->getWAL()->logCreateRelTableRecord(relTableID); - } -} - -std::string CreateRelTableGroup::getOutputMsg() { - return stringFormat("Rel table group: {} has been created.", info.tableName); -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/create_table.cpp b/src/processor/operator/ddl/create_table.cpp new file mode 100644 index 00000000000..a4f73420773 --- /dev/null +++ b/src/processor/operator/ddl/create_table.cpp @@ -0,0 +1,24 @@ +#include "processor/operator/ddl/create_table.h" + +#include "common/string_format.h" +#include "storage/storage_manager.h" + +using namespace kuzu::catalog; +using namespace kuzu::common; + +namespace kuzu { +namespace processor { + +void CreateTable::executeDDLInternal(ExecutionContext* context) { + auto catalog = context->clientContext->getCatalog(); + auto newTableID = catalog->createTableSchema(info); + auto storageManager = context->clientContext->getStorageManager(); + storageManager->createTable(newTableID, catalog, context->clientContext->getTx()); +} + +std::string CreateTable::getOutputMsg() { + return stringFormat("Table {} has been created.", info.tableName); +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/operator/ddl/drop_property.cpp b/src/processor/operator/ddl/drop_property.cpp deleted file mode 100644 index d0f8cbe73cf..00000000000 --- a/src/processor/operator/ddl/drop_property.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "processor/operator/ddl/drop_property.h" - -namespace kuzu { -namespace processor { - -void DropProperty::executeDDLInternal(ExecutionContext* context) { - auto tableEntry = catalog->getTableCatalogEntry(context->clientContext->getTx(), tableID); - auto columnID = tableEntry->getColumnID(propertyID); - catalog->dropProperty(tableID, propertyID); - if (tableEntry->getTableType() == common::TableType::NODE) { - auto nodesStats = storageManager.getNodesStatisticsAndDeletedIDs(); - nodesStats->removeMetadataDAHInfo(tableID, columnID); - } else { - auto relsStats = storageManager.getRelsStatistics(); - relsStats->removeMetadataDAHInfo(tableID, columnID); - } -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/ddl/drop_table.cpp b/src/processor/operator/ddl/drop_table.cpp index 67d9919c3ba..71196bfc00a 100644 --- a/src/processor/operator/ddl/drop_table.cpp +++ b/src/processor/operator/ddl/drop_table.cpp @@ -1,5 +1,6 @@ #include "processor/operator/ddl/drop_table.h" +#include "catalog/catalog.h" #include "common/string_format.h" using namespace kuzu::catalog; @@ -8,8 +9,8 @@ using namespace kuzu::common; namespace kuzu { namespace processor { -void DropTable::executeDDLInternal(ExecutionContext* /*context*/) { - catalog->dropTableSchema(tableID); +void DropTable::executeDDLInternal(ExecutionContext* context) { + context->clientContext->getCatalog()->dropTableSchema(tableID); } std::string DropTable::getOutputMsg() { diff --git a/src/processor/operator/detach_database.cpp b/src/processor/operator/detach_database.cpp new file mode 100644 index 00000000000..c9c23041763 --- /dev/null +++ b/src/processor/operator/detach_database.cpp @@ -0,0 +1,16 @@ +#include "processor/operator/detach_database.h" + +#include "main/database.h" +#include "main/database_manager.h" + +namespace kuzu { +namespace processor { + +bool DetachDatabase::getNextTuplesInternal(kuzu::processor::ExecutionContext* context) { + auto dbManager = context->clientContext->getDatabase()->getDatabaseManagerUnsafe(); + dbManager->detachDatabase(dbName); + return false; +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/operator/filter.cpp b/src/processor/operator/filter.cpp index 6e420dddfde..5ff5bb88add 100644 --- a/src/processor/operator/filter.cpp +++ b/src/processor/operator/filter.cpp @@ -23,15 +23,15 @@ bool Filter::getNextTuplesInternal(ExecutionContext* context) { *dataChunkToSelect->state->selVector, context->clientContext); if (!dataChunkToSelect->state->isFlat() && dataChunkToSelect->state->selVector->isUnfiltered()) { - dataChunkToSelect->state->selVector->resetSelectorToValuePosBuffer(); + dataChunkToSelect->state->selVector->setToFiltered(); } } while (!hasAtLeastOneSelectedValue); metrics->numOutputTuple.increase(dataChunkToSelect->state->selVector->selectedSize); return true; } -void NodeLabelFiler::initLocalStateInternal( - ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) { +void NodeLabelFiler::initLocalStateInternal(ResultSet* /*resultSet_*/, + ExecutionContext* /*context*/) { nodeIDVector = resultSet->getValueVector(info->nodeVectorPos).get(); } @@ -44,14 +44,14 @@ bool NodeLabelFiler::getNextTuplesInternal(ExecutionContext* context) { } saveSelVector(nodeIDVector->state->selVector); numSelectValue = 0; - auto buffer = nodeIDVector->state->selVector->getSelectedPositionsBuffer(); + auto buffer = nodeIDVector->state->selVector->getMultableBuffer(); for (auto i = 0u; i < nodeIDVector->state->selVector->selectedSize; ++i) { auto pos = nodeIDVector->state->selVector->selectedPositions[i]; buffer[numSelectValue] = pos; numSelectValue += info->nodeLabelSet.contains(nodeIDVector->getValue(pos).tableID); } - nodeIDVector->state->selVector->resetSelectorToValuePosBuffer(); + nodeIDVector->state->selVector->setToFiltered(); } while (numSelectValue == 0); nodeIDVector->state->selVector->selectedSize = numSelectValue; metrics->numOutputTuple.increase(nodeIDVector->state->selVector->selectedSize); diff --git a/src/processor/operator/filtering_operator.cpp b/src/processor/operator/filtering_operator.cpp index 2d541bce55c..0f72df0a9c7 100644 --- a/src/processor/operator/filtering_operator.cpp +++ b/src/processor/operator/filtering_operator.cpp @@ -23,11 +23,11 @@ void SelVectorOverWriter::saveSelVector(std::shared_ptr& selVec void SelVectorOverWriter::resetToCurrentSelVector(std::shared_ptr& selVector) { currentSelVector->selectedSize = selVector->selectedSize; if (selVector->isUnfiltered()) { - currentSelVector->resetSelectorToUnselected(); + currentSelVector->setToUnfiltered(); } else { - memcpy(currentSelVector->getSelectedPositionsBuffer(), selVector->selectedPositions, + memcpy(currentSelVector->getMultableBuffer(), selVector->selectedPositions, selVector->selectedSize * sizeof(sel_t)); - currentSelVector->resetSelectorToValuePosBuffer(); + currentSelVector->setToFiltered(); } selVector = currentSelVector; } diff --git a/src/processor/operator/flatten.cpp b/src/processor/operator/flatten.cpp index cb1948dc75e..c815e785ecf 100644 --- a/src/processor/operator/flatten.cpp +++ b/src/processor/operator/flatten.cpp @@ -7,7 +7,7 @@ namespace processor { void Flatten::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* /*context*/) { dataChunkState = resultSet->dataChunks[dataChunkToFlattenPos]->state.get(); - currentSelVector->resetSelectorToValuePosBufferWithSize(1 /* size */); + currentSelVector->setToFiltered(1 /* size */); localState = std::make_unique(); } diff --git a/src/processor/operator/hash_join/hash_join_build.cpp b/src/processor/operator/hash_join/hash_join_build.cpp index 14dfd163b73..3749a3fce65 100644 --- a/src/processor/operator/hash_join/hash_join_build.cpp +++ b/src/processor/operator/hash_join/hash_join_build.cpp @@ -12,10 +12,10 @@ void HashJoinSharedState::mergeLocalHashTable(JoinHashTable& localHashTable) { } void HashJoinBuild::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { - std::vector> keyTypes; + std::vector keyTypes; for (auto i = 0u; i < info->keysPos.size(); ++i) { auto vector = resultSet->getValueVector(info->keysPos[i]).get(); - keyTypes.push_back(vector->dataType.copy()); + keyTypes.push_back(*vector->dataType.copy()); if (info->fStateTypes[i] == common::FStateType::UNFLAT) { setKeyState(vector->state.get()); } diff --git a/src/processor/operator/hash_join/hash_join_probe.cpp b/src/processor/operator/hash_join/hash_join_probe.cpp index 76b0e10f314..3e3e53364f7 100644 --- a/src/processor/operator/hash_join/hash_join_probe.cpp +++ b/src/processor/operator/hash_join/hash_join_probe.cpp @@ -18,16 +18,16 @@ void HashJoinProbe::initLocalStateInternal(ResultSet* resultSet, ExecutionContex } // We only need to read nonKeys from the factorizedTable. Key columns are always kept as first k // columns in the factorizedTable, so we skip the first k columns. - KU_ASSERT(probeDataInfo.keysDataPos.size() + probeDataInfo.getNumPayloads() + 1 == + KU_ASSERT(probeDataInfo.keysDataPos.size() + probeDataInfo.getNumPayloads() + 2 == sharedState->getHashTable()->getTableSchema()->getNumColumns()); columnIdxsToReadFrom.resize(probeDataInfo.getNumPayloads()); - iota( - columnIdxsToReadFrom.begin(), columnIdxsToReadFrom.end(), probeDataInfo.keysDataPos.size()); - hashVector = std::make_unique( - LogicalTypeID::INT64, context->clientContext->getMemoryManager()); + iota(columnIdxsToReadFrom.begin(), columnIdxsToReadFrom.end(), + probeDataInfo.keysDataPos.size()); + hashVector = std::make_unique(LogicalTypeID::INT64, + context->clientContext->getMemoryManager()); if (keyVectors.size() > 1) { - tmpHashVector = std::make_unique( - LogicalTypeID::INT64, context->clientContext->getMemoryManager()); + tmpHashVector = std::make_unique(LogicalTypeID::INT64, + context->clientContext->getMemoryManager()); } } @@ -45,11 +45,11 @@ bool HashJoinProbe::getMatchedTuplesForFlatKey(ExecutionContext* context) { return false; } saveSelVector(keyVectors[0]->state->selVector); - sharedState->getHashTable()->probe( - keyVectors, hashVector.get(), tmpHashVector.get(), probeState->probedTuples.get()); + sharedState->getHashTable()->probe(keyVectors, hashVector.get(), tmpHashVector.get(), + probeState->probedTuples.get()); } - auto numMatchedTuples = sharedState->getHashTable()->matchFlatKeys( - keyVectors, probeState->probedTuples.get(), probeState->matchedTuples.get()); + auto numMatchedTuples = sharedState->getHashTable()->matchFlatKeys(keyVectors, + probeState->probedTuples.get(), probeState->matchedTuples.get()); probeState->matchedSelVector->selectedSize = numMatchedTuples; probeState->nextMatchedTupleIdx = 0; return true; @@ -63,8 +63,8 @@ bool HashJoinProbe::getMatchedTuplesForUnFlatKey(ExecutionContext* context) { return false; } saveSelVector(keyVector->state->selVector); - sharedState->getHashTable()->probe( - keyVectors, hashVector.get(), tmpHashVector.get(), probeState->probedTuples.get()); + sharedState->getHashTable()->probe(keyVectors, hashVector.get(), tmpHashVector.get(), + probeState->probedTuples.get()); auto numMatchedTuples = sharedState->getHashTable()->matchUnFlatKey(keyVector, probeState->probedTuples.get(), probeState->matchedTuples.get(), probeState->matchedSelVector.get()); @@ -92,12 +92,11 @@ uint64_t HashJoinProbe::getInnerJoinResultForUnFlatKey() { auto keySelVector = keyVectors[0]->state->selVector.get(); if (keySelVector->selectedSize != numTuplesToRead) { // Some keys have no matched tuple. So we modify selected position. - auto keySelectedBuffer = keySelVector->getSelectedPositionsBuffer(); + auto buffer = keySelVector->getMultableBuffer(); for (auto i = 0u; i < numTuplesToRead; i++) { - keySelectedBuffer[i] = probeState->matchedSelVector->selectedPositions[i]; + buffer[i] = probeState->matchedSelVector->selectedPositions[i]; } - keySelVector->selectedSize = numTuplesToRead; - keySelVector->resetSelectorToValuePosBuffer(); + keySelVector->setToFiltered(numTuplesToRead); } sharedState->getHashTable()->lookup(vectorsToReadInto, columnIdxsToReadFrom, probeState->matchedTuples.get(), probeState->nextMatchedTupleIdx, numTuplesToRead); diff --git a/src/processor/operator/hash_join/join_hash_table.cpp b/src/processor/operator/hash_join/join_hash_table.cpp index 9e7a61a370e..8da39523f1d 100644 --- a/src/processor/operator/hash_join/join_hash_table.cpp +++ b/src/processor/operator/hash_join/join_hash_table.cpp @@ -1,6 +1,6 @@ #include "processor/operator/hash_join/join_hash_table.h" -#include "function/comparison/comparison_functions.h" +#include "common/utils.h" #include "function/hash/vector_hash_functions.h" using namespace kuzu::common; @@ -10,26 +10,15 @@ using namespace kuzu::function; namespace kuzu { namespace processor { -JoinHashTable::JoinHashTable(MemoryManager& memoryManager, - std::vector> keyTypes, +JoinHashTable::JoinHashTable(MemoryManager& memoryManager, logical_type_vec_t keyTypes, std::unique_ptr tableSchema) - : BaseHashTable{memoryManager}, keyTypes{std::move(keyTypes)} { + : BaseHashTable{memoryManager, std::move(keyTypes)} { auto numSlotsPerBlock = BufferPoolConstants::PAGE_256KB_SIZE / sizeof(uint8_t*); initSlotConstant(numSlotsPerBlock); // Prev pointer is always the last column in the table. - prevPtrColOffset = tableSchema->getColOffset(tableSchema->getNumColumns() - 1); + prevPtrColOffset = tableSchema->getColOffset(tableSchema->getNumColumns() - PREV_PTR_COL_IDX); factorizedTable = std::make_unique(&memoryManager, std::move(tableSchema)); this->tableSchema = factorizedTable->getTableSchema(); - initFunctions(); -} - -void JoinHashTable::initFunctions() { - entryHashFunctions.resize(keyTypes.size()); - entryCompareFunctions.resize(keyTypes.size()); - for (auto i = 0u; i < keyTypes.size(); ++i) { - getHashFunction(keyTypes[i]->getPhysicalType(), entryHashFunctions[i]); - getCompareFunction(keyTypes[i]->getPhysicalType(), entryCompareFunctions[i]); - } } static bool discardNullFromKeys(const std::vector& vectors) { @@ -48,6 +37,7 @@ void JoinHashTable::appendVectors(const std::vector& keyVectors, discardNullFromKeys(keyVectors); auto numTuplesToAppend = keyState->selVector->selectedSize; auto appendInfos = factorizedTable->allocateFlatTupleBlocks(numTuplesToAppend); + computeVectorHashes(keyVectors); auto colIdx = 0u; for (auto& vector : keyVectors) { appendVector(vector, appendInfos, colIdx++); @@ -55,11 +45,12 @@ void JoinHashTable::appendVectors(const std::vector& keyVectors, for (auto& vector : payloadVectors) { appendVector(vector, appendInfos, colIdx++); } + appendVector(hashVector.get(), appendInfos, colIdx); factorizedTable->numTuples += numTuplesToAppend; } -void JoinHashTable::appendVector( - ValueVector* vector, const std::vector& appendInfos, ft_col_idx_t colIdx) { +void JoinHashTable::appendVector(ValueVector* vector, + const std::vector& appendInfos, ft_col_idx_t colIdx) { auto numAppendedTuples = 0ul; for (auto& blockAppendInfo : appendInfos) { factorizedTable->copyVectorToColumn(*vector, blockAppendInfo, numAppendedTuples, colIdx); @@ -70,18 +61,18 @@ void JoinHashTable::appendVector( static void sortSelectedPos(ValueVector* nodeIDVector) { auto selVector = nodeIDVector->state->selVector.get(); auto size = selVector->selectedSize; - auto selectedPos = selVector->getSelectedPositionsBuffer(); + auto buffer = selVector->getMultableBuffer(); if (selVector->isUnfiltered()) { - memcpy(selectedPos, &SelectionVector::INCREMENTAL_SELECTED_POS, size * sizeof(sel_t)); - selVector->resetSelectorToValuePosBuffer(); + memcpy(buffer, &SelectionVector::INCREMENTAL_SELECTED_POS, size * sizeof(sel_t)); + selVector->setToFiltered(); } - std::sort(selectedPos, selectedPos + size, [nodeIDVector](sel_t left, sel_t right) { + std::sort(buffer, buffer + size, [nodeIDVector](sel_t left, sel_t right) { return nodeIDVector->getValue(left) < nodeIDVector->getValue(right); }); } -void JoinHashTable::appendVectorWithSorting( - ValueVector* keyVector, std::vector payloadVectors) { +void JoinHashTable::appendVectorWithSorting(ValueVector* keyVector, + std::vector payloadVectors) { auto numTuplesToAppend = 1; KU_ASSERT(keyVector->state->selVector->selectedSize == 1); // Based on the way we are planning, we assume that the first and second vectors are both @@ -89,19 +80,24 @@ void JoinHashTable::appendVectorWithSorting( auto payloadNodeIDVector = payloadVectors[0]; auto payloadsState = payloadNodeIDVector->state.get(); if (!payloadsState->isFlat()) { - // Sorting is only needed when the payload is unflat (a list of values). + // Sorting is only needed when the payload is unFlat (a list of values). sortSelectedPos(payloadNodeIDVector); } // A single appendInfo will return from `allocateFlatTupleBlocks` when numTuplesToAppend is 1. auto appendInfos = factorizedTable->allocateFlatTupleBlocks(numTuplesToAppend); KU_ASSERT(appendInfos.size() == 1); auto colIdx = 0u; + std::vector keyVectors = {keyVector}; + computeVectorHashes(keyVectors); factorizedTable->copyVectorToColumn(*keyVector, appendInfos[0], numTuplesToAppend, colIdx++); for (auto& vector : payloadVectors) { factorizedTable->copyVectorToColumn(*vector, appendInfos[0], numTuplesToAppend, colIdx++); } + factorizedTable->copyVectorToColumn(*hashVector, appendInfos[0], numTuplesToAppend, colIdx); if (!payloadsState->isFlat()) { - payloadsState->selVector->resetSelectorToUnselected(); + // TODO(Xiyang): I can no longer recall why I set to un-filtered but this is probably wrong. + // We should set back to the un-sorted state. + payloadsState->selVector->setToUnfiltered(); } factorizedTable->numTuples += numTuplesToAppend; } @@ -148,8 +144,8 @@ void JoinHashTable::probe(const std::vector& keyVectors, ValueVect } } -sel_t JoinHashTable::matchFlatKeys( - const std::vector& keyVectors, uint8_t** probedTuples, uint8_t** matchedTuples) { +sel_t JoinHashTable::matchFlatKeys(const std::vector& keyVectors, + uint8_t** probedTuples, uint8_t** matchedTuples) { auto numMatchedTuples = 0; while (probedTuples[0]) { if (numMatchedTuples == DEFAULT_VECTOR_CAPACITY) { @@ -170,8 +166,7 @@ sel_t JoinHashTable::matchUnFlatKey(ValueVector* keyVector, uint8_t** probedTupl auto pos = keyVector->state->selVector->selectedPositions[i]; while (probedTuples[i]) { auto currentTuple = probedTuples[i]; - uint8_t entryCompareResult = false; - entryCompareFunctions[0](*keyVector, pos, currentTuple, entryCompareResult); + auto entryCompareResult = compareEntryFuncs[0](keyVector, pos, currentTuple); if (entryCompareResult) { matchedTuples[numMatchedTuples] = currentTuple; matchedTuplesSelVector->selectedPositions[numMatchedTuples] = pos; @@ -184,16 +179,8 @@ sel_t JoinHashTable::matchUnFlatKey(ValueVector* keyVector, uint8_t** probedTupl return numMatchedTuples; } -uint8_t** JoinHashTable::findHashSlot(uint8_t* tuple) const { - auto idx = 0u; - hash_t hash; - entryHashFunctions[idx++](tuple, hash); - hash_t tmpHash; - while (idx < keyTypes.size()) { - entryHashFunctions[idx](tuple + tableSchema->getColOffset(idx), tmpHash); - function::CombineHash::operation(hash, tmpHash, hash); - idx++; - } +uint8_t** JoinHashTable::findHashSlot(const uint8_t* tuple) const { + auto hash = *(hash_t*)(tuple + getHashValueColOffset()); auto slotIdx = getSlotIdxForHash(hash); return (uint8_t**)(hashSlotsBlocks[slotIdx >> numSlotsPerBlockLog2]->getData() + (slotIdx & slotIdxInBlockMask) * sizeof(uint8_t*)); @@ -206,14 +193,13 @@ uint8_t* JoinHashTable::insertEntry(uint8_t* tuple) const { return prevPtr; } -bool JoinHashTable::compareFlatKeys( - const std::vector& keyVectors, const uint8_t* tuple) { - uint8_t equal = false; +bool JoinHashTable::compareFlatKeys(const std::vector& keyVectors, + const uint8_t* tuple) { for (auto i = 0u; i < keyVectors.size(); i++) { auto keyVector = keyVectors[i]; KU_ASSERT(keyVector->state->selVector->selectedSize == 1); auto pos = keyVector->state->selVector->selectedPositions[0]; - entryCompareFunctions[i](*keyVector, pos, tuple + tableSchema->getColOffset(i), equal); + auto equal = compareEntryFuncs[i](keyVector, pos, tuple + tableSchema->getColOffset(i)); if (!equal) { return false; } @@ -221,125 +207,13 @@ bool JoinHashTable::compareFlatKeys( return true; } -template -static void hashEntry(const uint8_t* entry, hash_t& result) { - Hash::operation(*(T*)entry, result); -} - -void JoinHashTable::getHashFunction(PhysicalTypeID physicalTypeID, hash_function_t& func) { - switch (physicalTypeID) { - case PhysicalTypeID::INTERNAL_ID: { - func = hashEntry; - } break; - case PhysicalTypeID::BOOL: { - func = hashEntry; - } break; - case PhysicalTypeID::INT64: { - func = hashEntry; - } break; - case PhysicalTypeID::INT32: { - func = hashEntry; - } break; - case PhysicalTypeID::INT16: { - func = hashEntry; - } break; - case PhysicalTypeID::INT8: { - func = hashEntry; - } - case PhysicalTypeID::UINT64: { - func = hashEntry; - } - case PhysicalTypeID::UINT32: { - func = hashEntry; - } - case PhysicalTypeID::UINT16: { - func = hashEntry; - } - case PhysicalTypeID::UINT8: { - func = hashEntry; - } - case PhysicalTypeID::INT128: { - func = hashEntry; - } - case PhysicalTypeID::DOUBLE: { - func = hashEntry; - } break; - case PhysicalTypeID::FLOAT: { - func = hashEntry; - } break; - case PhysicalTypeID::STRING: { - func = hashEntry; - } break; - case PhysicalTypeID::INTERVAL: { - func = hashEntry; - } break; - default: { - throw RuntimeException("Join hash table cannot hash data type " + - PhysicalTypeUtils::physicalTypeToString(physicalTypeID)); - } - } -} - -template -static void compareEntry( - const ValueVector& vector, uint32_t pos, const uint8_t* entry, uint8_t& result) { - Equals::operation(vector.getValue(pos), *(T*)entry, result, nullptr /* leftVector */, - nullptr /* rightVector */); +void JoinHashTable::computeVectorHashes(std::vector keyVectors) { + std::vector dummyUnFlatKeyVectors; + BaseHashTable::computeVectorHashes(keyVectors, dummyUnFlatKeyVectors); } -void JoinHashTable::getCompareFunction( - PhysicalTypeID physicalTypeID, JoinHashTable::compare_function_t& func) { - switch (physicalTypeID) { - case PhysicalTypeID::INTERNAL_ID: { - func = compareEntry; - } break; - case PhysicalTypeID::BOOL: { - func = compareEntry; - } break; - case PhysicalTypeID::INT64: { - func = compareEntry; - } break; - case PhysicalTypeID::INT32: { - func = compareEntry; - } break; - case PhysicalTypeID::INT16: { - func = compareEntry; - } break; - case PhysicalTypeID::INT8: { - func = compareEntry; - } - case PhysicalTypeID::UINT64: { - func = compareEntry; - } - case PhysicalTypeID::UINT32: { - func = compareEntry; - } - case PhysicalTypeID::UINT16: { - func = compareEntry; - } - case PhysicalTypeID::UINT8: { - func = compareEntry; - } - case PhysicalTypeID::INT128: { - func = compareEntry; - } - case PhysicalTypeID::DOUBLE: { - func = compareEntry; - } break; - case PhysicalTypeID::FLOAT: { - func = compareEntry; - } break; - case PhysicalTypeID::STRING: { - func = compareEntry; - } break; - case PhysicalTypeID::INTERVAL: { - func = compareEntry; - } break; - default: { - throw RuntimeException("Join hash table cannot compare data type " + - PhysicalTypeUtils::physicalTypeToString(physicalTypeID)); - } - } +offset_t JoinHashTable::getHashValueColOffset() const { + return tableSchema->getColOffset(tableSchema->getNumColumns() - HASH_COL_IDX); } } // namespace processor diff --git a/src/processor/operator/index_lookup.cpp b/src/processor/operator/index_lookup.cpp index 1fa7b89e1d9..669c34c85cc 100644 --- a/src/processor/operator/index_lookup.cpp +++ b/src/processor/operator/index_lookup.cpp @@ -32,8 +32,8 @@ std::unique_ptr IndexLookup::clone() { for (const auto& info : infos) { copiedInfos.push_back(info->copy()); } - return make_unique( - std::move(copiedInfos), children[0]->clone(), getOperatorID(), paramsString); + return make_unique(std::move(copiedInfos), children[0]->clone(), getOperatorID(), + paramsString); } void IndexLookup::setBatchInsertSharedState(std::shared_ptr sharedState) { diff --git a/src/processor/operator/index_scan.cpp b/src/processor/operator/index_scan.cpp index 984262d61e4..c4b0a44f0a5 100644 --- a/src/processor/operator/index_scan.cpp +++ b/src/processor/operator/index_scan.cpp @@ -20,19 +20,21 @@ bool IndexScan::getNextTuplesInternal(ExecutionContext* context) { } saveSelVector(outVector->state->selVector); numSelectedValues = 0u; + auto buffer = outVector->state->selVector->getMultableBuffer(); for (auto i = 0u; i < indexVector->state->selVector->selectedSize; ++i) { auto pos = indexVector->state->selVector->selectedPositions[i]; if (indexVector->isNull(pos)) { continue; } - outVector->state->selVector->getSelectedPositionsBuffer()[numSelectedValues] = pos; + buffer[numSelectedValues] = pos; offset_t nodeOffset = INVALID_OFFSET; - numSelectedValues += pkIndex->lookup(transaction, indexVector, pos, nodeOffset); + numSelectedValues += + pkIndex->lookup(context->clientContext->getTx(), indexVector, pos, nodeOffset); nodeID_t nodeID{nodeOffset, tableID}; outVector->setValue(pos, nodeID); } if (!outVector->state->isFlat() && outVector->state->selVector->isUnfiltered()) { - outVector->state->selVector->resetSelectorToValuePosBuffer(); + outVector->state->selVector->setToFiltered(); } } while (numSelectedValues == 0); outVector->state->selVector->selectedSize = numSelectedValues; diff --git a/src/processor/operator/install_extension.cpp b/src/processor/operator/install_extension.cpp index 3d144866f26..4b7a67d447d 100644 --- a/src/processor/operator/install_extension.cpp +++ b/src/processor/operator/install_extension.cpp @@ -43,8 +43,8 @@ std::string InstallExtension::tryDownloadExtension() { return res->body; } -void InstallExtension::saveExtensionToLocalFile( - const std::string& extensionData, main::ClientContext* context) { +void InstallExtension::saveExtensionToLocalFile(const std::string& extensionData, + main::ClientContext* context) { auto extensionDir = context->getExtensionDir(); auto extensionPath = ExtensionUtils::getExtensionPath(extensionDir, name); auto vfs = context->getVFSUnsafe(); diff --git a/src/processor/operator/intersect/intersect.cpp b/src/processor/operator/intersect/intersect.cpp index 59f7b52ca00..b80ed297136 100644 --- a/src/processor/operator/intersect/intersect.cpp +++ b/src/processor/operator/intersect/intersect.cpp @@ -55,6 +55,8 @@ void Intersect::probeHTs() { void Intersect::twoWayIntersect(nodeID_t* leftNodeIDs, SelectionVector& lSelVector, nodeID_t* rightNodeIDs, SelectionVector& rSelVector) { KU_ASSERT(lSelVector.selectedSize <= rSelVector.selectedSize); + auto leftPositionBuffer = lSelVector.getMultableBuffer(); + auto rightPositionBuffer = rSelVector.getMultableBuffer(); sel_t leftPosition = 0, rightPosition = 0; uint64_t outputValuePosition = 0; while (leftPosition < lSelVector.selectedSize && rightPosition < rSelVector.selectedSize) { @@ -65,16 +67,16 @@ void Intersect::twoWayIntersect(nodeID_t* leftNodeIDs, SelectionVector& lSelVect } else if (leftNodeID.offset > rightNodeID.offset) { rightPosition++; } else { - lSelVector.getSelectedPositionsBuffer()[outputValuePosition] = leftPosition; - rSelVector.getSelectedPositionsBuffer()[outputValuePosition] = rightPosition; + leftPositionBuffer[outputValuePosition] = leftPosition; + rightPositionBuffer[outputValuePosition] = rightPosition; leftNodeIDs[outputValuePosition] = leftNodeID; leftPosition++; rightPosition++; outputValuePosition++; } } - lSelVector.resetSelectorToValuePosBufferWithSize(outputValuePosition); - rSelVector.resetSelectorToValuePosBufferWithSize(outputValuePosition); + lSelVector.setToFiltered(outputValuePosition); + rSelVector.setToFiltered(outputValuePosition); } static std::vector fetchListsToIntersectFromTuples( @@ -105,14 +107,15 @@ static std::vector swapSmallestListToFront(std::vector& selVectorsToSlice, SelectionVector& slicer) { +static void sliceSelVectors(const std::vector& selVectorsToSlice, + SelectionVector& slicer) { for (auto selVec : selVectorsToSlice) { for (auto i = 0u; i < slicer.selectedSize; i++) { auto pos = slicer.selectedPositions[i]; - selVec->getSelectedPositionsBuffer()[i] = selVec->selectedPositions[pos]; + auto buffer = selVec->getMultableBuffer(); + buffer[i] = selVec->selectedPositions[pos]; } - selVec->resetSelectorToValuePosBufferWithSize(slicer.selectedSize); + selVec->setToFiltered(slicer.selectedSize); } } @@ -127,24 +130,23 @@ void Intersect::intersectLists(const std::vector& listsToInter SelectionVector lSelVector(listsToIntersect[0].numElements); lSelVector.selectedSize = listsToIntersect[0].numElements; std::vector selVectorsForIntersectedLists; - intersectSelVectors[0]->resetSelectorToUnselectedWithSize(listsToIntersect[0].numElements); + intersectSelVectors[0]->setToUnfiltered(listsToIntersect[0].numElements); selVectorsForIntersectedLists.push_back(intersectSelVectors[0].get()); for (auto i = 0u; i < listsToIntersect.size() - 1; i++) { - intersectSelVectors[i + 1]->resetSelectorToUnselectedWithSize( - listsToIntersect[i + 1].numElements); + intersectSelVectors[i + 1]->setToUnfiltered(listsToIntersect[i + 1].numElements); twoWayIntersect((nodeID_t*)outKeyVector->getData(), lSelVector, (nodeID_t*)listsToIntersect[i + 1].value, *intersectSelVectors[i + 1]); // Here we need to slice all selVectors that have been previously intersected, as all these // lists need to be selected synchronously to read payloads correctly. sliceSelVectors(selVectorsForIntersectedLists, lSelVector); - lSelVector.resetSelectorToUnselected(); + lSelVector.setToUnfiltered(); selVectorsForIntersectedLists.push_back(intersectSelVectors[i + 1].get()); } outKeyVector->state->selVector->selectedSize = lSelVector.selectedSize; } -void Intersect::populatePayloads( - const std::vector& tuples, const std::vector& listIdxes) { +void Intersect::populatePayloads(const std::vector& tuples, + const std::vector& listIdxes) { for (auto i = 0u; i < listIdxes.size(); i++) { auto listIdx = listIdxes[i]; sharedHTs[listIdx]->getHashTable()->getFactorizedTable()->lookup( diff --git a/src/processor/operator/macro/create_macro.cpp b/src/processor/operator/macro/create_macro.cpp index 11645f9cf12..e3984feedb8 100644 --- a/src/processor/operator/macro/create_macro.cpp +++ b/src/processor/operator/macro/create_macro.cpp @@ -11,8 +11,8 @@ bool CreateMacro::getNextTuplesInternal(kuzu::processor::ExecutionContext* /*con if (hasExecuted) { return false; } - createMacroInfo->catalog->addScalarMacroFunction( - createMacroInfo->macroName, createMacroInfo->macro->copy()); + createMacroInfo->catalog->addScalarMacroFunction(createMacroInfo->macroName, + createMacroInfo->macro->copy()); hasExecuted = true; outputVector->setValue(outputVector->state->selVector->selectedPositions[0], stringFormat("Macro: {} has been created.", createMacroInfo->macroName)); diff --git a/src/processor/operator/order_by/key_block_merger.cpp b/src/processor/operator/order_by/key_block_merger.cpp index 93cff20ed2f..40bfe42712c 100644 --- a/src/processor/operator/order_by/key_block_merger.cpp +++ b/src/processor/operator/order_by/key_block_merger.cpp @@ -7,8 +7,8 @@ using namespace kuzu::storage; namespace kuzu { namespace processor { -MergedKeyBlocks::MergedKeyBlocks( - uint32_t numBytesPerTuple, uint64_t numTuples, MemoryManager* memoryManager) +MergedKeyBlocks::MergedKeyBlocks(uint32_t numBytesPerTuple, uint64_t numTuples, + MemoryManager* memoryManager) : numBytesPerTuple{numBytesPerTuple}, numTuplesPerBlock{(uint32_t)(BufferPoolConstants::PAGE_256KB_SIZE / numBytesPerTuple)}, numTuples{numTuples}, endTupleOffset{numTuplesPerBlock * numBytesPerTuple} { @@ -26,8 +26,8 @@ MergedKeyBlocks::MergedKeyBlocks(uint32_t numBytesPerTuple, std::shared_ptrgetNumTuples() - 1 || - !keyBlockMerger.compareTuplePtr( - leftEndTuplePtr, rightKeyBlock->getTuple(curTupleIdx + 1))) { + !keyBlockMerger.compareTuplePtr(leftEndTuplePtr, + rightKeyBlock->getTuple(curTupleIdx + 1))) { // If the current tuple is the last tuple or the value of next tuple is larger than // the value of leftEndTuple, return the curTupleIdx. return curTupleIdx; @@ -145,8 +145,8 @@ void KeyBlockMerger::mergeKeyBlocks(KeyBlockMergeMorsel& keyBlockMergeMorsel) co keyBlockMergeMorsel.rightKeyBlockEndIdx, keyBlockMergeMorsel.keyBlockMergeTask->rightKeyBlock.get()); - auto resultBlockPtrInfo = BlockPtrInfo( - keyBlockMergeMorsel.leftKeyBlockStartIdx + keyBlockMergeMorsel.rightKeyBlockStartIdx, + auto resultBlockPtrInfo = BlockPtrInfo(keyBlockMergeMorsel.leftKeyBlockStartIdx + + keyBlockMergeMorsel.rightKeyBlockStartIdx, keyBlockMergeMorsel.leftKeyBlockEndIdx + keyBlockMergeMorsel.rightKeyBlockEndIdx, keyBlockMergeMorsel.keyBlockMergeTask->resultKeyBlock.get()); @@ -161,8 +161,8 @@ void KeyBlockMerger::mergeKeyBlocks(KeyBlockMergeMorsel& keyBlockMergeMorsel) co numBytesPerTuple); rightBlockPtrInfo.curTuplePtr += numBytesPerTuple; } else { - memcpy( - resultBlockPtrInfo.curTuplePtr, leftBlockPtrInfo.curTuplePtr, numBytesPerTuple); + memcpy(resultBlockPtrInfo.curTuplePtr, leftBlockPtrInfo.curTuplePtr, + numBytesPerTuple); leftBlockPtrInfo.curTuplePtr += numBytesPerTuple; } resultBlockPtrInfo.curTuplePtr += numBytesPerTuple; @@ -178,8 +178,8 @@ void KeyBlockMerger::mergeKeyBlocks(KeyBlockMergeMorsel& keyBlockMergeMorsel) co // This function returns true if the value in the leftTuplePtr is larger than the value in the // rightTuplePtr. -bool KeyBlockMerger::compareTuplePtrWithStringCol( - uint8_t* leftTuplePtr, uint8_t* rightTuplePtr) const { +bool KeyBlockMerger::compareTuplePtrWithStringCol(uint8_t* leftTuplePtr, + uint8_t* rightTuplePtr) const { // We can't simply use memcmp to compare tuples if there are string columns. // We should only compare the binary strings starting from the last compared string column // till the next string column. @@ -229,10 +229,10 @@ bool KeyBlockMerger::compareTuplePtrWithStringCol( auto& rightFactorizedTable = factorizedTables[OrderByKeyEncoder::getEncodedFTIdx(rightTupleInfo)]; uint8_t result; - auto leftStr = leftFactorizedTable->getData( - leftBlockIdx, leftBlockOffset, strKeyColInfo.colOffsetInFT); - auto rightStr = rightFactorizedTable->getData( - rightBlockIdx, rightBlockOffset, strKeyColInfo.colOffsetInFT); + auto leftStr = leftFactorizedTable->getData(leftBlockIdx, leftBlockOffset, + strKeyColInfo.colOffsetInFT); + auto rightStr = rightFactorizedTable->getData(rightBlockIdx, + rightBlockOffset, strKeyColInfo.colOffsetInFT); result = (leftStr == rightStr); if (result) { // If the tie can't be solved, we need to check the next string column. @@ -250,11 +250,11 @@ bool KeyBlockMerger::compareTuplePtrWithStringCol( return false; } -void KeyBlockMerger::copyRemainingBlockDataToResult( - BlockPtrInfo& blockToCopy, BlockPtrInfo& resultBlock) const { +void KeyBlockMerger::copyRemainingBlockDataToResult(BlockPtrInfo& blockToCopy, + BlockPtrInfo& resultBlock) const { while (blockToCopy.curBlockIdx <= blockToCopy.endBlockIdx) { - uint64_t nextNumBytesToMerge = std::min( - blockToCopy.getNumBytesLeftInCurBlock(), resultBlock.getNumBytesLeftInCurBlock()); + uint64_t nextNumBytesToMerge = std::min(blockToCopy.getNumBytesLeftInCurBlock(), + resultBlock.getNumBytesLeftInCurBlock()); for (auto i = 0u; i < nextNumBytesToMerge; i += numBytesPerTuple) { memcpy(resultBlock.curTuplePtr, blockToCopy.curTuplePtr, numBytesPerTuple); blockToCopy.curTuplePtr += numBytesPerTuple; @@ -284,8 +284,8 @@ std::unique_ptr KeyBlockMergeTaskDispatcher::getMorsel() { sortedKeyBlocks->pop(); auto resultKeyBlock = std::make_shared(leftKeyBlock->getNumBytesPerTuple(), leftKeyBlock->getNumTuples() + rightKeyBlock->getNumTuples(), memoryManager); - auto newMergeTask = std::make_shared( - leftKeyBlock, rightKeyBlock, resultKeyBlock, *keyBlockMerger); + auto newMergeTask = std::make_shared(leftKeyBlock, rightKeyBlock, + resultKeyBlock, *keyBlockMerger); activeKeyBlockMergeTasks.emplace_back(newMergeTask); auto morsel = newMergeTask->getMorsel(); morsel->keyBlockMergeTask = newMergeTask; @@ -315,8 +315,8 @@ void KeyBlockMergeTaskDispatcher::init(MemoryManager* memoryManager, KU_ASSERT(this->keyBlockMerger == nullptr); this->memoryManager = memoryManager; this->sortedKeyBlocks = sortedKeyBlocks; - this->keyBlockMerger = std::make_unique( - std::move(factorizedTables), strKeyColsInfo, numBytesPerTuple); + this->keyBlockMerger = std::make_unique(std::move(factorizedTables), + strKeyColsInfo, numBytesPerTuple); } } // namespace processor diff --git a/src/processor/operator/order_by/order_by_key_encoder.cpp b/src/processor/operator/order_by/order_by_key_encoder.cpp index cb423c34022..0d00e6f09b8 100644 --- a/src/processor/operator/order_by/order_by_key_encoder.cpp +++ b/src/processor/operator/order_by/order_by_key_encoder.cpp @@ -81,8 +81,8 @@ uint32_t OrderByKeyEncoder::getEncodingSize(const LogicalType& dataType) { } } -void OrderByKeyEncoder::flipBytesIfNecessary( - uint32_t keyColIdx, uint8_t* tuplePtr, uint32_t numEntriesToEncode, LogicalType& type) { +void OrderByKeyEncoder::flipBytesIfNecessary(uint32_t keyColIdx, uint8_t* tuplePtr, + uint32_t numEntriesToEncode, LogicalType& type) { if (!isAscOrder[keyColIdx]) { auto encodingSize = getEncodingSize(type); // If the current column is in desc order, flip all bytes. @@ -95,8 +95,8 @@ void OrderByKeyEncoder::flipBytesIfNecessary( } } -void OrderByKeyEncoder::encodeFlatVector( - ValueVector* vector, uint8_t* tuplePtr, uint32_t keyColIdx) { +void OrderByKeyEncoder::encodeFlatVector(ValueVector* vector, uint8_t* tuplePtr, + uint32_t keyColIdx) { auto pos = vector->state->selVector->selectedPositions[0]; if (vector->isNull(pos)) { for (auto j = 0u; j < getEncodingSize(vector->dataType); j++) { @@ -104,8 +104,8 @@ void OrderByKeyEncoder::encodeFlatVector( } } else { *tuplePtr = 0; - encodeFunctions[keyColIdx]( - vector->getData() + pos * vector->getNumBytesPerValue(), tuplePtr + 1, swapBytes); + encodeFunctions[keyColIdx](vector->getData() + pos * vector->getNumBytesPerValue(), + tuplePtr + 1, swapBytes); } } @@ -154,9 +154,9 @@ void OrderByKeyEncoder::encodeUnflatVector(ValueVector* vector, uint8_t* tuplePt } } else { *tuplePtr = 0; - encodeFunctions[keyColIdx]( - vector->getData() + pos * vector->getNumBytesPerValue(), tuplePtr + 1, - swapBytes); + encodeFunctions[keyColIdx](vector->getData() + + pos * vector->getNumBytesPerValue(), + tuplePtr + 1, swapBytes); } tuplePtr += numBytesPerTuple; } @@ -177,8 +177,8 @@ void OrderByKeyEncoder::encodeVector(ValueVector* vector, uint8_t* tuplePtr, uin void OrderByKeyEncoder::encodeFTIdx(uint32_t numEntriesToEncode, uint8_t* tupleInfoPtr) { uint32_t numUpdatedFTInfoEntries = 0; while (numUpdatedFTInfoEntries < numEntriesToEncode) { - auto nextBatchOfEntries = std::min( - numEntriesToEncode - numUpdatedFTInfoEntries, numTuplesPerBlockInFT - ftBlockOffset); + auto nextBatchOfEntries = std::min(numEntriesToEncode - numUpdatedFTInfoEntries, + numTuplesPerBlockInFT - ftBlockOffset); for (auto i = 0u; i < nextBatchOfEntries; i++) { *(uint32_t*)tupleInfoPtr = ftBlockIdx; *(uint32_t*)(tupleInfoPtr + 4) = ftBlockOffset; diff --git a/src/processor/operator/order_by/order_by_scan.cpp b/src/processor/operator/order_by/order_by_scan.cpp index 3910e4d663e..3c930f14ec7 100644 --- a/src/processor/operator/order_by/order_by_scan.cpp +++ b/src/processor/operator/order_by/order_by_scan.cpp @@ -5,13 +5,18 @@ using namespace kuzu::common; namespace kuzu { namespace processor { -void OrderByScanLocalState::init( - std::vector& outVectorPos, SortSharedState& sharedState, ResultSet& resultSet) { +void OrderByScanLocalState::init(std::vector& outVectorPos, SortSharedState& sharedState, + ResultSet& resultSet) { for (auto& dataPos : outVectorPos) { vectorsToRead.push_back(resultSet.getValueVector(dataPos).get()); } - payloadScanner = std::make_unique( - sharedState.getMergedKeyBlock(), sharedState.getPayloadTables()); + payloadScanner = std::make_unique(sharedState.getMergedKeyBlock(), + sharedState.getPayloadTables()); + numTuples = 0; + for (auto& table : sharedState.getPayloadTables()) { + numTuples += table->getNumTuples(); + } + numTuplesRead = 0; } void OrderByScan::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* /*context*/) { @@ -25,5 +30,14 @@ bool OrderByScan::getNextTuplesInternal(ExecutionContext* /*context*/) { return numTuplesRead != 0; } +double OrderByScan::getProgress(ExecutionContext* /*context*/) const { + if (localState->numTuples == 0) { + return 0.0; + } else if (localState->numTuplesRead == localState->numTuples) { + return 1.0; + } + return static_cast(localState->numTuplesRead) / localState->numTuples; +} + } // namespace processor } // namespace kuzu diff --git a/src/processor/operator/order_by/radix_sort.cpp b/src/processor/operator/order_by/radix_sort.cpp index 18ab1d7f0ca..4e19cf4103a 100644 --- a/src/processor/operator/order_by/radix_sort.cpp +++ b/src/processor/operator/order_by/radix_sort.cpp @@ -58,11 +58,10 @@ void RadixSort::radixSort(uint8_t* keyBlockPtr, uint32_t numTuplesToSort, uint32 auto tmpKeyBlockPtr = tmpSortingResultBlock->getData(); keyBlockPtr += numBytesSorted; tmpKeyBlockPtr += numBytesSorted; - constexpr uint16_t countingArraySize = 256; - uint32_t count[countingArraySize]; + uint32_t count[COUNTING_ARRAY_SIZE]; auto isInTmpBlock = false; for (auto curByteIdx = 1ul; curByteIdx <= numBytesToSort; curByteIdx++) { - memset(count, 0, countingArraySize * sizeof(uint32_t)); + memset(count, 0, COUNTING_ARRAY_SIZE * sizeof(uint32_t)); auto sourcePtr = isInTmpBlock ? tmpKeyBlockPtr : keyBlockPtr; auto targetPtr = isInTmpBlock ? keyBlockPtr : tmpKeyBlockPtr; auto curByteOffset = numBytesToSort - curByteIdx; @@ -73,7 +72,7 @@ void RadixSort::radixSort(uint8_t* keyBlockPtr, uint32_t numTuplesToSort, uint32 sortBytePtr += numBytesPerTuple; } auto maxCounter = count[0]; - for (auto val = 1ul; val < countingArraySize; val++) { + for (auto val = 1ul; val < COUNTING_ARRAY_SIZE; val++) { maxCounter = std::max(count[val], maxCounter); count[val] = count[val] + count[val - 1]; } @@ -85,14 +84,16 @@ void RadixSort::radixSort(uint8_t* keyBlockPtr, uint32_t numTuplesToSort, uint32 auto sourceTuplePtr = sourcePtr + (numTuplesToSort - 1) * numBytesPerTuple; for (auto j = 0ul; j < numTuplesToSort; j++) { auto targetTupleNum = --count[*(sourceTuplePtr + curByteOffset)]; - memcpy(targetPtr + targetTupleNum * numBytesPerTuple, sourceTuplePtr, numBytesPerTuple); + memcpy(targetPtr + targetTupleNum * numBytesPerTuple - numBytesSorted, + sourceTuplePtr - numBytesSorted, numBytesPerTuple); sourceTuplePtr -= numBytesPerTuple; } isInTmpBlock = !isInTmpBlock; } // If the data is in the tmp block, copy the data from tmp block back. if (isInTmpBlock) { - memcpy(keyBlockPtr, tmpKeyBlockPtr, numTuplesToSort * numBytesPerTuple); + memcpy(keyBlockPtr - numBytesSorted, tmpKeyBlockPtr - numBytesSorted, + numTuplesToSort * numBytesPerTuple); } } @@ -256,10 +257,10 @@ void RadixSort::solveStringTies(TieRange& keyBlockTie, uint8_t* keyBlockPtr, const auto rightBlockIdx = OrderByKeyEncoder::getEncodedFTBlockIdx(rightTupleInfoPtr); const auto rightBlockOffset = OrderByKeyEncoder::getEncodedFTBlockOffset(rightTupleInfoPtr); - auto leftStr = factorizedTable.getData( - leftBlockIdx, leftBlockOffset, keyColInfo.colOffsetInFT); - auto rightStr = factorizedTable.getData( - rightBlockIdx, rightBlockOffset, keyColInfo.colOffsetInFT); + auto leftStr = factorizedTable.getData(leftBlockIdx, leftBlockOffset, + keyColInfo.colOffsetInFT); + auto rightStr = factorizedTable.getData(rightBlockIdx, rightBlockOffset, + keyColInfo.colOffsetInFT); return keyColInfo.isAscOrder ? leftStr < rightStr : leftStr > rightStr; }); reOrderKeyBlock(keyBlockTie, keyBlockPtr); diff --git a/src/processor/operator/order_by/sort_state.cpp b/src/processor/operator/order_by/sort_state.cpp index 1e1bfd7a918..08ffeff0f9c 100644 --- a/src/processor/operator/order_by/sort_state.cpp +++ b/src/processor/operator/order_by/sort_state.cpp @@ -60,8 +60,8 @@ void SortLocalState::init(const OrderByDataInfo& orderByDataInfo, SortSharedStat payloadTable = table; orderByKeyEncoder = std::make_unique(orderByDataInfo, memoryManager, globalIdx, payloadTable->getNumTuplesPerBlock(), sharedState.getNumBytesPerTuple()); - radixSorter = std::make_unique( - memoryManager, *payloadTable, *orderByKeyEncoder, sharedState.getStrKeyColInfo()); + radixSorter = std::make_unique(memoryManager, *payloadTable, *orderByKeyEncoder, + sharedState.getStrKeyColInfo()); } void SortLocalState::append(const std::vector& keyVectors, @@ -83,8 +83,8 @@ void SortLocalState::finalize(kuzu::processor::SortSharedState& sharedState) { PayloadScanner::PayloadScanner(MergedKeyBlocks* keyBlockToScan, std::vector payloadTables, uint64_t skipNumber, uint64_t limitNumber) - : keyBlockToScan{keyBlockToScan}, payloadTables{std::move(payloadTables)}, limitNumber{ - limitNumber} { + : keyBlockToScan{keyBlockToScan}, payloadTables{std::move(payloadTables)}, + limitNumber{limitNumber} { if (this->keyBlockToScan == nullptr || this->keyBlockToScan->getNumTuples() == 0) { nextTupleIdxToReadInMergedKeyBlock = 0; endTuplesIdxToReadInMergedKeyBlock = 0; @@ -129,8 +129,8 @@ uint64_t PayloadScanner::scan(std::vector vectorsToRead) { endTuplesIdxToReadInMergedKeyBlock - nextTupleIdxToReadInMergedKeyBlock); auto numTuplesRead = 0u; while (numTuplesRead < numTuplesToRead) { - auto numTuplesToReadInCurBlock = std::min( - numTuplesToRead - numTuplesRead, blockPtrInfo->getNumTuplesLeftInCurBlock()); + auto numTuplesToReadInCurBlock = std::min(numTuplesToRead - numTuplesRead, + blockPtrInfo->getNumTuplesLeftInCurBlock()); for (auto i = 0u; i < numTuplesToReadInCurBlock; i++) { auto payloadInfo = blockPtrInfo->curTuplePtr + payloadIdxOffset; auto blockIdx = OrderByKeyEncoder::getEncodedFTBlockIdx(payloadInfo); diff --git a/src/processor/operator/order_by/top_k.cpp b/src/processor/operator/order_by/top_k.cpp index c323f308419..2484b8dc067 100644 --- a/src/processor/operator/order_by/top_k.cpp +++ b/src/processor/operator/order_by/top_k.cpp @@ -13,8 +13,8 @@ TopKSortState::TopKSortState() : numTuples{0}, memoryManager{nullptr} { orderBySharedState = std::make_unique(); } -void TopKSortState::init( - const OrderByDataInfo& orderByDataInfo, storage::MemoryManager* memoryManager) { +void TopKSortState::init(const OrderByDataInfo& orderByDataInfo, + storage::MemoryManager* memoryManager) { this->memoryManager = memoryManager; orderBySharedState->init(orderByDataInfo); orderByLocalState->init(orderByDataInfo, *orderBySharedState, memoryManager); @@ -42,8 +42,8 @@ void TopKSortState::finalize() { } } -void TopKBuffer::init( - storage::MemoryManager* memoryManager, uint64_t skipNumber, uint64_t limitNumber) { +void TopKBuffer::init(storage::MemoryManager* memoryManager, uint64_t skipNumber, + uint64_t limitNumber) { this->memoryManager = memoryManager; sortState->init(*orderByDataInfo, memoryManager); this->skip = skipNumber; @@ -132,8 +132,8 @@ void TopKBuffer::initVectors() { } template -void TopKBuffer::getSelectComparisonFunction( - common::PhysicalTypeID typeID, vector_select_comparison_func& selectFunc) { +void TopKBuffer::getSelectComparisonFunction(common::PhysicalTypeID typeID, + vector_select_comparison_func& selectFunc) { switch (typeID) { case common::PhysicalTypeID::INT64: { selectFunc = function::BinaryFunctionExecutor::selectComparison; @@ -209,13 +209,12 @@ bool TopKBuffer::compareBoundaryValue(const std::vector& k } } -bool TopKBuffer::compareFlatKeys( - vector_idx_t vectorIdxToCompare, std::vector keyVectors) { - std::shared_ptr selVector = - std::make_shared(common::DEFAULT_VECTOR_CAPACITY); - selVector->resetSelectorToValuePosBuffer(); - auto compareResult = compareFuncs[vectorIdxToCompare]( - *keyVectors[vectorIdxToCompare], *boundaryVecs[vectorIdxToCompare], *selVector); +bool TopKBuffer::compareFlatKeys(vector_idx_t vectorIdxToCompare, + std::vector keyVectors) { + auto selVector = std::make_shared(common::DEFAULT_VECTOR_CAPACITY); + selVector->setToFiltered(); + auto compareResult = compareFuncs[vectorIdxToCompare](*keyVectors[vectorIdxToCompare], + *boundaryVecs[vectorIdxToCompare], *selVector); if (vectorIdxToCompare == keyVectors.size() - 1) { return compareResult; } else if (equalsFuncs[vectorIdxToCompare](*keyVectors[vectorIdxToCompare], @@ -226,17 +225,17 @@ bool TopKBuffer::compareFlatKeys( } } -void TopKBuffer::compareUnflatKeys( - vector_idx_t vectorIdxToCompare, std::vector keyVectors) { +void TopKBuffer::compareUnflatKeys(vector_idx_t vectorIdxToCompare, + std::vector keyVectors) { auto compareSelVector = std::make_shared(common::DEFAULT_VECTOR_CAPACITY); - compareSelVector->resetSelectorToValuePosBuffer(); - compareFuncs[vectorIdxToCompare]( - *keyVectors[vectorIdxToCompare], *boundaryVecs[vectorIdxToCompare], *compareSelVector); + compareSelVector->setToFiltered(); + compareFuncs[vectorIdxToCompare](*keyVectors[vectorIdxToCompare], + *boundaryVecs[vectorIdxToCompare], *compareSelVector); if (vectorIdxToCompare != keyVectors.size() - 1) { auto equalsSelVector = std::make_shared(common::DEFAULT_VECTOR_CAPACITY); - equalsSelVector->resetSelectorToValuePosBuffer(); + equalsSelVector->setToFiltered(); if (equalsFuncs[vectorIdxToCompare](*keyVectors[vectorIdxToCompare], *boundaryVecs[vectorIdxToCompare], *equalsSelVector)) { keyVectors[vectorIdxToCompare]->state->selVector = equalsSelVector; @@ -247,8 +246,8 @@ void TopKBuffer::compareUnflatKeys( keyVectors[vectorIdxToCompare]->state->selVector = std::move(compareSelVector); } -void TopKBuffer::appendSelState( - common::SelectionVector* selVector, common::SelectionVector* selVectorToAppend) { +void TopKBuffer::appendSelState(common::SelectionVector* selVector, + common::SelectionVector* selVectorToAppend) { for (auto i = 0u; i < selVectorToAppend->selectedSize; i++) { selVector->selectedPositions[selVector->selectedSize + i] = selVectorToAppend->selectedPositions[i]; @@ -272,8 +271,8 @@ void TopKLocalState::append(const std::vector& keyVectors, void TopK::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { localState = std::make_unique(); - localState->init( - *info, context->clientContext->getMemoryManager(), *resultSet, skipNumber, limitNumber); + localState->init(*info, context->clientContext->getMemoryManager(), *resultSet, skipNumber, + limitNumber); for (auto& dataPos : info->payloadsPos) { payloadVectors.push_back(resultSet->getValueVector(dataPos).get()); } diff --git a/src/processor/operator/order_by/top_k_scanner.cpp b/src/processor/operator/order_by/top_k_scanner.cpp index b4c8d1c46e6..4e164fdd4b4 100644 --- a/src/processor/operator/order_by/top_k_scanner.cpp +++ b/src/processor/operator/order_by/top_k_scanner.cpp @@ -3,16 +3,16 @@ namespace kuzu { namespace processor { -void TopKLocalScanState::init( - std::vector& outVectorPos, TopKSharedState& sharedState, ResultSet& resultSet) { +void TopKLocalScanState::init(std::vector& outVectorPos, TopKSharedState& sharedState, + ResultSet& resultSet) { for (auto& pos : outVectorPos) { vectorsToScan.push_back(resultSet.getValueVector(pos).get()); } payloadScanner = sharedState.buffer->getScanner(); } -void TopKScan::initLocalStateInternal( - kuzu::processor::ResultSet* resultSet, kuzu::processor::ExecutionContext* /*context*/) { +void TopKScan::initLocalStateInternal(kuzu::processor::ResultSet* resultSet, + kuzu::processor::ExecutionContext* /*context*/) { localState->init(outVectorPos, *sharedState, *resultSet); } diff --git a/src/processor/operator/partitioner.cpp b/src/processor/operator/partitioner.cpp index 8db8df79e23..3f78f582c41 100644 --- a/src/processor/operator/partitioner.cpp +++ b/src/processor/operator/partitioner.cpp @@ -1,5 +1,8 @@ #include "processor/operator/partitioner.h" +#include "common/constants.h" +#include "common/data_chunk/sel_vector.h" +#include "processor/execution_context.h" #include "storage/store/node_table.h" using namespace kuzu::common; @@ -29,11 +32,11 @@ std::vector> PartitioningInfo::copy( return result; } -static common::partition_idx_t getNumPartitions(offset_t maxOffset) { +static partition_idx_t getNumPartitions(offset_t maxOffset) { return (maxOffset + StorageConstants::NODE_GROUP_SIZE) / StorageConstants::NODE_GROUP_SIZE; } -void PartitionerSharedState::initialize() { +void PartitionerSharedState::initialize(std::vector>& infos) { maxNodeOffsets.resize(2); maxNodeOffsets[0] = srcNodeTable->getMaxNodeOffset(transaction::Transaction::getDummyWriteTrx().get()); @@ -42,7 +45,7 @@ void PartitionerSharedState::initialize() { numPartitions.resize(2); numPartitions[0] = getNumPartitions(maxNodeOffsets[0]); numPartitions[1] = getNumPartitions(maxNodeOffsets[1]); - Partitioner::initializePartitioningStates(partitioningBuffers, numPartitions, mm); + Partitioner::initializePartitioningStates(infos, partitioningBuffers, numPartitions); } partition_idx_t PartitionerSharedState::getNextPartition(vector_idx_t partitioningIdx) { @@ -71,9 +74,9 @@ void PartitionerSharedState::merge( void PartitioningBuffer::merge(std::unique_ptr localPartitioningState) { KU_ASSERT(partitions.size() == localPartitioningState->partitions.size()); for (auto partitionIdx = 0u; partitionIdx < partitions.size(); partitionIdx++) { - auto sharedPartition = partitions[partitionIdx].get(); - auto localPartition = localPartitioningState->partitions[partitionIdx].get(); - sharedPartition->merge(localPartition); + auto& sharedPartition = partitions[partitionIdx]; + auto& localPartition = localPartitioningState->partitions[partitionIdx]; + sharedPartition.merge(localPartition); } } @@ -88,40 +91,43 @@ Partitioner::Partitioner(std::unique_ptr resultSetDescripto } void Partitioner::initGlobalStateInternal(ExecutionContext* /*context*/) { - sharedState->initialize(); + sharedState->initialize(infos); } -void Partitioner::initLocalStateInternal(ResultSet* /*resultSet*/, ExecutionContext* context) { +void Partitioner::initLocalStateInternal(ResultSet* /*resultSet*/, ExecutionContext* /*context*/) { localState = std::make_unique(); - initializePartitioningStates(localState->partitioningBuffers, sharedState->numPartitions, - context->clientContext->getMemoryManager()); + initializePartitioningStates(infos, localState->partitioningBuffers, + sharedState->numPartitions); } -static void constructDataChunk(DataChunk* dataChunk, const std::vector& columnPositions, - const logical_types_t& columnTypes, const ResultSet& resultSet) { +DataChunk Partitioner::constructDataChunk(const std::vector& columnPositions, + const std::vector& columnTypes, const ResultSet& resultSet, + const std::shared_ptr& state) { + DataChunk dataChunk(columnTypes.size(), state); for (auto i = 0u; i < columnPositions.size(); i++) { auto pos = columnPositions[i]; if (pos.isValid()) { - dataChunk->insert(i, resultSet.getValueVector(pos)); + dataChunk.insert(i, resultSet.getValueVector(pos)); } else { - auto columnType = columnTypes[i].get(); - auto nullVector = std::make_shared(*columnType); + auto nullVector = std::make_shared(columnTypes[i]); nullVector->setAllNull(); - dataChunk->insert(i, nullVector); + dataChunk.insert(i, nullVector); } } + return dataChunk; } void Partitioner::initializePartitioningStates( + std::vector>& infos, std::vector>& partitioningBuffers, - std::vector numPartitions, MemoryManager* mm) { + std::vector numPartitions) { partitioningBuffers.resize(numPartitions.size()); for (auto partitioningIdx = 0u; partitioningIdx < numPartitions.size(); partitioningIdx++) { auto numPartition = numPartitions[partitioningIdx]; auto partitioningBuffer = std::make_unique(); partitioningBuffer->partitions.reserve(numPartition); for (auto i = 0u; i < numPartition; i++) { - partitioningBuffer->partitions.push_back(std::make_unique(mm)); + partitioningBuffer->partitions.emplace_back(infos[partitioningIdx]->columnTypes); } partitioningBuffers[partitioningIdx] = std::move(partitioningBuffer); } @@ -134,30 +140,31 @@ void Partitioner::executeInternal(ExecutionContext* context) { auto keyVector = resultSet->getValueVector(info->keyDataPos); partitionIdxes->state = resultSet->getValueVector(info->keyDataPos)->state; info->partitionerFunc(keyVector.get(), partitionIdxes.get()); - auto columnDataChunk = - std::make_unique(info->columnTypes.size(), keyVector->state); - constructDataChunk( - columnDataChunk.get(), info->columnDataPositions, info->columnTypes, *resultSet); - copyDataToPartitions(partitioningIdx, columnDataChunk.get()); + auto chunkToCopyFrom = constructDataChunk(info->columnDataPositions, info->columnTypes, + *resultSet, keyVector->state); + copyDataToPartitions(partitioningIdx, std::move(chunkToCopyFrom)); } } sharedState->merge(std::move(localState->partitioningBuffers)); } -void Partitioner::copyDataToPartitions( - partition_idx_t partitioningIdx, DataChunk* chunkToCopyFrom) { - auto originalChunkState = chunkToCopyFrom->state; - chunkToCopyFrom->state = std::make_shared(1 /* capacity */); - chunkToCopyFrom->state->selVector->resetSelectorToValuePosBufferWithSize(1 /* size */); - for (auto i = 0u; i < originalChunkState->selVector->selectedSize; i++) { - auto posToCopyFrom = originalChunkState->selVector->selectedPositions[i]; +void Partitioner::copyDataToPartitions(partition_idx_t partitioningIdx, DataChunk chunkToCopyFrom) { + std::vector vectorsToAppend; + vectorsToAppend.reserve(chunkToCopyFrom.getNumValueVectors()); + for (auto j = 0u; j < chunkToCopyFrom.getNumValueVectors(); j++) { + vectorsToAppend.push_back(chunkToCopyFrom.getValueVector(j).get()); + } + SelectionVector selVector(1); + selVector.setToFiltered(1); + for (auto i = 0u; i < chunkToCopyFrom.state->selVector->selectedSize; i++) { + auto posToCopyFrom = chunkToCopyFrom.state->selVector->selectedPositions[i]; auto partitionIdx = partitionIdxes->getValue(posToCopyFrom); KU_ASSERT( partitionIdx < localState->getPartitioningBuffer(partitioningIdx)->partitions.size()); - auto partition = - localState->getPartitioningBuffer(partitioningIdx)->partitions[partitionIdx].get(); - chunkToCopyFrom->state->selVector->selectedPositions[0] = posToCopyFrom; - partition->append(*chunkToCopyFrom); + auto& partition = + localState->getPartitioningBuffer(partitioningIdx)->partitions[partitionIdx]; + selVector.selectedPositions[0] = posToCopyFrom; + partition.append(vectorsToAppend, selVector); } } diff --git a/src/processor/operator/persistent/batch_insert.cpp b/src/processor/operator/persistent/batch_insert.cpp index 37e36cd3453..1511e42769a 100644 --- a/src/processor/operator/persistent/batch_insert.cpp +++ b/src/processor/operator/persistent/batch_insert.cpp @@ -9,7 +9,7 @@ namespace kuzu { namespace processor { void BatchInsert::checkIfTableIsEmpty() { - if (sharedState->table->getNumTuples() != 0) { + if (sharedState->table->getNumTuples(&transaction::DUMMY_READ_TRANSACTION) != 0) { throw CopyException(ExceptionMessage::notAllowCopyOnNonEmptyTableException()); } } diff --git a/src/processor/operator/persistent/copy_rdf.cpp b/src/processor/operator/persistent/copy_rdf.cpp index ab4f3b0acad..e2a5e9701e4 100644 --- a/src/processor/operator/persistent/copy_rdf.cpp +++ b/src/processor/operator/persistent/copy_rdf.cpp @@ -8,8 +8,8 @@ namespace processor { void CopyRdf::finalize(ExecutionContext* context) { auto outputMsg = common::stringFormat("Done copy rdf."); - FactorizedTableUtils::appendStringToTable( - sharedState->fTable.get(), outputMsg, context->clientContext->getMemoryManager()); + FactorizedTableUtils::appendStringToTable(sharedState->fTable.get(), outputMsg, + context->clientContext->getMemoryManager()); } } // namespace processor diff --git a/src/processor/operator/persistent/copy_to_csv.cpp b/src/processor/operator/persistent/copy_to_csv.cpp index 4d80e982b26..534da31d68a 100644 --- a/src/processor/operator/persistent/copy_to_csv.cpp +++ b/src/processor/operator/persistent/copy_to_csv.cpp @@ -34,8 +34,8 @@ void CopyToCSVLocalState::init(CopyToInfo* info, MemoryManager* mm, ResultSet* r castFuncs.resize(info->dataPoses.size()); for (auto i = 0u; i < info->dataPoses.size(); i++) { auto vectorToCast = resultSet->getValueVector(info->dataPoses[i]); - castFuncs[i] = function::CastFunction::bindCastFunction( - "cast", vectorToCast->dataType.getLogicalTypeID(), LogicalTypeID::STRING) + castFuncs[i] = function::CastFunction::bindCastFunction("cast", + vectorToCast->dataType.getLogicalTypeID(), LogicalTypeID::STRING) ->execFunc; vectorsToCast.push_back(std::move(vectorToCast)); auto castVector = std::make_unique(LogicalTypeID::STRING, mm); @@ -104,8 +104,8 @@ void CopyToCSVLocalState::writeString(common::BufferedSerializer* serializer, } } -bool CopyToCSVLocalState::requireQuotes( - CopyToCSVInfo* copyToCsvInfo, const uint8_t* str, uint64_t len) { +bool CopyToCSVLocalState::requireQuotes(CopyToCSVInfo* copyToCsvInfo, const uint8_t* str, + uint64_t len) { // Check if the string is equal to the null string. if (len == strlen(CopyToCSVConstants::DEFAULT_NULL_STR) && memcmp(str, CopyToCSVConstants::DEFAULT_NULL_STR, len) == 0) { @@ -167,10 +167,10 @@ void CopyToCSVLocalState::writeRows(CopyToCSVInfo* copyToCsvInfo) { continue; } auto strValue = vector->getValue(pos); - // Note: we need blindly add quotes to VAR_LIST. + // Note: we need blindly add quotes to LIST. writeString(serializer.get(), copyToCsvInfo, strValue.getData(), strValue.len, CopyToCSVConstants::DEFAULT_FORCE_QUOTE || - vectorsToCast[j]->dataType.getLogicalTypeID() == LogicalTypeID::VAR_LIST); + vectorsToCast[j]->dataType.getLogicalTypeID() == LogicalTypeID::LIST); } serializer->writeBufferData(CopyToCSVConstants::DEFAULT_CSV_NEWLINE); } diff --git a/src/processor/operator/persistent/copy_to_parquet.cpp b/src/processor/operator/persistent/copy_to_parquet.cpp index d74e9884b36..58f32753d23 100644 --- a/src/processor/operator/persistent/copy_to_parquet.cpp +++ b/src/processor/operator/persistent/copy_to_parquet.cpp @@ -6,11 +6,14 @@ namespace processor { using namespace kuzu::common; using namespace kuzu::storage; -void CopyToParquetLocalState::init( - CopyToInfo* info, storage::MemoryManager* mm, ResultSet* resultSet) { +void CopyToParquetLocalState::init(CopyToInfo* info, storage::MemoryManager* mm, + ResultSet* resultSet) { auto copyToInfo = reinterpret_cast(info); ft = std::make_unique(mm, std::move(copyToInfo->tableSchema)); + numTuplesInFT = 0; + countingVec = nullptr; vectorsToAppend.reserve(info->dataPoses.size()); + countingVec = resultSet->getValueVector(copyToInfo->countingVecPos).get(); for (auto& pos : info->dataPoses) { vectorsToAppend.push_back(resultSet->getValueVector(pos).get()); } @@ -19,8 +22,10 @@ void CopyToParquetLocalState::init( void CopyToParquetLocalState::sink(CopyToSharedState* sharedState, CopyToInfo* /*info*/) { ft->append(vectorsToAppend); - if (ft->getTotalNumFlatTuples() > StorageConstants::NODE_GROUP_SIZE) { + numTuplesInFT += countingVec->state->selVector->selectedSize; + if (numTuplesInFT > StorageConstants::NODE_GROUP_SIZE) { reinterpret_cast(sharedState)->flush(*ft); + numTuplesInFT = 0; } } diff --git a/src/processor/operator/persistent/delete.cpp b/src/processor/operator/persistent/delete.cpp index e500a2f3568..d4117a8c9c0 100644 --- a/src/processor/operator/persistent/delete.cpp +++ b/src/processor/operator/persistent/delete.cpp @@ -25,8 +25,8 @@ std::unique_ptr DeleteNode::clone() { for (auto& executor : executors) { executorsCopy.push_back(executor->copy()); } - return std::make_unique( - std::move(executorsCopy), children[0]->clone(), id, paramsString); + return std::make_unique(std::move(executorsCopy), children[0]->clone(), id, + paramsString); } void DeleteRel::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { @@ -51,8 +51,8 @@ std::unique_ptr DeleteRel::clone() { for (auto& executor : executors) { executorsCopy.push_back(executor->copy()); } - return std::make_unique( - std::move(executorsCopy), children[0]->clone(), id, paramsString); + return std::make_unique(std::move(executorsCopy), children[0]->clone(), id, + paramsString); } } // namespace processor diff --git a/src/processor/operator/persistent/delete_executor.cpp b/src/processor/operator/persistent/delete_executor.cpp index 59abfe16a75..1b62030fc13 100644 --- a/src/processor/operator/persistent/delete_executor.cpp +++ b/src/processor/operator/persistent/delete_executor.cpp @@ -26,8 +26,8 @@ static void deleteFromRelTable(ExecutionContext* context, DeleteNodeType deleteT RelDetachDeleteState* detachDeleteState) { switch (deleteType) { case DeleteNodeType::DETACH_DELETE: { - relTable->detachDelete( - context->clientContext->getTx(), direction, nodeIDVector, detachDeleteState); + relTable->detachDelete(context->clientContext->getTx(), direction, nodeIDVector, + detachDeleteState); } break; case DeleteNodeType::DELETE: { relTable->checkIfNodeHasRels(context->clientContext->getTx(), direction, nodeIDVector); @@ -53,7 +53,8 @@ void SingleLabelNodeDeleteExecutor::delete_(ExecutionContext* context) { deleteFromRelTable(context, deleteType, RelDataDirection::BWD, relTable, nodeIDVector, detachDeleteState.get()); } - table->delete_(context->clientContext->getTx(), nodeIDVector, pkVector.get()); + auto deleteState = std::make_unique(*nodeIDVector, *pkVector); + table->delete_(context->clientContext->getTx(), *deleteState); } void MultiLabelNodeDeleteExecutor::init(ResultSet* resultSet, ExecutionContext* context) { @@ -82,11 +83,18 @@ void MultiLabelNodeDeleteExecutor::delete_(ExecutionContext* context) { detachDeleteState.get()); } for (auto& relTable : bwdRelTables) { + // TODO(Guodong): For detach delete, there can possibly be a case where the same relTable is + // in both fwd and bwd rel tables set. the rels can be deleted twice. This is a temporary + // hack. + if (deleteType == DeleteNodeType::DETACH_DELETE && fwdRelTables.contains(relTable)) { + continue; + } deleteFromRelTable(context, deleteType, RelDataDirection::BWD, relTable, nodeIDVector, detachDeleteState.get()); } - table->delete_( - context->clientContext->getTx(), nodeIDVector, pkVectors.at(nodeID.tableID).get()); + auto deleteState = std::make_unique(*nodeIDVector, + *pkVectors.at(nodeID.tableID)); + table->delete_(context->clientContext->getTx(), *deleteState); } void RelDeleteExecutor::init(ResultSet* resultSet, ExecutionContext* /*context*/) { @@ -96,7 +104,9 @@ void RelDeleteExecutor::init(ResultSet* resultSet, ExecutionContext* /*context*/ } void SingleLabelRelDeleteExecutor::delete_(ExecutionContext* context) { - table->delete_(context->clientContext->getTx(), srcNodeIDVector, dstNodeIDVector, relIDVector); + auto deleteState = std::make_unique(*srcNodeIDVector, + *dstNodeIDVector, *relIDVector); + table->delete_(context->clientContext->getTx(), *deleteState); } void MultiLabelRelDeleteExecutor::delete_(ExecutionContext* context) { @@ -105,7 +115,9 @@ void MultiLabelRelDeleteExecutor::delete_(ExecutionContext* context) { auto relID = relIDVector->getValue(pos); KU_ASSERT(tableIDToTableMap.contains(relID.tableID)); auto table = tableIDToTableMap.at(relID.tableID); - table->delete_(context->clientContext->getTx(), srcNodeIDVector, dstNodeIDVector, relIDVector); + auto deleteState = std::make_unique(*srcNodeIDVector, + *dstNodeIDVector, *relIDVector); + table->delete_(context->clientContext->getTx(), *deleteState); } } // namespace processor diff --git a/src/processor/operator/persistent/export_db.cpp b/src/processor/operator/persistent/export_db.cpp index 7f80a5c2496..4f492892080 100644 --- a/src/processor/operator/persistent/export_db.cpp +++ b/src/processor/operator/persistent/export_db.cpp @@ -7,8 +7,10 @@ #include "catalog/catalog.h" #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "catalog/catalog_entry/rel_table_catalog_entry.h" +#include "common/copier_config/csv_reader_config.h" #include "common/file_system/virtual_file_system.h" #include "common/string_utils.h" +#include "function/scalar_macro_function.h" using namespace kuzu::common; using namespace kuzu::transaction; @@ -19,22 +21,20 @@ namespace processor { using std::stringstream; -static void writeStringStreamToFile( - VirtualFileSystem* vfs, std::string ss_string, const std::string& path) { +static void writeStringStreamToFile(VirtualFileSystem* vfs, std::string ss_string, + const std::string& path) { auto fileInfo = vfs->openFile(path, O_WRONLY | O_CREAT); - fileInfo->writeFile( - reinterpret_cast(ss_string.c_str()), ss_string.size(), 0 /* offset */); + fileInfo->writeFile(reinterpret_cast(ss_string.c_str()), ss_string.size(), + 0 /* offset */); } -static void writeCopyStatement( - stringstream& ss, std::string tableName, ReaderConfig* boundFileInfo) { - ss << "COPY "; - ss << tableName << " FROM \"" << boundFileInfo->filePaths[0] << "/" << tableName; +static void writeCopyStatement(stringstream& ss, std::string tableName, + ReaderConfig* boundFileInfo) { auto fileTypeStr = FileTypeUtils::toString(boundFileInfo->fileType); StringUtils::toLower(fileTypeStr); - ss << "." << fileTypeStr; auto csvConfig = common::CSVReaderConfig::construct(boundFileInfo->options); - ss << "\"" << csvConfig.option.toCypher() << std::endl; + ss << stringFormat("COPY {} FROM \"{}.{}\" {};\n", tableName, tableName, fileTypeStr, + csvConfig.option.toCypher()); } std::string getSchemaCypher(main::ClientContext* clientContext, transaction::Transaction* tx) { @@ -57,8 +57,8 @@ std::string getMacroCypher(catalog::Catalog* catalog, transaction::Transaction* return ss.str(); } -std::string getCopyCypher( - catalog::Catalog* catalog, transaction::Transaction* tx, ReaderConfig* boundFileInfo) { +std::string getCopyCypher(catalog::Catalog* catalog, transaction::Transaction* tx, + ReaderConfig* boundFileInfo) { stringstream ss; for (auto& nodeTableEntry : catalog->getNodeTableEntries(tx)) { auto tableName = nodeTableEntry->getName(); @@ -83,8 +83,8 @@ bool ExportDB::getNextTuplesInternal(ExecutionContext* context) { // write the copy.cypher file // for every table, we write COPY FROM statement writeStringStreamToFile(context->clientContext->getVFSUnsafe(), - getCopyCypher( - context->clientContext->getCatalog(), context->clientContext->getTx(), &boundFileInfo), + getCopyCypher(context->clientContext->getCatalog(), context->clientContext->getTx(), + &boundFileInfo), boundFileInfo.filePaths[0] + "/copy.cypher"); return false; } diff --git a/src/processor/operator/persistent/index_builder.cpp b/src/processor/operator/persistent/index_builder.cpp index 9ea69537b24..82deb37588c 100644 --- a/src/processor/operator/persistent/index_builder.cpp +++ b/src/processor/operator/persistent/index_builder.cpp @@ -34,34 +34,26 @@ void IndexBuilderGlobalQueues::maybeConsumeIndex(size_t index) { if (!mutexes[index].try_lock()) { return; } - std::unique_lock lck{mutexes[index], std::adopt_lock}; - - std::visit(overload{[&](Queue&& queues) { - using T = std::decay_t; - Buffer elem; - while (queues.array[index].pop(elem)) { - for (auto [key, value] : elem) { - if (!pkIndex->appendWithIndexPos(key, value, index)) { - throw CopyException( - ExceptionMessage::duplicatePKException(std::move(key))); - } - } - } - return; - }, - [&](auto&& queues) { - using T = std::decay_t; - Buffer elem; - while (queues.array[index].pop(elem)) { - for (auto [key, value] : elem) { - if (!pkIndex->appendWithIndexPos(key, value, index)) { - throw CopyException(ExceptionMessage::duplicatePKException( - TypeUtils::toString(key))); - } - } - } - return; - }}, + + std::visit( + [&](auto&& queues) { + using T = std::decay_t; + std::unique_lock lck{mutexes[index], std::adopt_lock}; + IndexBuffer buffer; + while (queues.array[index].pop(buffer)) { + auto numValuesInserted = pkIndex->appendWithIndexPos(buffer, index); + if (numValuesInserted < buffer.size()) { + if constexpr (std::same_as) { + throw CopyException(ExceptionMessage::duplicatePKException( + std::move(buffer[numValuesInserted].first))); + } else { + throw CopyException(ExceptionMessage::duplicatePKException( + TypeUtils::toString(buffer[numValuesInserted].first))); + } + } + } + return; + }, std::move(queues)); } @@ -97,26 +89,27 @@ void IndexBuilderSharedState::quitProducer() { } } -void IndexBuilder::insert(ColumnChunk* chunk, offset_t nodeOffset, offset_t numNodes) { - checkNonNullConstraint(chunk->getNullChunk(), numNodes); +void IndexBuilder::insert(const ColumnChunk& chunk, offset_t nodeOffset, offset_t numNodes) { + checkNonNullConstraint(chunk.getNullChunk(), numNodes); TypeUtils::visit( - chunk->getDataType().getPhysicalType(), + chunk.getDataType().getPhysicalType(), [&](T) { for (auto i = 0u; i < numNodes; i++) { - auto value = chunk->getValue(i); + auto value = chunk.getValue(i); localBuffers.insert(value, nodeOffset + i); } }, [&](ku_string_t) { - auto stringColumnChunk = ku_dynamic_cast(chunk); + auto& stringColumnChunk = + ku_dynamic_cast(chunk); for (auto i = 0u; i < numNodes; i++) { - auto value = stringColumnChunk->getValue(i); + auto value = stringColumnChunk.getValue(i); localBuffers.insert(std::move(value), nodeOffset + i); } }, [&](auto) { - throw CopyException(ExceptionMessage::invalidPKType(chunk->getDataType().toString())); + throw CopyException(ExceptionMessage::invalidPKType(chunk.getDataType().toString())); }); } @@ -137,9 +130,9 @@ void IndexBuilder::finalize(ExecutionContext* /*context*/) { sharedState->flush(); } -void IndexBuilder::checkNonNullConstraint(NullColumnChunk* nullChunk, offset_t numNodes) { +void IndexBuilder::checkNonNullConstraint(const NullColumnChunk& nullChunk, offset_t numNodes) { for (auto i = 0u; i < numNodes; i++) { - if (nullChunk->isNull(i)) { + if (nullChunk.isNull(i)) { throw CopyException(ExceptionMessage::nullPKException()); } } diff --git a/src/processor/operator/persistent/insert.cpp b/src/processor/operator/persistent/insert.cpp index 7414e96dc21..f3a8bee3be7 100644 --- a/src/processor/operator/persistent/insert.cpp +++ b/src/processor/operator/persistent/insert.cpp @@ -20,10 +20,10 @@ bool Insert::getNextTuplesInternal(ExecutionContext* context) { return false; } for (auto& executor : nodeExecutors) { - executor.insert(transaction, context); + executor.insert(context->clientContext->getTx(), context); } for (auto& executor : relExecutors) { - executor.insert(transaction, context); + executor.insert(context->clientContext->getTx(), context); } return true; } diff --git a/src/processor/operator/persistent/insert_executor.cpp b/src/processor/operator/persistent/insert_executor.cpp index 7400881cef9..3c4893beb59 100644 --- a/src/processor/operator/persistent/insert_executor.cpp +++ b/src/processor/operator/persistent/insert_executor.cpp @@ -50,17 +50,39 @@ void NodeInsertExecutor::insert(Transaction* tx, ExecutionContext* context) { evaluator->evaluate(context->clientContext); } KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); + if (checkConfict(tx)) { + return; + } + // TODO: Move pkVector pos to info. + auto nodeInsertState = std::make_unique(*nodeIDVector, + *columnDataVectors[table->getPKColumnID()], columnDataVectors); + table->insert(tx, *nodeInsertState); + writeResult(); +} + +void NodeInsertExecutor::evaluateResult(ExecutionContext* context) { + for (auto& evaluator : columnDataEvaluators) { + evaluator->evaluate(context->clientContext); + } + nodeIDVector->setNull(nodeIDVector->state->selVector->selectedPositions[0], false); + writeResult(); +} + +bool NodeInsertExecutor::checkConfict(Transaction* transaction) { if (conflictAction == ConflictAction::ON_CONFLICT_DO_NOTHING) { - auto off = table->validateUniquenessConstraint(tx, columnDataVectors); + auto off = table->validateUniquenessConstraint(transaction, columnDataVectors); if (off != INVALID_OFFSET) { // Conflict. Skip insertion. auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[0]; nodeIDVector->setNull(nodeIDPos, false); nodeIDVector->setValue(nodeIDPos, {off, table->getTableID()}); - return; + return true; } } - table->insert(tx, nodeIDVector, columnDataVectors); + return false; +} + +void NodeInsertExecutor::writeResult() { for (auto i = 0u; i < columnVectors.size(); ++i) { auto columnVector = columnVectors[i]; auto dataVector = columnDataVectors[i]; @@ -124,12 +146,18 @@ void RelInsertExecutor::insert(transaction::Transaction* tx, ExecutionContext* c return; } auto offset = relsStatistics->getNextRelOffset(tx, table->getTableID()); - columnDataVectors[0]->setValue(0, offset); // internal ID property + columnDataVectors[0]->setValue(0, internalID_t{offset, table->getTableID()}); columnDataVectors[0]->setNull(0, false); for (auto i = 1u; i < columnDataEvaluators.size(); ++i) { columnDataEvaluators[i]->evaluate(context->clientContext); } - table->insert(tx, srcNodeIDVector, dstNodeIDVector, columnDataVectors); + auto insertState = std::make_unique(*srcNodeIDVector, + *dstNodeIDVector, columnDataVectors); + table->insert(tx, *insertState); + writeResult(); +} + +void RelInsertExecutor::writeResult() { for (auto i = 0u; i < columnVectors.size(); ++i) { auto columnVector = columnVectors[i]; auto dataVector = columnDataVectors[i]; diff --git a/src/processor/operator/persistent/merge.cpp b/src/processor/operator/persistent/merge.cpp index f488b9b13a1..ccf66d830db 100644 --- a/src/processor/operator/persistent/merge.cpp +++ b/src/processor/operator/persistent/merge.cpp @@ -4,7 +4,10 @@ namespace kuzu { namespace processor { void Merge::initLocalStateInternal(ResultSet* /*resultSet_*/, ExecutionContext* context) { - markVector = resultSet->getValueVector(markPos).get(); + existenceVector = resultSet->getValueVector(existenceMark).get(); + if (distinctMark.isValid()) { + distinctVector = resultSet->getValueVector(distinctMark).get(); + } for (auto& executor : nodeInsertExecutors) { executor.init(resultSet, context); } @@ -29,9 +32,9 @@ bool Merge::getNextTuplesInternal(ExecutionContext* context) { if (!children[0]->getNextTuple(context)) { return false; } - KU_ASSERT(markVector->state->isFlat()); - auto pos = markVector->state->selVector->selectedPositions[0]; - if (!markVector->isNull(pos)) { + KU_ASSERT(existenceVector->state->isFlat()); + auto existencePos = existenceVector->state->selVector->selectedPositions[0]; + if (!existenceVector->isNull(existencePos)) { for (auto& executor : onMatchNodeSetExecutors) { executor->set(context); } @@ -39,17 +42,37 @@ bool Merge::getNextTuplesInternal(ExecutionContext* context) { executor->set(context); } } else { - for (auto& executor : nodeInsertExecutors) { - executor.insert(transaction, context); - } - for (auto& executor : relInsertExecutors) { - executor.insert(transaction, context); - } - for (auto& executor : onCreateNodeSetExecutors) { - executor->set(context); - } - for (auto& executor : onCreateRelSetExecutors) { - executor->set(context); + // pattern not exist + if (distinctVector != nullptr && + !distinctVector->getValue( + distinctVector->state->selVector->selectedPositions[0])) { + // pattern has been created + for (auto& executor : nodeInsertExecutors) { + executor.evaluateResult(context); + } + for (auto& executor : relInsertExecutors) { + executor.insert(context->clientContext->getTx(), context); + } + for (auto& executor : onMatchNodeSetExecutors) { + executor->set(context); + } + for (auto& executor : onMatchRelSetExecutors) { + executor->set(context); + } + } else { + // do insert and on create + for (auto& executor : nodeInsertExecutors) { + executor.insert(context->clientContext->getTx(), context); + } + for (auto& executor : relInsertExecutors) { + executor.insert(context->clientContext->getTx(), context); + } + for (auto& executor : onCreateNodeSetExecutors) { + executor->set(context); + } + for (auto& executor : onCreateRelSetExecutors) { + executor->set(context); + } } } return true; diff --git a/src/processor/operator/persistent/node_batch_insert.cpp b/src/processor/operator/persistent/node_batch_insert.cpp index ecfdffdcda1..857f8cb6e6c 100644 --- a/src/processor/operator/persistent/node_batch_insert.cpp +++ b/src/processor/operator/persistent/node_batch_insert.cpp @@ -16,8 +16,8 @@ void NodeBatchInsertSharedState::initPKIndex(kuzu::processor::ExecutionContext* KU_ASSERT(pkType.getLogicalTypeID() != LogicalTypeID::SERIAL); auto indexFName = StorageUtils::getNodeIndexFName(context->clientContext->getVFSUnsafe(), wal->getDirectory(), table->getTableID(), FileVersionType::ORIGINAL); - pkIndex = std::make_unique( - indexFName, pkType.getPhysicalType(), context->clientContext->getVFSUnsafe()); + pkIndex = std::make_unique(indexFName, pkType.getPhysicalType(), + context->clientContext->getVFSUnsafe()); uint64_t numRows; if (readerSharedState != nullptr) { KU_ASSERT(distinctSharedState == nullptr); @@ -32,7 +32,7 @@ void NodeBatchInsertSharedState::initPKIndex(kuzu::processor::ExecutionContext* } void NodeBatchInsertSharedState::appendIncompleteNodeGroup( - std::unique_ptr localNodeGroup, std::optional& indexBuilder) { + std::unique_ptr localNodeGroup, std::optional& indexBuilder) { std::unique_lock xLck{mtx}; if (!sharedNodeGroup) { sharedNodeGroup = std::move(localNodeGroup); @@ -43,8 +43,8 @@ void NodeBatchInsertSharedState::appendIncompleteNodeGroup( if (sharedNodeGroup->isFull()) { auto nodeGroupIdx = getNextNodeGroupIdxWithoutLock(); auto nodeTable = ku_dynamic_cast(table); - NodeBatchInsert::writeAndResetNodeGroup( - nodeGroupIdx, indexBuilder, pkColumnIdx, nodeTable, sharedNodeGroup.get()); + NodeBatchInsert::writeAndResetNodeGroup(nodeGroupIdx, indexBuilder, pkColumnIdx, nodeTable, + sharedNodeGroup.get()); } if (numNodesAppended < localNodeGroup->getNumRows()) { sharedNodeGroup->append(localNodeGroup.get(), numNodesAppended); @@ -87,16 +87,16 @@ void NodeBatchInsert::initLocalStateInternal(ResultSet* resultSet, ExecutionCont if (pos.isValid()) { nodeLocalState->columnVectors.push_back(resultSet->getValueVector(pos).get()); } else { - auto columnType = nodeInfo->columnTypes[i].get(); - auto nullVector = std::make_shared(*columnType); + auto& columnType = nodeInfo->columnTypes[i]; + auto nullVector = std::make_shared(columnType); nullVector->setState(state); nullVector->setAllNull(); nodeLocalState->nullColumnVectors.push_back(nullVector); nodeLocalState->columnVectors.push_back(nullVector.get()); } } - nodeLocalState->nodeGroup = NodeGroupFactory::createNodeGroup( - ColumnDataFormat::REGULAR, nodeInfo->columnTypes, info->compressionEnabled); + nodeLocalState->nodeGroup = NodeGroupFactory::createNodeGroup(ColumnDataFormat::REGULAR, + nodeInfo->columnTypes, info->compressionEnabled); nodeLocalState->columnState = state.get(); } @@ -117,8 +117,8 @@ void NodeBatchInsert::executeInternal(ExecutionContext* context) { auto nodeSharedState = ku_dynamic_cast( sharedState.get()); - nodeSharedState->appendIncompleteNodeGroup( - std::move(nodeLocalState->nodeGroup), nodeLocalState->localIndexBuilder); + nodeSharedState->appendIncompleteNodeGroup(std::move(nodeLocalState->nodeGroup), + nodeLocalState->localIndexBuilder); } if (nodeLocalState->localIndexBuilder) { KU_ASSERT(token); @@ -129,12 +129,12 @@ void NodeBatchInsert::executeInternal(ExecutionContext* context) { void NodeBatchInsert::writeAndResetNodeGroup(node_group_idx_t nodeGroupIdx, std::optional& indexBuilder, column_id_t pkColumnID, NodeTable* table, - NodeGroup* nodeGroup) { + ChunkedNodeGroup* nodeGroup) { nodeGroup->finalize(nodeGroupIdx); if (indexBuilder) { auto nodeOffset = StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); - indexBuilder->insert( - nodeGroup->getColumnChunk(pkColumnID), nodeOffset, nodeGroup->getNumRows()); + indexBuilder->insert(nodeGroup->getColumnChunkUnsafe(pkColumnID), nodeOffset, + nodeGroup->getNumRows()); } table->append(nodeGroup); nodeGroup->resetToEmpty(); @@ -158,7 +158,7 @@ void NodeBatchInsert::copyToNodeGroup() { while (numAppendedTuples < numTuplesToAppend) { auto numAppendedTuplesInNodeGroup = nodeLocalState->nodeGroup->append(nodeLocalState->columnVectors, - nodeLocalState->columnState, numTuplesToAppend - numAppendedTuples); + *nodeLocalState->columnState->selVector, numTuplesToAppend - numAppendedTuples); numAppendedTuples += numAppendedTuplesInNodeGroup; if (nodeLocalState->nodeGroup->isFull()) { node_group_idx_t nodeGroupIdx; @@ -176,7 +176,7 @@ void NodeBatchInsert::finalize(ExecutionContext* context) { auto nodeSharedState = ku_dynamic_cast(sharedState.get()); nodeSharedState->calculateNumTuples(); - nodeSharedState->setNumTuplesForTable(); + nodeSharedState->updateNumTuplesForTable(); if (nodeSharedState->sharedNodeGroup) { auto nodeGroupIdx = nodeSharedState->getNextNodeGroupIdx(); auto nodeTable = ku_dynamic_cast(nodeSharedState->table); @@ -188,8 +188,8 @@ void NodeBatchInsert::finalize(ExecutionContext* context) { } auto outputMsg = stringFormat("{} number of tuples has been copied to table: {}.", sharedState->getNumRows(), info->tableEntry->getName()); - FactorizedTableUtils::appendStringToTable( - sharedState->fTable.get(), outputMsg, context->clientContext->getMemoryManager()); + FactorizedTableUtils::appendStringToTable(sharedState->fTable.get(), outputMsg, + context->clientContext->getMemoryManager()); } } // namespace processor } // namespace kuzu diff --git a/src/processor/operator/persistent/reader/csv/base_csv_reader.cpp b/src/processor/operator/persistent/reader/csv/base_csv_reader.cpp index 59e74991257..d03d95b647f 100644 --- a/src/processor/operator/persistent/reader/csv/base_csv_reader.cpp +++ b/src/processor/operator/persistent/reader/csv/base_csv_reader.cpp @@ -114,6 +114,10 @@ bool BaseCSVReader::isEOF() const { return getFileOffset() >= fileInfo->getFileSize(); } +uint64_t BaseCSVReader::getFileSize() { + return fileInfo->getFileSize(); +} + template void BaseCSVReader::addValue(Driver& driver, uint64_t rowNum, column_id_t columnIdx, std::string_view strVal, std::vector& escapePositions) { @@ -272,7 +276,7 @@ uint64_t BaseCSVReader::parseCSV(Driver& driver) { goto final_state; } goto value_start; -add_row : { +add_row: { // We get here after we have a newline. KU_ASSERT(isNewLine(buffer[position])); bool isCarriageReturn = buffer[position] == '\r'; @@ -319,8 +323,8 @@ add_row : { } while (readBuffer(&start)); [[unlikely]] // still in quoted state at the end of the file, error: - throw CopyException(stringFormat( - "Error in file {} on line {}: unterminated quotes.", fileInfo->path, getLineNumber())); + throw CopyException(stringFormat("Error in file {} on line {}: unterminated quotes.", + fileInfo->path, getLineNumber())); unquote: KU_ASSERT(hasQuotes && buffer[position] == option.quoteChar); // this state handles the state directly after we unquote @@ -417,8 +421,8 @@ uint64_t BaseCSVReader::getLineNumber() { char buf[BUF_SIZE]; if (fileInfo->seek(0, SEEK_SET) == -1) { // LCOV_EXCL_START - throw CopyException(stringFormat( - "Could not seek to beginning of file {}: {}", fileInfo->path, posixErrMessage())); + throw CopyException(stringFormat("Could not seek to beginning of file {}: {}", + fileInfo->path, posixErrMessage())); // LCOV_EXCL_STOP } diff --git a/src/processor/operator/persistent/reader/csv/driver.cpp b/src/processor/operator/persistent/reader/csv/driver.cpp index f6a1598696f..fbf03c29861 100644 --- a/src/processor/operator/persistent/reader/csv/driver.cpp +++ b/src/processor/operator/persistent/reader/csv/driver.cpp @@ -17,8 +17,8 @@ bool ParsingDriver::done(uint64_t rowNum) { return rowNum >= DEFAULT_VECTOR_CAPACITY || doneEarly(); } -void ParsingDriver::addValue( - uint64_t rowNum, common::column_id_t columnIdx, std::string_view value) { +void ParsingDriver::addValue(uint64_t rowNum, common::column_id_t columnIdx, + std::string_view value) { uint64_t length = value.length(); if (length == 0 && columnIdx == 0) { rowEmpty = true; @@ -36,8 +36,8 @@ void ParsingDriver::addValue( reader->fileInfo->path, reader->getLineNumber(), reader->numColumns)); } try { - function::CastString::copyStringToVector( - chunk.getValueVector(columnIdx).get(), rowNum, value, &reader->option); + function::CastString::copyStringToVector(chunk.getValueVector(columnIdx).get(), rowNum, + value, &reader->option); } catch (ConversionException& e) { throw CopyException(stringFormat("Error in file {} on line {}: {}", reader->fileInfo->path, reader->getLineNumber(), e.what())); @@ -113,8 +113,8 @@ bool SniffCSVColumnCountDriver::done(uint64_t) const { return !emptyRow; } -void SniffCSVColumnCountDriver::addValue( - uint64_t, common::column_id_t columnIdx, std::string_view value) { +void SniffCSVColumnCountDriver::addValue(uint64_t, common::column_id_t columnIdx, + std::string_view value) { if (value != "" || columnIdx > 0) { emptyRow = false; } diff --git a/src/processor/operator/persistent/reader/csv/parallel_csv_reader.cpp b/src/processor/operator/persistent/reader/csv/parallel_csv_reader.cpp index 4a11ad40d78..76f3712b3ea 100644 --- a/src/processor/operator/persistent/reader/csv/parallel_csv_reader.cpp +++ b/src/processor/operator/persistent/reader/csv/parallel_csv_reader.cpp @@ -109,6 +109,7 @@ bool ParallelCSVReader::finishedBlock() const { void ParallelCSVScanSharedState::setFileComplete(uint64_t completedFileIdx) { std::lock_guard guard{lock}; if (completedFileIdx == fileIdx) { + numBlocksReadByFiles += blockIdx; blockIdx = 0; fileIdx++; } @@ -116,8 +117,10 @@ void ParallelCSVScanSharedState::setFileComplete(uint64_t completedFileIdx) { static offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output) { auto& outputChunk = output.dataChunk; - auto parallelCSVLocalState = reinterpret_cast(input.localState); - auto parallelCSVSharedState = reinterpret_cast(input.sharedState); + auto parallelCSVLocalState = + ku_dynamic_cast(input.localState); + auto parallelCSVSharedState = + ku_dynamic_cast(input.sharedState); do { if (parallelCSVLocalState->reader != nullptr && parallelCSVLocalState->reader->hasMoreToRead()) { @@ -150,9 +153,9 @@ static offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output) { } while (true); } -static std::unique_ptr bindFunc( - main::ClientContext* /*context*/, TableFuncBindInput* input) { - auto scanInput = reinterpret_cast(input); +static std::unique_ptr bindFunc(main::ClientContext* /*context*/, + TableFuncBindInput* input) { + auto scanInput = ku_dynamic_cast(input); std::vector detectedColumnNames; std::vector detectedColumnTypes; SerialCSVScan::bindColumns(scanInput, detectedColumnNames, detectedColumnTypes); @@ -165,28 +168,48 @@ static std::unique_ptr bindFunc( } static std::unique_ptr initSharedState(TableFunctionInitInput& input) { - auto bindData = reinterpret_cast(input.bindData); + auto bindData = ku_dynamic_cast(input.bindData); auto csvConfig = CSVReaderConfig::construct(bindData->config.options); row_idx_t numRows = 0; - return std::make_unique(bindData->config.copy(), numRows, - bindData->columnNames.size(), bindData->context, csvConfig.copy()); + auto sharedState = std::make_unique(bindData->config.copy(), + numRows, bindData->columnNames.size(), bindData->context, csvConfig.copy()); + for (auto filePath : sharedState->readerConfig.filePaths) { + auto reader = std::make_unique(filePath, + sharedState->csvReaderConfig.option.copy(), sharedState->numColumns, + sharedState->context); + sharedState->totalSize += reader->getFileSize(); + } + return sharedState; } static std::unique_ptr initLocalState(TableFunctionInitInput& /*input*/, TableFuncSharedState* state, storage::MemoryManager* /*mm*/) { auto localState = std::make_unique(); - auto sharedState = reinterpret_cast(state); + auto sharedState = ku_dynamic_cast(state); localState->reader = std::make_unique(sharedState->readerConfig.filePaths[0], sharedState->csvReaderConfig.option.copy(), sharedState->numColumns, sharedState->context); localState->fileIdx = 0; return localState; } +static double progressFunc(TableFuncSharedState* sharedState) { + auto state = ku_dynamic_cast(sharedState); + if (state->fileIdx >= state->readerConfig.getNumFiles()) { + return 1.0; + } + if (state->totalSize == 0) { + return 0.0; + } + uint64_t totalReadSize = + (state->numBlocksReadByFiles + state->blockIdx) * CopyConstants::PARALLEL_BLOCK_SIZE; + return static_cast(totalReadSize) / state->totalSize; +} + function_set ParallelCSVScan::getFunctionSet() { function_set functionSet; functionSet.push_back( - std::make_unique(READ_CSV_PARALLEL_FUNC_NAME, tableFunc, bindFunc, - initSharedState, initLocalState, std::vector{LogicalTypeID::STRING})); + std::make_unique(name, tableFunc, bindFunc, initSharedState, initLocalState, + progressFunc, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/processor/operator/persistent/reader/csv/serial_csv_reader.cpp b/src/processor/operator/persistent/reader/csv/serial_csv_reader.cpp index 1bfa025e91a..c809d8d1c5e 100644 --- a/src/processor/operator/persistent/reader/csv/serial_csv_reader.cpp +++ b/src/processor/operator/persistent/reader/csv/serial_csv_reader.cpp @@ -55,6 +55,7 @@ void SerialCSVScanSharedState::read(DataChunk& outputChunk) { if (numRows > 0) { return; } + totalReadSizeByFile += reader->getFileSize(); fileIdx++; initReader(context); } while (true); @@ -62,13 +63,14 @@ void SerialCSVScanSharedState::read(DataChunk& outputChunk) { void SerialCSVScanSharedState::initReader(main::ClientContext* context) { if (fileIdx < readerConfig.getNumFiles()) { - reader = std::make_unique( - readerConfig.filePaths[fileIdx], csvReaderConfig.option.copy(), numColumns, context); + reader = std::make_unique(readerConfig.filePaths[fileIdx], + csvReaderConfig.option.copy(), numColumns, context); } } static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output) { - auto serialCSVScanSharedState = reinterpret_cast(input.sharedState); + auto serialCSVScanSharedState = + ku_dynamic_cast(input.sharedState); serialCSVScanSharedState->read(output.dataChunk); return output.dataChunk.state->selVector->selectedSize; } @@ -97,9 +99,9 @@ void SerialCSVScan::bindColumns(const ScanTableFuncBindInput* bindInput, } } -static std::unique_ptr bindFunc( - main::ClientContext* /*context*/, TableFuncBindInput* input) { - auto scanInput = reinterpret_cast(input); +static std::unique_ptr bindFunc(main::ClientContext* /*context*/, + TableFuncBindInput* input) { + auto scanInput = ku_dynamic_cast(input); std::vector detectedColumnNames; std::vector detectedColumnTypes; SerialCSVScan::bindColumns(scanInput, detectedColumnNames, detectedColumnTypes); @@ -112,11 +114,18 @@ static std::unique_ptr bindFunc( } static std::unique_ptr initSharedState(TableFunctionInitInput& input) { - auto bindData = reinterpret_cast(input.bindData); + auto bindData = ku_dynamic_cast(input.bindData); auto csvConfig = CSVReaderConfig::construct(bindData->config.options); row_idx_t numRows = 0; - return std::make_unique(bindData->config.copy(), numRows, + auto sharedState = std::make_unique(bindData->config.copy(), numRows, bindData->columnNames.size(), csvConfig.copy(), bindData->context); + for (auto filePath : sharedState->readerConfig.filePaths) { + auto reader = + std::make_unique(filePath, sharedState->csvReaderConfig.option.copy(), + sharedState->numColumns, sharedState->context); + sharedState->totalSize += reader->getFileSize(); + } + return sharedState; } static std::unique_ptr initLocalState(TableFunctionInitInput& /*input*/, @@ -124,11 +133,22 @@ static std::unique_ptr initLocalState(TableFunctionInitInpu return std::make_unique(); } +static double progressFunc(TableFuncSharedState* sharedState) { + auto state = ku_dynamic_cast(sharedState); + if (state->totalSize == 0) { + return 0.0; + } else if (state->fileIdx >= state->readerConfig.getNumFiles()) { + return 1.0; + } + uint64_t totalReadSize = state->totalReadSizeByFile + state->reader->getFileOffset(); + return static_cast(totalReadSize) / state->totalSize; +} + function_set SerialCSVScan::getFunctionSet() { function_set functionSet; functionSet.push_back( - std::make_unique(READ_CSV_SERIAL_FUNC_NAME, tableFunc, bindFunc, - initSharedState, initLocalState, std::vector{LogicalTypeID::STRING})); + std::make_unique(name, tableFunc, bindFunc, initSharedState, initLocalState, + progressFunc, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/processor/operator/persistent/reader/npy/npy_reader.cpp b/src/processor/operator/persistent/reader/npy/npy_reader.cpp index 2b4425548fe..5fd2298bbf0 100644 --- a/src/processor/operator/persistent/reader/npy/npy_reader.cpp +++ b/src/processor/operator/persistent/reader/npy/npy_reader.cpp @@ -183,7 +183,7 @@ void NpyReader::validate(const LogicalType& type_, offset_t numRows) { if (numNodesInFile != numRows) { throw CopyException("Number of rows in npy files is not equal to each other."); } - // TODO(Guodong): Set npy reader data type to FIXED_LIST, so we can simplify checks here. + // TODO(Guodong): Set npy reader data type to ARRAY, so we can simplify checks here. if (type_.getLogicalTypeID() == this->type) { if (getNumElementsPerRow() != 1) { throw CopyException(stringFormat("Cannot copy a vector property in npy file {} to a " @@ -191,13 +191,13 @@ void NpyReader::validate(const LogicalType& type_, offset_t numRows) { filePath)); } return; - } else if (type_.getLogicalTypeID() == LogicalTypeID::FIXED_LIST) { - if (this->type != FixedListType::getChildType(&type_)->getLogicalTypeID()) { + } else if (type_.getLogicalTypeID() == LogicalTypeID::ARRAY) { + if (this->type != ArrayType::getChildType(&type_)->getLogicalTypeID()) { throw CopyException(stringFormat("The type of npy file {} does not " "match the expected type.", filePath)); } - if (getNumElementsPerRow() != FixedListType::getNumValuesInList(&type_)) { + if (getNumElementsPerRow() != ArrayType::getNumElements(&type_)) { throw CopyException( stringFormat("The shape of {} does not match {}.", filePath, type_.toString())); } @@ -217,9 +217,22 @@ void NpyReader::readBlock(block_idx_t blockIdx, common::ValueVector* vectorToRea } else { auto rowPointer = getPointerToRow(rowNumber); auto numRowsToRead = std::min(DEFAULT_VECTOR_CAPACITY, getNumRows() - rowNumber); - memcpy(vectorToRead->getData(), rowPointer, - numRowsToRead * vectorToRead->getNumBytesPerValue()); - vectorToRead->state->selVector->selectedSize = numRowsToRead; + auto rowType = vectorToRead->dataType; + if (rowType.getLogicalTypeID() == LogicalTypeID::ARRAY) { + auto numValuesPerRow = ArrayType::getNumElements(&rowType); + for (auto i = 0u; i < numRowsToRead; i++) { + auto listEntry = ListVector::addList(vectorToRead, numValuesPerRow); + vectorToRead->setValue(i, listEntry); + } + auto dataVector = ListVector::getDataVector(vectorToRead); + memcpy(dataVector->getData(), rowPointer, + numRowsToRead * numValuesPerRow * dataVector->getNumBytesPerValue()); + vectorToRead->state->selVector->selectedSize = numRowsToRead; + } else { + memcpy(vectorToRead->getData(), rowPointer, + numRowsToRead * vectorToRead->getNumBytesPerValue()); + vectorToRead->state->selVector->selectedSize = numRowsToRead; + } } } @@ -247,21 +260,21 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output return output.dataChunk.state->selVector->selectedSize; } -static std::unique_ptr bindFixedListType( - const std::vector& shape, LogicalTypeID typeID) { - if (shape.size() == 1) { - return std::make_unique(typeID); +static std::unique_ptr bindColumnType(const NpyReader& reader) { + if (reader.getShape().size() == 1) { + return std::make_unique(reader.getType()); } - auto childShape = std::vector{shape.begin() + 1, shape.end()}; - auto childType = bindFixedListType(childShape, typeID); - return LogicalType::FIXED_LIST(std::move(childType), (uint32_t)shape[0]); + // For columns whose type is a multi-dimension array of size n*m, + // we flatten the row data into an 1-d array with size 1*k where k = n*m + return LogicalType::ARRAY(std::make_unique(reader.getType()), + reader.getNumElementsPerRow()); } static void bindColumns(const common::ReaderConfig& readerConfig, uint32_t fileIdx, std::vector& columnNames, std::vector& columnTypes) { auto reader = NpyReader(readerConfig.filePaths[fileIdx]); // TODO: double check auto columnName = std::string("column" + std::to_string(fileIdx)); - auto columnType = bindFixedListType(reader.getShape(), reader.getType()); + auto columnType = bindColumnType(reader); columnNames.push_back(columnName); columnTypes.push_back(*columnType); } @@ -280,8 +293,8 @@ static void bindColumns(const common::ReaderConfig& readerConfig, } } -static std::unique_ptr bindFunc( - main::ClientContext* /*context*/, function::TableFuncBindInput* input) { +static std::unique_ptr bindFunc(main::ClientContext* /*context*/, + function::TableFuncBindInput* input) { auto scanInput = reinterpret_cast(input); std::vector detectedColumnNames; std::vector detectedColumnTypes; @@ -319,7 +332,7 @@ static std::unique_ptr initLocalState( function_set NpyScanFunction::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(READ_NPY_FUNC_NAME, tableFunc, bindFunc, + functionSet.push_back(std::make_unique(name, tableFunc, bindFunc, initSharedState, initLocalState, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/processor/operator/persistent/reader/parquet/boolean_column_reader.cpp b/src/processor/operator/persistent/reader/parquet/boolean_column_reader.cpp index 7c0443f75ed..a34e4d074c5 100644 --- a/src/processor/operator/persistent/reader/parquet/boolean_column_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/boolean_column_reader.cpp @@ -7,8 +7,8 @@ void BooleanColumnReader::initializeRead(uint64_t rowGroupIdx, const std::vector& columns, kuzu_apache::thrift::protocol::TProtocol& protocol) { bytePos = 0; - TemplatedColumnReader::initializeRead( - rowGroupIdx, columns, protocol); + TemplatedColumnReader::initializeRead(rowGroupIdx, columns, + protocol); } bool BooleanParquetValueConversion::plainRead(ByteBuffer& plainData, ColumnReader& reader) { diff --git a/src/processor/operator/persistent/reader/parquet/column_reader.cpp b/src/processor/operator/persistent/reader/parquet/column_reader.cpp index 5cf65751429..26802b5adb0 100644 --- a/src/processor/operator/persistent/reader/parquet/column_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/column_reader.cpp @@ -174,8 +174,8 @@ uint64_t ColumnReader::read(uint64_t numValues, parquet_filter_t& filter, uint8_ auto readBuf = std::make_shared(); readBuf->resize(sizeof(bool) * (readNow - nullCount)); rleDecoder->GetBatch(readBuf->ptr, readNow - nullCount); - plainTemplated>( - readBuf, defineOut, readNow, filter, resultOffset, resultOut); + plainTemplated>(readBuf, defineOut, readNow, + filter, resultOffset, resultOut); } else { plain(block, defineOut, readNow, filter, resultOffset, resultOut); } @@ -195,63 +195,63 @@ std::unique_ptr ColumnReader::createReader(ParquetReader& reader, uint64_t fileIdx, uint64_t maxDefine, uint64_t maxRepeat) { switch (type->getLogicalTypeID()) { case common::LogicalTypeID::BOOL: - return std::make_unique( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + return std::make_unique(reader, std::move(type), schema, fileIdx, + maxDefine, maxRepeat); case common::LogicalTypeID::INT8: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::INT16: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::INT32: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::INT64: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::UINT8: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::UINT16: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::UINT32: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::UINT64: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::FLOAT: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::DOUBLE: return std::make_unique< - TemplatedColumnReader>>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + TemplatedColumnReader>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::DATE: return std::make_unique< CallbackColumnReader>( reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); case common::LogicalTypeID::BLOB: case common::LogicalTypeID::STRING: - return std::make_unique( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + return std::make_unique(reader, std::move(type), schema, fileIdx, + maxDefine, maxRepeat); case common::LogicalTypeID::INTERVAL: - return std::make_unique( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + return std::make_unique(reader, std::move(type), schema, fileIdx, + maxDefine, maxRepeat); case common::LogicalTypeID::TIMESTAMP_TZ: case common::LogicalTypeID::TIMESTAMP: - return createTimestampReader( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + return createTimestampReader(reader, std::move(type), schema, fileIdx, maxDefine, + maxRepeat); // TODO(kebing): timestamp default: KU_UNREACHABLE; @@ -303,15 +303,15 @@ void ColumnReader::decompressInternal(kuzu_parquet::format::CompressionCodec::ty throw common::CopyException("Parquet data unexpectedly uncompressed"); case CompressionCodec::GZIP: { MiniZStream s; - s.Decompress( - reinterpret_cast(src), srcSize, reinterpret_cast(dst), dstSize); + s.Decompress(reinterpret_cast(src), srcSize, reinterpret_cast(dst), + dstSize); break; } case CompressionCodec::SNAPPY: { { size_t uncompressedSize = 0; - auto res = kuzu_snappy::GetUncompressedLength( - reinterpret_cast(src), srcSize, &uncompressedSize); + auto res = kuzu_snappy::GetUncompressedLength(reinterpret_cast(src), + srcSize, &uncompressedSize); // LCOV_EXCL_START if (!res) { throw common::RuntimeException{"Failed to decompress parquet file."}; @@ -322,8 +322,8 @@ void ColumnReader::decompressInternal(kuzu_parquet::format::CompressionCodec::ty } // LCOV_EXCL_STOP } - auto res = kuzu_snappy::RawUncompress( - reinterpret_cast(src), srcSize, reinterpret_cast(dst)); + auto res = kuzu_snappy::RawUncompress(reinterpret_cast(src), srcSize, + reinterpret_cast(dst)); // LCOV_EXCL_START if (!res) { throw common::RuntimeException{"Snappy decompression failure"}; @@ -426,8 +426,8 @@ void ColumnReader::prepareDataPage(kuzu_parquet::format::PageHeader& pageHdr) { uint32_t repLength = isV1 ? block->read() : v2Header.repetition_levels_byte_length; block->available(repLength); - repeatedDecoder = std::make_unique( - block->ptr, repLength, RleBpDecoder::ComputeBitWidth(maxRepeat)); + repeatedDecoder = std::make_unique(block->ptr, repLength, + RleBpDecoder::ComputeBitWidth(maxRepeat)); block->inc(repLength); } else if (isV2 && v2Header.repetition_levels_byte_length > 0) { block->inc(v2Header.repetition_levels_byte_length); @@ -436,8 +436,8 @@ void ColumnReader::prepareDataPage(kuzu_parquet::format::PageHeader& pageHdr) { if (hasDefines()) { auto defLen = isV1 ? block->read() : v2Header.definition_levels_byte_length; block->available(defLen); - defineDecoder = std::make_unique( - block->ptr, defLen, RleBpDecoder::ComputeBitWidth(maxDefine)); + defineDecoder = std::make_unique(block->ptr, defLen, + RleBpDecoder::ComputeBitWidth(maxDefine)); block->inc(defLen); } else if (isV2 && v2Header.definition_levels_byte_length > 0) { block->inc(v2Header.definition_levels_byte_length); @@ -491,23 +491,23 @@ std::unique_ptr ColumnReader::createTimestampReader(ParquetReader& switch (schema.type) { case Type::INT96: { return std::make_unique>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + ParquetTimeStampUtils::impalaTimestampToTimestamp>>(reader, std::move(type), schema, + fileIdx, maxDefine, maxRepeat); } case Type::INT64: { if (schema.__isset.logicalType && schema.logicalType.__isset.TIMESTAMP) { if (schema.logicalType.TIMESTAMP.unit.__isset.MILLIS) { return std::make_unique>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + ParquetTimeStampUtils::parquetTimestampMsToTimestamp>>(reader, std::move(type), + schema, fileIdx, maxDefine, maxRepeat); } else if (schema.logicalType.TIMESTAMP.unit.__isset.MICROS) { return std::make_unique>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + ParquetTimeStampUtils::parquetTimestampMicrosToTimestamp>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); } else if (schema.logicalType.TIMESTAMP.unit.__isset.NANOS) { return std::make_unique>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + ParquetTimeStampUtils::parquetTimestampNsToTimestamp>>(reader, std::move(type), + schema, fileIdx, maxDefine, maxRepeat); } // LCOV_EXCL_START } else if (schema.__isset.converted_type) { @@ -515,12 +515,12 @@ std::unique_ptr ColumnReader::createTimestampReader(ParquetReader& switch (schema.converted_type) { case ConvertedType::TIMESTAMP_MICROS: return std::make_unique>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + ParquetTimeStampUtils::parquetTimestampMicrosToTimestamp>>(reader, + std::move(type), schema, fileIdx, maxDefine, maxRepeat); case ConvertedType::TIMESTAMP_MILLIS: return std::make_unique>( - reader, std::move(type), schema, fileIdx, maxDefine, maxRepeat); + ParquetTimeStampUtils::parquetTimestampMsToTimestamp>>(reader, std::move(type), + schema, fileIdx, maxDefine, maxRepeat); default: KU_UNREACHABLE; } diff --git a/src/processor/operator/persistent/reader/parquet/interval_column_reader.cpp b/src/processor/operator/persistent/reader/parquet/interval_column_reader.cpp index 49045ad709a..5c34fe7a6b6 100644 --- a/src/processor/operator/persistent/reader/parquet/interval_column_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/interval_column_reader.cpp @@ -12,8 +12,8 @@ common::interval_t IntervalValueConversion::readParquetInterval(const char* inpu return result; } -common::interval_t IntervalValueConversion::plainRead( - ByteBuffer& plainData, ColumnReader& /*reader*/) { +common::interval_t IntervalValueConversion::plainRead(ByteBuffer& plainData, + ColumnReader& /*reader*/) { auto intervalLen = common::ParquetConstants::PARQUET_INTERVAL_SIZE; plainData.available(intervalLen); auto res = readParquetInterval(reinterpret_cast(plainData.ptr)); @@ -21,8 +21,8 @@ common::interval_t IntervalValueConversion::plainRead( return res; } -void IntervalColumnReader::dictionary( - const std::shared_ptr& dictionary_data, uint64_t num_entries) { +void IntervalColumnReader::dictionary(const std::shared_ptr& dictionary_data, + uint64_t num_entries) { allocateDict(num_entries * sizeof(common::interval_t)); auto dict_ptr = reinterpret_cast(this->dict->ptr); for (auto i = 0u; i < num_entries; i++) { diff --git a/src/processor/operator/persistent/reader/parquet/list_column_reader.cpp b/src/processor/operator/persistent/reader/parquet/list_column_reader.cpp index 50c8e70bb07..ce22b533e3b 100644 --- a/src/processor/operator/persistent/reader/parquet/list_column_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/list_column_reader.cpp @@ -15,7 +15,7 @@ ListColumnReader::ListColumnReader(ParquetReader& reader, std::unique_ptr( - *common::VarListType::getChildType(this->type.get()), memoryManager); + *common::ListType::getChildType(this->type.get()), memoryManager); } void ListColumnReader::applyPendingSkips(uint64_t numValues) { @@ -62,8 +62,8 @@ uint64_t ListColumnReader::read(uint64_t numValues, parquet_filter_t& /*filter*/ // see if we have read enough if we have not read enough, we read another vector if we // have read enough, we leave any unhandled elements in the overflow vector for a // subsequent read - auto childReqNumValues = std::min( - common::DEFAULT_VECTOR_CAPACITY, childColumnReader->getGroupRowsAvailable()); + auto childReqNumValues = std::min(common::DEFAULT_VECTOR_CAPACITY, + childColumnReader->getGroupRowsAvailable()); childActualNumValues = childColumnReader->read(childReqNumValues, childFilter, childDefinesPtr, childRepeatsPtr, vectorToRead.get()); } else { diff --git a/src/processor/operator/persistent/reader/parquet/parquet_reader.cpp b/src/processor/operator/persistent/reader/parquet/parquet_reader.cpp index 76f2e3cd4d8..f7e40d05bb0 100644 --- a/src/processor/operator/persistent/reader/parquet/parquet_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/parquet_reader.cpp @@ -24,8 +24,8 @@ ParquetReader::ParquetReader(const std::string& filePath, main::ClientContext* c initMetadata(); } -void ParquetReader::initializeScan( - ParquetReaderScanState& state, std::vector groups_to_read, VirtualFileSystem* vfs) { +void ParquetReader::initializeScan(ParquetReaderScanState& state, + std::vector groups_to_read, VirtualFileSystem* vfs) { state.currentGroup = -1; state.finished = false; state.groupOffset = 0; @@ -52,7 +52,8 @@ bool ParquetReader::scanInternal(ParquetReaderScanState& state, DataChunk& resul state.groupOffset = 0; auto& trans = - reinterpret_cast(*state.thriftFileProto->getTransport()); + ku_dynamic_cast( + *state.thriftFileProto->getTransport()); trans.ClearPrefetch(); state.currentGroupPrefetched = false; @@ -67,7 +68,8 @@ bool ParquetReader::scanInternal(ParquetReaderScanState& state, DataChunk& resul auto fileColIdx = colIdx; - auto rootReader = reinterpret_cast(state.rootReader.get()); + auto rootReader = + ku_dynamic_cast(state.rootReader.get()); toScanCompressedBytes += rootReader->getChildReader(fileColIdx)->getTotalCompressedSize(); } @@ -99,7 +101,8 @@ bool ParquetReader::scanInternal(ParquetReaderScanState& state, DataChunk& resul // Prefetch column-wise. for (auto colIdx = 0u; colIdx < result.getNumValueVectors(); colIdx++) { auto fileColIdx = colIdx; - auto rootReader = reinterpret_cast(state.rootReader.get()); + auto rootReader = + ku_dynamic_cast(state.rootReader.get()); rootReader->getChildReader(fileColIdx) ->registerPrefetch(trans, true /* lazy fetch */); @@ -136,7 +139,7 @@ bool ParquetReader::scanInternal(ParquetReaderScanState& state, DataChunk& resul auto definePtr = (uint8_t*)state.defineBuf.ptr; auto repeatPtr = (uint8_t*)state.repeatBuf.ptr; - auto rootReader = reinterpret_cast(state.rootReader.get()); + auto rootReader = ku_dynamic_cast(state.rootReader.get()); for (auto colIdx = 0u; colIdx < result.getNumValueVectors(); colIdx++) { auto fileColIdx = colIdx; @@ -168,7 +171,9 @@ void ParquetReader::scan(processor::ParquetReaderScanState& state, DataChunk& re void ParquetReader::initMetadata() { auto fileInfo = context->getVFSUnsafe()->openFile(filePath, O_RDONLY, context); auto proto = createThriftProtocol(fileInfo.get(), false); - auto& transport = reinterpret_cast(*proto->getTransport()); + auto& transport = + ku_dynamic_cast( + *proto->getTransport()); auto fileSize = transport.GetSize(); // LCOV_EXCL_START if (fileSize < 12) { @@ -266,11 +271,11 @@ std::unique_ptr ParquetReader::createReaderRecursive(uint64_t dept } // LCOV_EXCL_STOP auto structType = LogicalType::STRUCT(std::move(structFields)); - resultType = std::unique_ptr(new LogicalType( - LogicalTypeID::MAP, std::make_unique(std::move(structType)))); + resultType = std::unique_ptr(new LogicalType(LogicalTypeID::MAP, + std::make_unique(std::move(structType)))); auto structReader = std::make_unique(*this, - VarListType::getChildType(resultType.get())->copy(), sEle, thisIdx, maxDefine - 1, + ListType::getChildType(resultType.get())->copy(), sEle, thisIdx, maxDefine - 1, maxRepeat - 1, std::move(childrenReaders)); return std::make_unique(*this, std::move(resultType), sEle, thisIdx, maxDefine, maxRepeat, std::move(structReader), context->getMemoryManager()); @@ -286,7 +291,7 @@ std::unique_ptr ParquetReader::createReaderRecursive(uint64_t dept result = std::move(childrenReaders[0]); } if (isRepeated) { - resultType = LogicalType::VAR_LIST(std::move(resultType)); + resultType = LogicalType::LIST(std::move(resultType)); return std::make_unique(*this, std::move(resultType), sEle, thisIdx, maxDefine, maxRepeat, std::move(result), context->getMemoryManager()); } @@ -300,15 +305,15 @@ std::unique_ptr ParquetReader::createReaderRecursive(uint64_t dept // LCOV_EXCL_STOP if (sEle.repetition_type == FieldRepetitionType::REPEATED) { auto derivedType = deriveLogicalType(sEle); - auto listType = LogicalType::VAR_LIST(derivedType->copy()); - auto elementReader = ColumnReader::createReader( - *this, std::move(derivedType), sEle, nextFileIdx++, maxDefine, maxRepeat); + auto listType = LogicalType::LIST(derivedType->copy()); + auto elementReader = ColumnReader::createReader(*this, std::move(derivedType), sEle, + nextFileIdx++, maxDefine, maxRepeat); return std::make_unique(*this, std::move(listType), sEle, thisIdx, maxDefine, maxRepeat, std::move(elementReader), context->getMemoryManager()); } // TODO check return value of derive type or should we only do this on read() - return ColumnReader::createReader( - *this, deriveLogicalType(sEle), sEle, nextFileIdx++, maxDefine, maxRepeat); + return ColumnReader::createReader(*this, deriveLogicalType(sEle), sEle, nextFileIdx++, + maxDefine, maxRepeat); } } @@ -343,8 +348,8 @@ std::unique_ptr ParquetReader::createReader() { void ParquetReader::prepareRowGroupBuffer(ParquetReaderScanState& state, uint64_t /*colIdx*/) { auto& group = getGroup(state); - state.rootReader->initializeRead( - state.groupIdxList[state.currentGroup], group.columns, *state.thriftFileProto); + state.rootReader->initializeRead(state.groupIdxList[state.currentGroup], group.columns, + *state.thriftFileProto); } uint64_t ParquetReader::getGroupSpan(ParquetReaderScanState& state) { @@ -355,8 +360,8 @@ uint64_t ParquetReader::getGroupSpan(ParquetReaderScanState& state) { // Set the min offset auto current_min_offset = UINT64_MAX; if (column_chunk.meta_data.__isset.dictionary_page_offset) { - current_min_offset = std::min( - current_min_offset, column_chunk.meta_data.dictionary_page_offset); + current_min_offset = std::min(current_min_offset, + column_chunk.meta_data.dictionary_page_offset); } if (column_chunk.meta_data.__isset.index_page_offset) { current_min_offset = @@ -365,8 +370,8 @@ uint64_t ParquetReader::getGroupSpan(ParquetReaderScanState& state) { current_min_offset = std::min(current_min_offset, column_chunk.meta_data.data_page_offset); min_offset = std::min(current_min_offset, min_offset); - max_offset = std::max( - max_offset, column_chunk.meta_data.total_compressed_size + current_min_offset); + max_offset = std::max(max_offset, + column_chunk.meta_data.total_compressed_size + current_min_offset); } return max_offset - min_offset; @@ -558,15 +563,21 @@ uint64_t ParquetReader::getGroupOffset(ParquetReaderScanState& state) { return minOffset; } -ParquetScanSharedState::ParquetScanSharedState( - common::ReaderConfig readerConfig, uint64_t numRows, main::ClientContext* context) +ParquetScanSharedState::ParquetScanSharedState(common::ReaderConfig readerConfig, uint64_t numRows, + main::ClientContext* context) : ScanFileSharedState{std::move(readerConfig), numRows, context} { readers.push_back( std::make_unique(this->readerConfig.filePaths[fileIdx], context)); + totalRowsGroups = 0; + for (auto i = fileIdx; i < this->readerConfig.getNumFiles(); i++) { + auto reader = std::make_unique(this->readerConfig.filePaths[i], context); + totalRowsGroups += reader->getNumRowsGroups(); + } + numBlocksReadByFiles = 0; } -static bool parquetSharedStateNext( - ParquetScanLocalState& localState, ParquetScanSharedState& sharedState) { +static bool parquetSharedStateNext(ParquetScanLocalState& localState, + ParquetScanSharedState& sharedState) { std::lock_guard mtx{sharedState.lock}; while (true) { if (sharedState.fileIdx >= sharedState.readerConfig.getNumFiles()) { @@ -574,11 +585,13 @@ static bool parquetSharedStateNext( } if (sharedState.blockIdx < sharedState.readers[sharedState.fileIdx]->getNumRowsGroups()) { localState.reader = sharedState.readers[sharedState.fileIdx].get(); - localState.reader->initializeScan( - *localState.state, {sharedState.blockIdx}, sharedState.context->getVFSUnsafe()); + localState.reader->initializeScan(*localState.state, {sharedState.blockIdx}, + sharedState.context->getVFSUnsafe()); sharedState.blockIdx++; return true; } else { + sharedState.numBlocksReadByFiles += + sharedState.readers[sharedState.fileIdx]->getNumRowsGroups(); sharedState.blockIdx = 0; sharedState.fileIdx++; if (sharedState.fileIdx >= sharedState.readerConfig.getNumFiles()) { @@ -596,8 +609,10 @@ static common::offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output if (input.localState == nullptr) { return 0; } - auto parquetScanLocalState = reinterpret_cast(input.localState); - auto parquetScanSharedState = reinterpret_cast(input.sharedState); + auto parquetScanLocalState = + ku_dynamic_cast(input.localState); + auto parquetScanSharedState = + ku_dynamic_cast(input.sharedState); do { parquetScanLocalState->reader->scan(*parquetScanLocalState->state, outputChunk); if (outputChunk.state->selVector->selectedSize > 0) { @@ -633,9 +648,10 @@ static void bindColumns(const ScanTableFuncBindInput* bindInput, } } -static std::unique_ptr bindFunc( - main::ClientContext* /*context*/, function::TableFuncBindInput* input) { - auto scanInput = reinterpret_cast(input); +static std::unique_ptr bindFunc(main::ClientContext* /*context*/, + function::TableFuncBindInput* input) { + auto scanInput = + ku_dynamic_cast(input); std::vector detectedColumnNames; std::vector detectedColumnTypes; bindColumns(scanInput, detectedColumnNames, detectedColumnTypes); @@ -644,8 +660,8 @@ static std::unique_ptr bindFunc( ReaderBindUtils::resolveColumns(scanInput->expectedColumnNames, detectedColumnNames, resultColumnNames, scanInput->expectedColumnTypes, detectedColumnTypes, resultColumnTypes); if (!scanInput->expectedColumnTypes.empty()) { - ReaderBindUtils::validateColumnTypes( - scanInput->expectedColumnNames, scanInput->expectedColumnTypes, detectedColumnTypes); + ReaderBindUtils::validateColumnTypes(scanInput->expectedColumnNames, + scanInput->expectedColumnTypes, detectedColumnTypes); } return std::make_unique(std::move(resultColumnTypes), std::move(resultColumnNames), scanInput->config.copy(), scanInput->context); @@ -653,20 +669,21 @@ static std::unique_ptr bindFunc( static std::unique_ptr initSharedState( TableFunctionInitInput& input) { - auto parquetScanBindData = reinterpret_cast(input.bindData); + auto parquetScanBindData = ku_dynamic_cast(input.bindData); row_idx_t numRows = 0; for (const auto& path : parquetScanBindData->config.filePaths) { auto reader = std::make_unique(path, parquetScanBindData->context); numRows += reader->getMetadata()->num_rows; } - return std::make_unique( - parquetScanBindData->config.copy(), numRows, parquetScanBindData->context); + return std::make_unique(parquetScanBindData->config.copy(), numRows, + parquetScanBindData->context); } static std::unique_ptr initLocalState( TableFunctionInitInput& /*input*/, TableFuncSharedState* state, storage::MemoryManager* /*mm*/) { - auto parquetScanSharedState = reinterpret_cast(state); + auto parquetScanSharedState = + ku_dynamic_cast(state); auto localState = std::make_unique(); if (!parquetSharedStateNext(*localState, *parquetScanSharedState)) { return nullptr; @@ -674,11 +691,23 @@ static std::unique_ptr initLocalState( return localState; } +static double progressFunc(TableFuncSharedState* sharedState) { + auto state = ku_dynamic_cast(sharedState); + if (state->fileIdx >= state->readerConfig.getNumFiles()) { + return 1.0; + } + if (state->totalRowsGroups == 0) { + return 0.0; + } + uint64_t totalReadSize = state->numBlocksReadByFiles + state->blockIdx; + return static_cast(totalReadSize) / state->totalRowsGroups; +} + function_set ParquetScanFunction::getFunctionSet() { function_set functionSet; functionSet.push_back( - std::make_unique(READ_PARQUET_FUNC_NAME, tableFunc, bindFunc, - initSharedState, initLocalState, std::vector{LogicalTypeID::STRING})); + std::make_unique(name, tableFunc, bindFunc, initSharedState, initLocalState, + progressFunc, std::vector{LogicalTypeID::STRING})); return functionSet; } diff --git a/src/processor/operator/persistent/reader/parquet/string_column_reader.cpp b/src/processor/operator/persistent/reader/parquet/string_column_reader.cpp index 0e1cc47cc45..ec2acbe216c 100644 --- a/src/processor/operator/persistent/reader/parquet/string_column_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/string_column_reader.cpp @@ -13,8 +13,8 @@ namespace processor { StringColumnReader::StringColumnReader(ParquetReader& reader, std::unique_ptr type, const kuzu_parquet::format::SchemaElement& schema, uint64_t schemaIdx, uint64_t maxDefine, uint64_t maxRepeat) - : TemplatedColumnReader( - reader, std::move(type), schema, schemaIdx, maxDefine, maxRepeat) { + : TemplatedColumnReader(reader, + std::move(type), schema, schemaIdx, maxDefine, maxRepeat) { fixedWidthStringLength = 0; if (schema.type == Type::FIXED_LEN_BYTE_ARRAY) { KU_ASSERT(schema.__isset.type_length); @@ -22,8 +22,8 @@ StringColumnReader::StringColumnReader(ParquetReader& reader, } } -uint32_t StringColumnReader::verifyString( - const char* strData, uint32_t strLen, const bool isVarchar) { +uint32_t StringColumnReader::verifyString(const char* strData, uint32_t strLen, + const bool isVarchar) { if (!isVarchar) { return strLen; } @@ -42,12 +42,12 @@ uint32_t StringColumnReader::verifyString( } uint32_t StringColumnReader::verifyString(const char* strData, uint32_t strLen) { - return verifyString( - strData, strLen, getDataType()->getLogicalTypeID() == common::LogicalTypeID::STRING); + return verifyString(strData, strLen, + getDataType()->getLogicalTypeID() == common::LogicalTypeID::STRING); } -void StringColumnReader::dictionary( - const std::shared_ptr& data, uint64_t numEntries) { +void StringColumnReader::dictionary(const std::shared_ptr& data, + uint64_t numEntries) { dict = data; dictStrs = std::unique_ptr(new common::ku_string_t[numEntries]); for (auto dictIdx = 0u; dictIdx < numEntries; dictIdx++) { @@ -68,14 +68,14 @@ void StringColumnReader::dictionary( } } -common::ku_string_t StringParquetValueConversion::dictRead( - ByteBuffer& /*dict*/, uint32_t& offset, ColumnReader& reader) { +common::ku_string_t StringParquetValueConversion::dictRead(ByteBuffer& /*dict*/, uint32_t& offset, + ColumnReader& reader) { auto& dictStrings = reinterpret_cast(reader).dictStrs; return dictStrings[offset]; } -common::ku_string_t StringParquetValueConversion::plainRead( - ByteBuffer& plainData, ColumnReader& reader) { +common::ku_string_t StringParquetValueConversion::plainRead(ByteBuffer& plainData, + ColumnReader& reader) { auto& scr = reinterpret_cast(reader); uint32_t strLen = scr.fixedWidthStringLength == 0 ? plainData.read() : scr.fixedWidthStringLength; diff --git a/src/processor/operator/persistent/reader/parquet/struct_column_reader.cpp b/src/processor/operator/persistent/reader/parquet/struct_column_reader.cpp index b1d70525aee..3e94d8216c0 100644 --- a/src/processor/operator/persistent/reader/parquet/struct_column_reader.cpp +++ b/src/processor/operator/persistent/reader/parquet/struct_column_reader.cpp @@ -49,8 +49,8 @@ uint64_t StructColumnReader::read(uint64_t numValuesToRead, parquet_filter_t& fi uint64_t numValuesRead = numValuesToRead; for (auto i = 0u; i < fieldVectors.size(); i++) { - auto numValuesChildrenRead = childReaders[i]->read( - numValuesToRead, filter, define_out, repeat_out, fieldVectors[i].get()); + auto numValuesChildrenRead = childReaders[i]->read(numValuesToRead, filter, define_out, + repeat_out, fieldVectors[i].get()); if (i == 0) { numValuesRead = numValuesChildrenRead; } else if (numValuesRead != numValuesChildrenRead) { @@ -72,7 +72,7 @@ void StructColumnReader::skip(uint64_t num_values) { static bool TypeHasExactRowCount(const common::LogicalType* type) { switch (type->getLogicalTypeID()) { - case common::LogicalTypeID::VAR_LIST: + case common::LogicalTypeID::LIST: case common::LogicalTypeID::MAP: return false; case common::LogicalTypeID::STRUCT: diff --git a/src/processor/operator/persistent/reader/rdf/rdf_reader.cpp b/src/processor/operator/persistent/reader/rdf/rdf_reader.cpp index 85dfdedf806..c1cc548b3f4 100644 --- a/src/processor/operator/persistent/reader/rdf/rdf_reader.cpp +++ b/src/processor/operator/persistent/reader/rdf/rdf_reader.cpp @@ -38,8 +38,8 @@ static SerdSyntax getSerdSyntax(FileType fileType) { void RdfReader::initInternal(SerdStatementSink statementSink) { KU_ASSERT(reader == nullptr); fp = fopen(this->filePath.c_str(), "rb"); - reader = serd_reader_new( - getSerdSyntax(fileType), this, nullptr, baseHandle, prefixHandle, statementSink, nullptr); + reader = serd_reader_new(getSerdSyntax(fileType), this, nullptr, baseHandle, prefixHandle, + statementSink, nullptr); serd_reader_set_error_sink(reader, errorHandle, this); auto fileName = this->filePath.substr(this->filePath.find_last_of("/\\") + 1); serd_reader_start_stream(reader, fp, reinterpret_cast(fileName.c_str()), true); @@ -62,8 +62,8 @@ SerdStatus RdfReader::baseHandle(void* handle, const SerdNode* baseNode) { return SERD_SUCCESS; } -SerdStatus RdfReader::prefixHandle( - void* handle, const SerdNode* nameNode, const SerdNode* uriNode) { +SerdStatus RdfReader::prefixHandle(void* handle, const SerdNode* nameNode, + const SerdNode* uriNode) { auto reader = reinterpret_cast(handle); serd_env_set_prefix(reader->env, nameNode, uriNode); return SERD_SUCCESS; @@ -142,8 +142,8 @@ std::string RdfReader::getAsString(const SerdNode* node) { return std::string((const char*)prefix.buf, prefix.len) + std::string((const char*)suffix.buf, suffix.len); } else if (rdfConfig.strict) { - throw RuntimeException(stringFormat( - "Cannot expand {}.", std::string((const char*)node->buf, node->n_bytes))); + throw RuntimeException(stringFormat("Cannot expand {}.", + std::string((const char*)node->buf, node->n_bytes))); } return std::string(); // expand fail return empty string. } diff --git a/src/processor/operator/persistent/reader/rdf/rdf_scan.cpp b/src/processor/operator/persistent/reader/rdf/rdf_scan.cpp index d3b0267d972..f268ddec033 100644 --- a/src/processor/operator/persistent/reader/rdf/rdf_scan.cpp +++ b/src/processor/operator/persistent/reader/rdf/rdf_scan.cpp @@ -48,8 +48,8 @@ void RdfScanSharedState::initReader() { reader->init(); } -std::pair RdfInMemScanSharedState::getRange( - const RdfStore& store_, uint64_t& cursor) { +std::pair RdfInMemScanSharedState::getRange(const RdfStore& store_, + uint64_t& cursor) { std::unique_lock lck{lock}; auto numTuplesToScan = std::min(batchSize, store_.size() - cursor); auto startIdx = cursor; @@ -69,98 +69,26 @@ static std::unique_ptr inMemScanInitSharedState( return std::make_unique(bindData->store); } -static std::unique_ptr initLocalState( - TableFunctionInitInput&, TableFuncSharedState*, storage::MemoryManager*) { +static std::unique_ptr initLocalState(TableFunctionInitInput&, + TableFuncSharedState*, storage::MemoryManager*) { return std::make_unique(); } -function_set RdfResourceScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(READ_RDF_RESOURCE_FUNC_NAME, scanTableFunc, nullptr, - initSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfLiteralScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(READ_RDF_LITERAL_FUNC_NAME, scanTableFunc, nullptr, - initSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfResourceTripleScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(READ_RDF_RESOURCE_TRIPLE_FUNC_NAME, scanTableFunc, - nullptr, initSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfLiteralTripleScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(READ_RDF_LITERAL_TRIPLE_FUNC_NAME, scanTableFunc, - nullptr, initSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function::function_set RdfAllTripleScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(READ_RDF_ALL_TRIPLE_FUNC_NAME, tableFunc, bindFunc, - initSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfResourceInMemScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(IN_MEM_READ_RDF_RESOURCE_FUNC_NAME, tableFunc, - nullptr, inMemScanInitSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfLiteralInMemScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(IN_MEM_READ_RDF_LITERAL_FUNC_NAME, tableFunc, - nullptr, inMemScanInitSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfResourceTripleInMemScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(IN_MEM_READ_RDF_RESOURCE_TRIPLE_FUNC_NAME, - tableFunc, nullptr, inMemScanInitSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -function_set RdfLiteralTripleInMemScan::getFunctionSet() { - function_set functionSet; - auto func = std::make_unique(IN_MEM_READ_RDF_LITERAL_TRIPLE_FUNC_NAME, tableFunc, - nullptr, inMemScanInitSharedState, initLocalState, std::vector{}); - functionSet.push_back(std::move(func)); - return functionSet; -} - -offset_t RdfAllTripleScan::tableFunc(TableFuncInput& input, TableFuncOutput&) { +static offset_t RdfAllTripleScanTableFunc(TableFuncInput& input, TableFuncOutput&) { auto sharedState = reinterpret_cast(input.sharedState); sharedState->readAll(); return 0; } -std::unique_ptr RdfAllTripleScan::bindFunc( - main::ClientContext*, function::TableFuncBindInput* input_) { +static std::unique_ptr RdfAllTripleScanBindFunc(main::ClientContext*, + function::TableFuncBindInput* input_) { auto input = ku_dynamic_cast(input_); return std::make_unique(std::vector{}, std::vector{}, input->config.copy(), input->context, std::make_shared()); } -offset_t RdfResourceInMemScan::tableFunc(TableFuncInput& input, TableFuncOutput& output) { +static offset_t RdfResourceInMemScanTableFunc(TableFuncInput& input, TableFuncOutput& output) { auto sharedState = ku_dynamic_cast(input.sharedState); auto sVector = output.dataChunk.getValueVector(0).get(); @@ -185,7 +113,7 @@ offset_t RdfResourceInMemScan::tableFunc(TableFuncInput& input, TableFuncOutput& return vectorPos; } -offset_t RdfLiteralInMemScan::tableFunc(TableFuncInput& input, TableFuncOutput& output) { +static offset_t RdfLiteralInMemScanTableFunc(TableFuncInput& input, TableFuncOutput& output) { auto sharedState = ku_dynamic_cast(input.sharedState); auto oVector = output.dataChunk.getValueVector(0).get(); @@ -202,7 +130,8 @@ offset_t RdfLiteralInMemScan::tableFunc(TableFuncInput& input, TableFuncOutput& return numTuplesToScan; } -offset_t RdfResourceTripleInMemScan::tableFunc(TableFuncInput& input, TableFuncOutput& output) { +static offset_t RdfResourceTripleInMemScanTableFunc(TableFuncInput& input, + TableFuncOutput& output) { auto sharedState = ku_dynamic_cast(input.sharedState); auto [startIdx, numTuplesToScan] = sharedState->getResourceTripleRange(); @@ -218,7 +147,7 @@ offset_t RdfResourceTripleInMemScan::tableFunc(TableFuncInput& input, TableFuncO return numTuplesToScan; } -offset_t RdfLiteralTripleInMemScan::tableFunc(TableFuncInput& input, TableFuncOutput& output) { +static offset_t RdfLiteralTripleInMemScanTableFunc(TableFuncInput& input, TableFuncOutput& output) { auto sharedState = ku_dynamic_cast(input.sharedState); auto [startIdx, numTuplesToScan] = sharedState->getLiteralTripleRange(); @@ -234,44 +163,154 @@ offset_t RdfLiteralTripleInMemScan::tableFunc(TableFuncInput& input, TableFuncOu return numTuplesToScan; } -std::unique_ptr RdfResourceScan::initSharedState( +static std::unique_ptr RdfResourceScanInitSharedState( TableFunctionInitInput& input) { auto bindData = reinterpret_cast(input.bindData); auto rdfConfig = RdfReaderConfig::construct(bindData->config.options); - return std::make_unique( - bindData->config.copy(), std::move(rdfConfig)); + return std::make_unique(bindData->config.copy(), + std::move(rdfConfig)); } -std::unique_ptr RdfLiteralScan::initSharedState( +static std::unique_ptr RdfLiteralScanInitSharedState( TableFunctionInitInput& input) { auto bindData = reinterpret_cast(input.bindData); auto rdfConfig = RdfReaderConfig::construct(bindData->config.options); - return std::make_unique( - bindData->config.copy(), std::move(rdfConfig)); + return std::make_unique(bindData->config.copy(), + std::move(rdfConfig)); } -std::unique_ptr RdfResourceTripleScan::initSharedState( +static std::unique_ptr RdfResourceTripleScanInitSharedState( TableFunctionInitInput& input) { auto bindData = reinterpret_cast(input.bindData); auto rdfConfig = RdfReaderConfig::construct(bindData->config.options); - return std::make_unique( - bindData->config.copy(), std::move(rdfConfig)); + return std::make_unique(bindData->config.copy(), + std::move(rdfConfig)); } -std::unique_ptr RdfLiteralTripleScan::initSharedState( +static std::unique_ptr RdfLiteralTripleScanInitSharedState( TableFunctionInitInput& input) { auto bindData = reinterpret_cast(input.bindData); auto rdfConfig = RdfReaderConfig::construct(bindData->config.options); - return std::make_unique( - bindData->config.copy(), std::move(rdfConfig)); + return std::make_unique(bindData->config.copy(), + std::move(rdfConfig)); } -std::unique_ptr RdfAllTripleScan::initSharedState( +static std::unique_ptr RdfAllTripleScanInitSharedState( TableFunctionInitInput& input) { auto bindData = ku_dynamic_cast(input.bindData); auto rdfConfig = RdfReaderConfig::construct(bindData->config.options); - return std::make_unique( - bindData->config.copy(), std::move(rdfConfig), bindData->store); + return std::make_unique(bindData->config.copy(), std::move(rdfConfig), + bindData->store); +} + +static double RdfResourceInMemScanProgressFunc(TableFuncSharedState* sharedState) { + auto rdfSharedState = + ku_dynamic_cast(sharedState); + uint64_t rtSize = + ku_dynamic_cast(rdfSharedState->store.get())->rtStore.size(); + if (rtSize == 0) { + return 0.0; + } + return static_cast(rdfSharedState->rtCursor) / rtSize; +} + +static double RdfLiteralInMemScanProgressFunc(TableFuncSharedState* sharedState) { + auto rdfSharedState = + ku_dynamic_cast(sharedState); + uint64_t ltSize = + ku_dynamic_cast(rdfSharedState->store.get())->ltStore.size(); + if (ltSize == 0) { + return 0.0; + } + return static_cast(rdfSharedState->ltCursor) / ltSize; +} + +static double RdfResourceTripleInMemScanProgressFunc(TableFuncSharedState* sharedState) { + auto rdfSharedState = + ku_dynamic_cast(sharedState); + TripleStore* store = ku_dynamic_cast(rdfSharedState->store.get()); + uint64_t size = store->rtStore.size() + store->ltStore.size(); + if (size == 0) { + return 0.0; + } + return static_cast(rdfSharedState->rtCursor + rdfSharedState->ltCursor) / size; +} + +function_set RdfResourceScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, scanTableFunc, nullptr, + RdfResourceScanInitSharedState, initLocalState, std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfLiteralScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, scanTableFunc, nullptr, + RdfLiteralScanInitSharedState, initLocalState, std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfResourceTripleScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, scanTableFunc, nullptr, + RdfResourceTripleScanInitSharedState, initLocalState, std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfLiteralTripleScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, scanTableFunc, nullptr, + RdfLiteralTripleScanInitSharedState, initLocalState, std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function::function_set RdfAllTripleScan::getFunctionSet() { + function_set functionSet; + auto func = + std::make_unique(name, RdfAllTripleScanTableFunc, RdfAllTripleScanBindFunc, + RdfAllTripleScanInitSharedState, initLocalState, std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfResourceInMemScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, RdfResourceInMemScanTableFunc, nullptr, + inMemScanInitSharedState, initLocalState, RdfResourceInMemScanProgressFunc, + std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfLiteralInMemScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, RdfLiteralInMemScanTableFunc, nullptr, + inMemScanInitSharedState, initLocalState, RdfLiteralInMemScanProgressFunc, + std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfResourceTripleInMemScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, RdfResourceTripleInMemScanTableFunc, nullptr, + inMemScanInitSharedState, initLocalState, RdfResourceTripleInMemScanProgressFunc, + std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; +} + +function_set RdfLiteralTripleInMemScan::getFunctionSet() { + function_set functionSet; + auto func = std::make_unique(name, RdfLiteralTripleInMemScanTableFunc, nullptr, + inMemScanInitSharedState, initLocalState, RdfLiteralInMemScanProgressFunc, + std::vector{}); + functionSet.push_back(std::move(func)); + return functionSet; } } // namespace processor diff --git a/src/processor/operator/persistent/reader/rdf/rdf_utils.cpp b/src/processor/operator/persistent/reader/rdf/rdf_utils.cpp index 2baa4bbeed2..59677613aec 100644 --- a/src/processor/operator/persistent/reader/rdf/rdf_utils.cpp +++ b/src/processor/operator/persistent/reader/rdf/rdf_utils.cpp @@ -29,8 +29,8 @@ common::LogicalTypeID RdfUtils::getLogicalTypeID(const std::string& type) { return LogicalTypeID::STRING; } -void RdfUtils::addRdfLiteral( - ValueVector* vector, uint32_t pos, const std::string& str, LogicalTypeID targetTypeID) { +void RdfUtils::addRdfLiteral(ValueVector* vector, uint32_t pos, const std::string& str, + LogicalTypeID targetTypeID) { auto resolveAsString = true; switch (targetTypeID) { case LogicalTypeID::INT64: { diff --git a/src/processor/operator/persistent/rel_batch_insert.cpp b/src/processor/operator/persistent/rel_batch_insert.cpp index 0b83ab14a9a..420813bb11a 100644 --- a/src/processor/operator/persistent/rel_batch_insert.cpp +++ b/src/processor/operator/persistent/rel_batch_insert.cpp @@ -4,6 +4,8 @@ #include "common/exception/message.h" #include "common/string_format.h" #include "processor/result/factorized_table.h" +#include "storage/local_storage/local_rel_table.h" +#include "storage/store/column_chunk.h" #include "storage/store/rel_table.h" using namespace kuzu::common; @@ -12,20 +14,22 @@ using namespace kuzu::storage; namespace kuzu { namespace processor { -void RelBatchInsert::initGlobalStateInternal(ExecutionContext* /*context*/) { - checkIfTableIsEmpty(); +void RelBatchInsert::initGlobalStateInternal(ExecutionContext* context) { + if (!context->clientContext->getClientConfig()->enableMultiCopy) { + checkIfTableIsEmpty(); + } sharedState->logBatchInsertWALRecord(); } -void RelBatchInsert::initLocalStateInternal( - ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) { +void RelBatchInsert::initLocalStateInternal(ResultSet* /*resultSet_*/, + ExecutionContext* /*context*/) { localState = std::make_unique(); auto relInfo = ku_dynamic_cast(info.get()); - localState->nodeGroup = NodeGroupFactory::createNodeGroup( - ColumnDataFormat::CSR, relInfo->columnTypes, relInfo->compressionEnabled); + localState->nodeGroup = NodeGroupFactory::createNodeGroup(ColumnDataFormat::CSR, + relInfo->columnTypes, relInfo->compressionEnabled); } -void RelBatchInsert::executeInternal(ExecutionContext* /*context*/) { +void RelBatchInsert::executeInternal(ExecutionContext* context) { auto relInfo = ku_dynamic_cast(info.get()); auto relTable = ku_dynamic_cast(sharedState->table); auto relLocalState = @@ -34,60 +38,80 @@ void RelBatchInsert::executeInternal(ExecutionContext* /*context*/) { relLocalState->nodeGroupIdx = partitionerSharedState->getNextPartition(relInfo->partitioningIdx); if (relLocalState->nodeGroupIdx == INVALID_PARTITION_IDX) { + // No more partitions left in the partitioning buffer. break; } - // Read the whole partition, and set to node group. - auto partitioningBuffer = partitionerSharedState->getPartitionBuffer( - relInfo->partitioningIdx, relLocalState->nodeGroupIdx); - auto startNodeOffset = StorageUtils::getStartOffsetOfNodeGroup(relLocalState->nodeGroupIdx); - for (auto dataChunk : partitioningBuffer->getChunks()) { - setOffsetToWithinNodeGroup( - dataChunk->getValueVector(relInfo->offsetVectorIdx).get(), startNodeOffset); - } - // Calculate num of source nodes in this node group. - // This will be used to set the num of values of the node group. - auto numNodes = std::min(StorageConstants::NODE_GROUP_SIZE, - partitionerSharedState->maxNodeOffsets[relInfo->partitioningIdx] - startNodeOffset + 1); - prepareCSRNodeGroup( - partitioningBuffer, startNodeOffset, relInfo->offsetVectorIdx, numNodes); - for (auto dataChunk : partitioningBuffer->getChunks()) { - localState->nodeGroup->write(dataChunk, relInfo->offsetVectorIdx); + if (relTable->isNewNodeGroup(context->clientContext->getTx(), relLocalState->nodeGroupIdx, + relInfo->direction)) { + appendNewNodeGroup(*relInfo, *relLocalState, *sharedState, *partitionerSharedState); + } else { + mergeNodeGroup(context, *relInfo, *relLocalState, *sharedState, + *partitionerSharedState); } - localState->nodeGroup->finalize(relLocalState->nodeGroupIdx); - // Flush node group to table. - relTable->append(localState->nodeGroup.get(), relInfo->direction); - sharedState->incrementNumRows(localState->nodeGroup->getNumRows()); - localState->nodeGroup->resetToEmpty(); } } -void RelBatchInsert::prepareCSRNodeGroup(DataChunkCollection* partition, - common::offset_t startNodeOffset, vector_idx_t offsetVectorIdx, offset_t numNodes) { - auto relInfo = ku_dynamic_cast(info.get()); - auto csrNodeGroup = ku_dynamic_cast(localState->nodeGroup.get()); +void RelBatchInsert::prepareCSRNodeGroup(const ChunkedNodeGroupCollection& partition, + offset_t startNodeOffset, const RelBatchInsertInfo& relInfo, + RelBatchInsertLocalState& localState, offset_t numNodes) { + auto csrNodeGroup = + ku_dynamic_cast(localState.nodeGroup.get()); auto& csrHeader = csrNodeGroup->getCSRHeader(); csrHeader.setNumValues(numNodes); // Populate start csr offsets and lengths for each node. - auto gaps = populateStartCSROffsetsAndLengths(csrHeader, numNodes, partition, offsetVectorIdx); - auto invalid = checkRelMultiplicityConstraint(csrHeader); + auto gaps = + populateStartCSROffsetsAndLengths(csrHeader, numNodes, partition, relInfo.offsetColumnID); + auto invalid = checkRelMultiplicityConstraint(csrHeader, relInfo); if (invalid.has_value()) { throw CopyException(ExceptionMessage::violateRelMultiplicityConstraint( - info->tableEntry->getName(), std::to_string(invalid.value() + startNodeOffset), - RelDataDirectionUtils::relDirectionToString(relInfo->direction))); + relInfo.tableEntry->getName(), std::to_string(invalid.value() + startNodeOffset), + RelDataDirectionUtils::relDirectionToString(relInfo.direction))); } // Resize csr data column chunks. offset_t csrChunkCapacity = csrHeader.getEndCSROffset(numNodes - 1) + csrHeader.getCSRLength(numNodes - 1); - localState->nodeGroup->resizeChunks(csrChunkCapacity); - for (auto dataChunk : partition->getChunks()) { - auto offsetVector = dataChunk->getValueVector(offsetVectorIdx).get(); - setOffsetFromCSROffsets(offsetVector, csrHeader.offset.get()); + localState.nodeGroup->resizeChunks(csrChunkCapacity); + for (auto& chunkedGroup : partition.getChunkedGroups()) { + auto& offsetChunk = chunkedGroup->getColumnChunkUnsafe(relInfo.offsetColumnID); + setOffsetFromCSROffsets(offsetChunk, *csrHeader.offset); } populateEndCSROffsets(csrHeader, gaps); } -void RelBatchInsert::populateEndCSROffsets( - CSRHeaderChunks& csrHeader, std::vector& gaps) { +void RelBatchInsert::mergeNodeGroup(ExecutionContext* context, const RelBatchInsertInfo& relInfo, + RelBatchInsertLocalState& localState, BatchInsertSharedState& sharedState, + const PartitionerSharedState& partitionerSharedState) { + auto relTable = ku_dynamic_cast(sharedState.table); + auto nodeGroupStartOffset = StorageUtils::getStartOffsetOfNodeGroup(localState.nodeGroupIdx); + auto localNG = std::make_unique(nodeGroupStartOffset, relInfo.columnTypes); + auto& partition = + partitionerSharedState.getPartitionBuffer(relInfo.partitioningIdx, localState.nodeGroupIdx); + auto& insertChunks = localNG->getInsesrtChunks(); + auto startNodeOffset = StorageUtils::getStartOffsetOfNodeGroup(localState.nodeGroupIdx); + auto numRels = 0u; + for (auto& chunkedGroup : partition.getChunkedGroups()) { + auto& offsetChunk = chunkedGroup->getColumnChunkUnsafe(relInfo.offsetColumnID); + numRels += chunkedGroup->getNumRows(); + setOffsetToWithinNodeGroup(offsetChunk, startNodeOffset); + std::vector> chunksToAppend; + for (auto i = 0u; i < chunkedGroup->getNumColumns(); i++) { + if (i == relInfo.offsetColumnID) { + // Skip the offset vector. + continue; + } + chunksToAppend.push_back(std::move(chunkedGroup->getColumnChunksUnsafe()[i])); + } + auto chunkedGroupToAppend = std::make_unique(std::move(chunksToAppend)); + insertChunks.appendChunkedGroup(&offsetChunk, std::move(chunkedGroupToAppend)); + } + relTable->getDirectedTableData(relInfo.direction) + ->prepareCommitNodeGroup(context->clientContext->getTx(), localState.nodeGroupIdx, + localNG.get()); + sharedState.incrementNumRows(numRels); +} + +void RelBatchInsert::populateEndCSROffsets(ChunkedCSRHeader& csrHeader, + std::vector& gaps) { auto csrOffsets = (offset_t*)csrHeader.offset->getData(); for (auto i = 0u; i < csrHeader.offset->getNumValues(); i++) { csrOffsets[i] += gaps[i]; @@ -103,8 +127,8 @@ length_t RelBatchInsert::getGapSize(length_t length) { length; } -std::vector RelBatchInsert::populateStartCSROffsetsAndLengths(CSRHeaderChunks& csrHeader, - offset_t numNodes, DataChunkCollection* partition, vector_idx_t offsetVectorIdx) { +std::vector RelBatchInsert::populateStartCSROffsetsAndLengths(ChunkedCSRHeader& csrHeader, + offset_t numNodes, const ChunkedNodeGroupCollection& partition, column_id_t offsetColumnID) { KU_ASSERT(numNodes == csrHeader.length->getNumValues() && numNodes == csrHeader.offset->getNumValues()); std::vector gaps; @@ -113,11 +137,10 @@ std::vector RelBatchInsert::populateStartCSROffsetsAndLengths(CSRHeade auto csrLengths = (length_t*)csrHeader.length->getData(); std::fill(csrLengths, csrLengths + numNodes, 0); // Calculate length for each node. Store the num of tuples of node i at csrLengths[i]. - for (auto chunk : partition->getChunks()) { - auto offsetVector = chunk->getValueVector(offsetVectorIdx); - for (auto i = 0u; i < offsetVector->state->selVector->selectedSize; i++) { - auto pos = offsetVector->state->selVector->selectedPositions[i]; - auto nodeOffset = offsetVector->getValue(pos); + for (auto& chunkedGroup : partition.getChunkedGroups()) { + auto& offsetChunk = chunkedGroup->getColumnChunk(offsetColumnID); + for (auto i = 0u; i < offsetChunk.getNumValues(); i++) { + auto nodeOffset = offsetChunk.getValue(i); KU_ASSERT(nodeOffset < numNodes); csrLengths[nodeOffset]++; } @@ -134,33 +157,58 @@ std::vector RelBatchInsert::populateStartCSROffsetsAndLengths(CSRHeade return gaps; } -void RelBatchInsert::setOffsetToWithinNodeGroup(ValueVector* vector, offset_t startOffset) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::INT64 && - vector->state->selVector->isUnfiltered()); - auto offsets = (offset_t*)vector->getData(); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { +void RelBatchInsert::setOffsetToWithinNodeGroup(ColumnChunk& chunk, offset_t startOffset) { + KU_ASSERT(chunk.getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID); + auto offsets = (offset_t*)chunk.getData(); + for (auto i = 0u; i < chunk.getNumValues(); i++) { offsets[i] -= startOffset; } } -void RelBatchInsert::setOffsetFromCSROffsets(ValueVector* offsetVector, ColumnChunk* offsetChunk) { - KU_ASSERT(offsetVector->dataType.getPhysicalType() == PhysicalTypeID::INT64 && - offsetVector->state->selVector->isUnfiltered()); - for (auto i = 0u; i < offsetVector->state->selVector->selectedSize; i++) { - auto nodeOffset = offsetVector->getValue(i); - auto csrOffset = offsetChunk->getValue(nodeOffset); - offsetVector->setValue(i, csrOffset); - offsetChunk->setValue(csrOffset + 1, nodeOffset); +void RelBatchInsert::setOffsetFromCSROffsets(ColumnChunk& nodeOffsetChunk, + ColumnChunk& csrOffsetChunk) { + KU_ASSERT(nodeOffsetChunk.getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID); + for (auto i = 0u; i < nodeOffsetChunk.getNumValues(); i++) { + auto nodeOffset = nodeOffsetChunk.getValue(i); + auto csrOffset = csrOffsetChunk.getValue(nodeOffset); + nodeOffsetChunk.setValue(csrOffset, i); + csrOffsetChunk.setValue(csrOffset + 1, nodeOffset); } } -std::optional RelBatchInsert::checkRelMultiplicityConstraint( - const storage::CSRHeaderChunks& csrHeader) { - auto relInfo = ku_dynamic_cast(info.get()); +void RelBatchInsert::appendNewNodeGroup(const RelBatchInsertInfo& relInfo, + RelBatchInsertLocalState& localState, BatchInsertSharedState& sharedState, + const PartitionerSharedState& partitionerSharedState) { + auto nodeGroupIdx = localState.nodeGroupIdx; + auto& partitioningBuffer = + partitionerSharedState.getPartitionBuffer(relInfo.partitioningIdx, localState.nodeGroupIdx); + auto startNodeOffset = StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); + for (auto& chunkedGroup : partitioningBuffer.getChunkedGroups()) { + setOffsetToWithinNodeGroup(chunkedGroup->getColumnChunkUnsafe(relInfo.offsetColumnID), + startNodeOffset); + } + // Calculate num of source nodes in this node group. + // This will be used to set the num of values of the node group. + auto numNodes = std::min(StorageConstants::NODE_GROUP_SIZE, + partitionerSharedState.maxNodeOffsets[relInfo.partitioningIdx] - startNodeOffset + 1); + prepareCSRNodeGroup(partitioningBuffer, startNodeOffset, relInfo, localState, numNodes); + for (auto& chunkedGroup : partitioningBuffer.getChunkedGroups()) { + localState.nodeGroup->write(*chunkedGroup, relInfo.offsetColumnID); + } + localState.nodeGroup->finalize(nodeGroupIdx); + // Flush node group to table. + auto relTable = ku_dynamic_cast(sharedState.table); + relTable->append(localState.nodeGroup.get(), relInfo.direction); + sharedState.incrementNumRows(localState.nodeGroup->getNumRows()); + localState.nodeGroup->resetToEmpty(); +} + +std::optional RelBatchInsert::checkRelMultiplicityConstraint( + const storage::ChunkedCSRHeader& csrHeader, const RelBatchInsertInfo& relInfo) { auto relTableEntry = ku_dynamic_cast( - info->tableEntry); - if (!relTableEntry->isSingleMultiplicity(relInfo->direction)) { + relInfo.tableEntry); + if (!relTableEntry->isSingleMultiplicity(relInfo.direction)) { return std::nullopt; } for (auto i = 0u; i < csrHeader.length->getNumValues(); i++) { @@ -176,11 +224,11 @@ void RelBatchInsert::finalize(ExecutionContext* context) { if (relInfo->direction == RelDataDirection::BWD) { KU_ASSERT( relInfo->partitioningIdx == partitionerSharedState->partitioningBuffers.size() - 1); - sharedState->setNumTuplesForTable(); + sharedState->updateNumTuplesForTable(); auto outputMsg = stringFormat("{} number of tuples has been copied to table {}.", sharedState->getNumRows(), info->tableEntry->getName()); - FactorizedTableUtils::appendStringToTable( - sharedState->fTable.get(), outputMsg, context->clientContext->getMemoryManager()); + FactorizedTableUtils::appendStringToTable(sharedState->fTable.get(), outputMsg, + context->clientContext->getMemoryManager()); } sharedState->numRows.store(0); partitionerSharedState->resetState(); diff --git a/src/processor/operator/persistent/set_executor.cpp b/src/processor/operator/persistent/set_executor.cpp index 67bd22ab82f..ba2ae69f0bb 100644 --- a/src/processor/operator/persistent/set_executor.cpp +++ b/src/processor/operator/persistent/set_executor.cpp @@ -51,8 +51,9 @@ void SingleLabelNodeSetExecutor::set(ExecutionContext* context) { KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); auto lhsPos = nodeIDVector->state->selVector->selectedPositions[0]; auto rhsPos = rhsVector->state->selVector->selectedPositions[0]; - setInfo.table->update( - context->clientContext->getTx(), setInfo.columnID, nodeIDVector, rhsVector); + auto updateState = std::make_unique(setInfo.columnID, + *nodeIDVector, *rhsVector); + setInfo.table->update(context->clientContext->getTx(), *updateState); if (lhsVector != nullptr) { writeToPropertyVector(nodeIDVector, lhsVector, lhsPos, rhsVector, rhsPos); } @@ -72,8 +73,9 @@ void MultiLabelNodeSetExecutor::set(ExecutionContext* context) { } auto rhsPos = rhsVector->state->selVector->selectedPositions[0]; auto& setInfo = tableIDToSetInfo.at(nodeID.tableID); - setInfo.table->update( - context->clientContext->getTx(), setInfo.columnID, nodeIDVector, rhsVector); + auto updateState = std::make_unique(setInfo.columnID, + *nodeIDVector, *rhsVector); + setInfo.table->update(context->clientContext->getTx(), *updateState); if (lhsVector != nullptr) { KU_ASSERT(lhsVector->state->selVector->selectedSize == 1); writeToPropertyVector(nodeIDVector, lhsVector, lhsPos, rhsVector, rhsPos); @@ -102,8 +104,8 @@ std::vector> RelSetExecutor::copy( } // Assume both input vectors are flat. Should be removed eventually. -static void writeToPropertyVector( - ValueVector* relIDVector, ValueVector* propertyVector, ValueVector* rhsVector) { +static void writeToPropertyVector(ValueVector* relIDVector, ValueVector* propertyVector, + ValueVector* rhsVector) { KU_ASSERT(propertyVector->state->selVector->selectedSize == 1); auto propertyVectorPos = propertyVector->state->selVector->selectedPositions[0]; KU_ASSERT(rhsVector->state->selVector->selectedSize == 1); @@ -120,8 +122,9 @@ void SingleLabelRelSetExecutor::set(ExecutionContext* context) { return; } evaluator->evaluate(context->clientContext); - table->update(context->clientContext->getTx(), columnID, srcNodeIDVector, dstNodeIDVector, - relIDVector, rhsVector); + auto updateState = std::make_unique(columnID, *srcNodeIDVector, + *dstNodeIDVector, *relIDVector, *rhsVector); + table->update(context->clientContext->getTx(), *updateState); if (lhsVector != nullptr) { writeToPropertyVector(relIDVector, lhsVector, rhsVector); } @@ -138,9 +141,10 @@ void MultiLabelRelSetExecutor::set(ExecutionContext* context) { } return; } - auto [table, propertyID] = tableIDToTableAndColumnID.at(relID.tableID); - table->update(context->clientContext->getTx(), propertyID, srcNodeIDVector, dstNodeIDVector, - relIDVector, rhsVector); + auto [table, columnID] = tableIDToTableAndColumnID.at(relID.tableID); + auto updateState = std::make_unique(columnID, *srcNodeIDVector, + *dstNodeIDVector, *relIDVector, *rhsVector); + table->update(context->clientContext->getTx(), *updateState); if (lhsVector != nullptr) { writeToPropertyVector(relIDVector, lhsVector, rhsVector); } diff --git a/src/processor/operator/persistent/writer/parquet/CMakeLists.txt b/src/processor/operator/persistent/writer/parquet/CMakeLists.txt index 829581ddd73..b379ed42820 100644 --- a/src/processor/operator/persistent/writer/parquet/CMakeLists.txt +++ b/src/processor/operator/persistent/writer/parquet/CMakeLists.txt @@ -6,7 +6,7 @@ add_library(kuzu_processor_operator_parquet_writer interval_column_writer.cpp struct_column_writer.cpp string_column_writer.cpp - var_list_column_writer.cpp + list_column_writer.cpp parquet_writer.cpp parquet_rle_bp_encoder.cpp) diff --git a/src/processor/operator/persistent/writer/parquet/basic_column_writer.cpp b/src/processor/operator/persistent/writer/parquet/basic_column_writer.cpp index 9b59cdfe9cf..0e58c1ad862 100644 --- a/src/processor/operator/persistent/writer/parquet/basic_column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/basic_column_writer.cpp @@ -90,8 +90,8 @@ void BasicColumnWriter::beginWrite(ColumnWriterState& writerState) { nextPage(state); } -void BasicColumnWriter::write( - ColumnWriterState& writerState, common::ValueVector* vector, uint64_t count) { +void BasicColumnWriter::write(ColumnWriterState& writerState, common::ValueVector* vector, + uint64_t count) { auto& state = reinterpret_cast(writerState); uint64_t remaining = count; @@ -191,12 +191,12 @@ void BasicColumnWriter::nextPage(BasicColumnWriterState& state) { state.currentPage++; // write the repetition levels - writeLevels( - *writeInfo.writer, state.repetitionLevels, maxRepeat, pageInfo.offset, pageInfo.rowCount); + writeLevels(*writeInfo.writer, state.repetitionLevels, maxRepeat, pageInfo.offset, + pageInfo.rowCount); // write the definition levels - writeLevels( - *writeInfo.writer, state.definitionLevels, maxDefine, pageInfo.offset, pageInfo.rowCount); + writeLevels(*writeInfo.writer, state.definitionLevels, maxDefine, pageInfo.offset, + pageInfo.rowCount); } void BasicColumnWriter::flushPage(BasicColumnWriterState& state) { @@ -265,8 +265,8 @@ void BasicColumnWriter::writeDictionary(BasicColumnWriterState& state, state.writeInfo.insert(state.writeInfo.begin(), std::move(writeInfo)); } -void BasicColumnWriter::setParquetStatistics( - BasicColumnWriterState& state, kuzu_parquet::format::ColumnChunk& column) { +void BasicColumnWriter::setParquetStatistics(BasicColumnWriterState& state, + kuzu_parquet::format::ColumnChunk& column) { if (maxRepeat == 0) { column.meta_data.statistics.null_count = nullCount; column.meta_data.statistics.__isset.null_count = true; diff --git a/src/processor/operator/persistent/writer/parquet/boolean_column_writer.cpp b/src/processor/operator/persistent/writer/parquet/boolean_column_writer.cpp index 2565bc47893..a238466c26f 100644 --- a/src/processor/operator/persistent/writer/parquet/boolean_column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/boolean_column_writer.cpp @@ -31,8 +31,8 @@ void BooleanColumnWriter::writeVector(common::Serializer& temp_writer, } } -void BooleanColumnWriter::flushPageState( - common::Serializer& temp_writer, ColumnWriterPageState* writerPageState) { +void BooleanColumnWriter::flushPageState(common::Serializer& temp_writer, + ColumnWriterPageState* writerPageState) { auto state = reinterpret_cast(writerPageState); if (state->bytePos > 0) { temp_writer.write(state->byte); diff --git a/src/processor/operator/persistent/writer/parquet/column_writer.cpp b/src/processor/operator/persistent/writer/parquet/column_writer.cpp index 9b0b0dc6be3..b03df1c5954 100644 --- a/src/processor/operator/persistent/writer/parquet/column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/column_writer.cpp @@ -4,11 +4,11 @@ #include "function/cast/functions/numeric_limits.h" #include "processor/operator/persistent/writer/parquet/boolean_column_writer.h" #include "processor/operator/persistent/writer/parquet/interval_column_writer.h" +#include "processor/operator/persistent/writer/parquet/list_column_writer.h" #include "processor/operator/persistent/writer/parquet/parquet_writer.h" #include "processor/operator/persistent/writer/parquet/standard_column_writer.h" #include "processor/operator/persistent/writer/parquet/string_column_writer.h" #include "processor/operator/persistent/writer/parquet/struct_column_writer.h" -#include "processor/operator/persistent/writer/parquet/var_list_column_writer.h" #include "snappy/snappy.h" namespace kuzu { @@ -89,8 +89,8 @@ std::unique_ptr ColumnWriter::createWriterRecursive( std::move(schemaPathToCreate), maxRepeatToCreate, maxDefineToCreate, std::move(childWriters), canHaveNullsToCreate); } - case LogicalTypeID::VAR_LIST: { - auto childType = VarListType::getChildType(type); + case LogicalTypeID::LIST: { + auto childType = ListType::getChildType(type); // Set up the two schema elements for the list // for some reason we only set the converted type in the OPTIONAL element // first an OPTIONAL element. @@ -119,9 +119,8 @@ std::unique_ptr ColumnWriter::createWriterRecursive( auto child_writer = createWriterRecursive(schemas, writer, childType, "element", schemaPathToCreate, mm, maxRepeatToCreate + 1, maxDefineToCreate + 2); - return std::make_unique(writer, schemaIdx, - std::move(schemaPathToCreate), maxRepeatToCreate, maxDefineToCreate, - std::move(child_writer), canHaveNullsToCreate); + return std::make_unique(writer, schemaIdx, std::move(schemaPathToCreate), + maxRepeatToCreate, maxDefineToCreate, std::move(child_writer), canHaveNullsToCreate); } case LogicalTypeID::MAP: { // Maps are stored as follows in parquet: @@ -155,8 +154,8 @@ std::unique_ptr ColumnWriter::createWriterRecursive( schemaPathToCreate.emplace_back("key_value"); // Construct the child types recursively. - std::vector kvTypes{ - MapType::getKeyType(type), MapType::getValueType(type)}; + std::vector kvTypes{MapType::getKeyType(type), + MapType::getValueType(type)}; std::vector kvNames{"key", "value"}; std::vector> childrenWriters; childrenWriters.reserve(2); @@ -168,7 +167,7 @@ std::unique_ptr ColumnWriter::createWriterRecursive( auto structWriter = std::make_unique(writer, schemaIdx, schemaPathToCreate, maxRepeatToCreate, maxDefineToCreate, std::move(childrenWriters), canHaveNullsToCreate); - return std::make_unique(writer, schemaIdx, schemaPathToCreate, + return std::make_unique(writer, schemaIdx, schemaPathToCreate, maxRepeatToCreate, maxDefineToCreate, std::move(structWriter), canHaveNullsToCreate); } default: { diff --git a/src/processor/operator/persistent/writer/parquet/interval_column_writer.cpp b/src/processor/operator/persistent/writer/parquet/interval_column_writer.cpp index 089e86428ff..d1a7b1bacae 100644 --- a/src/processor/operator/persistent/writer/parquet/interval_column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/interval_column_writer.cpp @@ -28,8 +28,8 @@ void IntervalColumnWriter::writeVector(common::Serializer& bufferedSerializer, auto pos = getVectorPos(vector, r); if (!vector->isNull(pos)) { writeParquetInterval(vector->getValue(pos), tmpIntervalBuf); - bufferedSerializer.write( - tmpIntervalBuf, common::ParquetConstants::PARQUET_INTERVAL_SIZE); + bufferedSerializer.write(tmpIntervalBuf, + common::ParquetConstants::PARQUET_INTERVAL_SIZE); } } } diff --git a/src/processor/operator/persistent/writer/parquet/var_list_column_writer.cpp b/src/processor/operator/persistent/writer/parquet/list_column_writer.cpp similarity index 84% rename from src/processor/operator/persistent/writer/parquet/var_list_column_writer.cpp rename to src/processor/operator/persistent/writer/parquet/list_column_writer.cpp index 43cd40a5181..c885580dd0c 100644 --- a/src/processor/operator/persistent/writer/parquet/var_list_column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/list_column_writer.cpp @@ -1,34 +1,34 @@ -#include "processor/operator/persistent/writer/parquet/var_list_column_writer.h" +#include "processor/operator/persistent/writer/parquet/list_column_writer.h" namespace kuzu { namespace processor { using namespace kuzu_parquet::format; -std::unique_ptr VarListColumnWriter::initializeWriteState( +std::unique_ptr ListColumnWriter::initializeWriteState( kuzu_parquet::format::RowGroup& rowGroup) { auto result = std::make_unique(rowGroup, rowGroup.columns.size()); result->childState = childWriter->initializeWriteState(rowGroup); return result; } -bool VarListColumnWriter::hasAnalyze() { +bool ListColumnWriter::hasAnalyze() { return childWriter->hasAnalyze(); } -void VarListColumnWriter::analyze(ColumnWriterState& writerState, ColumnWriterState* /*parent*/, +void ListColumnWriter::analyze(ColumnWriterState& writerState, ColumnWriterState* /*parent*/, common::ValueVector* vector, uint64_t /*count*/) { auto& state = reinterpret_cast(writerState); childWriter->analyze(*state.childState, &writerState, common::ListVector::getDataVector(vector), common::ListVector::getDataVectorSize(vector)); } -void VarListColumnWriter::finalizeAnalyze(ColumnWriterState& writerState) { +void ListColumnWriter::finalizeAnalyze(ColumnWriterState& writerState) { auto& state = reinterpret_cast(writerState); childWriter->finalizeAnalyze(*state.childState); } -void VarListColumnWriter::prepare(ColumnWriterState& writerState, ColumnWriterState* parent, +void ListColumnWriter::prepare(ColumnWriterState& writerState, ColumnWriterState* parent, common::ValueVector* vector, uint64_t count) { auto& state = reinterpret_cast(writerState); @@ -85,19 +85,19 @@ void VarListColumnWriter::prepare(ColumnWriterState& writerState, ColumnWriterSt common::ListVector::getDataVectorSize(vector)); } -void VarListColumnWriter::beginWrite(ColumnWriterState& state_p) { +void ListColumnWriter::beginWrite(ColumnWriterState& state_p) { auto& state = reinterpret_cast(state_p); childWriter->beginWrite(*state.childState); } -void VarListColumnWriter::write( - ColumnWriterState& writerState, common::ValueVector* vector, uint64_t /*count*/) { +void ListColumnWriter::write(ColumnWriterState& writerState, common::ValueVector* vector, + uint64_t /*count*/) { auto& state = reinterpret_cast(writerState); childWriter->write(*state.childState, common::ListVector::getDataVector(vector), common::ListVector::getDataVectorSize(vector)); } -void VarListColumnWriter::finalizeWrite(ColumnWriterState& writerState) { +void ListColumnWriter::finalizeWrite(ColumnWriterState& writerState) { auto& state = reinterpret_cast(writerState); childWriter->finalizeWrite(*state.childState); } diff --git a/src/processor/operator/persistent/writer/parquet/parquet_writer.cpp b/src/processor/operator/persistent/writer/parquet/parquet_writer.cpp index f2dfd8db93d..2a3e812e55d 100644 --- a/src/processor/operator/persistent/writer/parquet/parquet_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/parquet_writer.cpp @@ -234,8 +234,8 @@ void ParquetWriter::prepareRowGroup(FactorizedTable& ft, PreparedRowGroup& resul while (numTuplesRead < ft.getNumTuples()) { readFromFT(ft, vectorsToRead, numTuplesRead); for (auto i = 0u; i < columnWriters.size(); i++) { - columnWriters[i]->write( - *writerStates[i], vectorsToRead[i], getNumTuples(unflatDataChunkToRead.get())); + columnWriters[i]->write(*writerStates[i], vectorsToRead[i], + getNumTuples(unflatDataChunkToRead.get())); } } @@ -262,8 +262,8 @@ void ParquetWriter::flushRowGroup(PreparedRowGroup& rowGroup) { fileMetaData.num_rows += parquetRowGroup.num_rows; } -void ParquetWriter::readFromFT( - FactorizedTable& ft, std::vector vectorsToRead, uint64_t& numTuplesRead) { +void ParquetWriter::readFromFT(FactorizedTable& ft, std::vector vectorsToRead, + uint64_t& numTuplesRead) { auto numTuplesToRead = ft.getTableSchema()->getNumUnflatColumns() != 0 ? 1 : @@ -276,8 +276,8 @@ void ParquetWriter::finalize() { auto startOffset = fileOffset; fileMetaData.write(protocol.get()); uint32_t metadataSize = fileOffset - startOffset; - fileInfo->writeFile( - reinterpret_cast(&metadataSize), sizeof(metadataSize), fileOffset); + fileInfo->writeFile(reinterpret_cast(&metadataSize), sizeof(metadataSize), + fileOffset); fileOffset += sizeof(uint32_t); // Parquet files also end with the string "PAR1". diff --git a/src/processor/operator/persistent/writer/parquet/string_column_writer.cpp b/src/processor/operator/persistent/writer/parquet/string_column_writer.cpp index 5c18604a4dc..021428c5fee 100644 --- a/src/processor/operator/persistent/writer/parquet/string_column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/string_column_writer.cpp @@ -154,8 +154,8 @@ void StringColumnWriter::writeVector(common::Serializer& serializer, } } -void StringColumnWriter::flushPageState( - common::Serializer& serializer, ColumnWriterPageState* writerPageState) { +void StringColumnWriter::flushPageState(common::Serializer& serializer, + ColumnWriterPageState* writerPageState) { auto pageState = reinterpret_cast(writerPageState); if (pageState->bitWidth != 0) { if (!pageState->writtenValue) { @@ -168,8 +168,8 @@ void StringColumnWriter::flushPageState( } } -void StringColumnWriter::flushDictionary( - BasicColumnWriterState& writerState, ColumnWriterStatistics* writerStats) { +void StringColumnWriter::flushDictionary(BasicColumnWriterState& writerState, + ColumnWriterStatistics* writerStats) { auto stats = reinterpret_cast(writerStats); auto& state = reinterpret_cast(writerState); if (!state.isDictionaryEncoded()) { @@ -195,8 +195,8 @@ void StringColumnWriter::flushDictionary( writeDictionary(state, std::move(bufferedSerializer), values.size()); } -uint64_t StringColumnWriter::getRowSize( - ValueVector* vector, uint64_t index, BasicColumnWriterState& writerState) { +uint64_t StringColumnWriter::getRowSize(ValueVector* vector, uint64_t index, + BasicColumnWriterState& writerState) { auto& state = reinterpret_cast(writerState); if (state.isDictionaryEncoded()) { return (state.keyBitWidth + 7) / 8; diff --git a/src/processor/operator/persistent/writer/parquet/struct_column_writer.cpp b/src/processor/operator/persistent/writer/parquet/struct_column_writer.cpp index 3355740949b..bf2f5c2e75c 100644 --- a/src/processor/operator/persistent/writer/parquet/struct_column_writer.cpp +++ b/src/processor/operator/persistent/writer/parquet/struct_column_writer.cpp @@ -35,8 +35,8 @@ void StructColumnWriter::analyze(ColumnWriterState& state_p, ColumnWriterState* for (auto child_idx = 0u; child_idx < childWriters.size(); child_idx++) { // Need to check again. It might be that just one child needs it but the rest not if (childWriters[child_idx]->hasAnalyze()) { - childWriters[child_idx]->analyze( - *state.childStates[child_idx], &state_p, childVectors[child_idx].get(), count); + childWriters[child_idx]->analyze(*state.childStates[child_idx], &state_p, + childVectors[child_idx].get(), count); } } } @@ -51,8 +51,8 @@ void StructColumnWriter::finalizeAnalyze(ColumnWriterState& state_p) { } } -void StructColumnWriter::prepare( - ColumnWriterState& state_p, ColumnWriterState* parent, ValueVector* vector, uint64_t count) { +void StructColumnWriter::prepare(ColumnWriterState& state_p, ColumnWriterState* parent, + ValueVector* vector, uint64_t count) { auto& state = reinterpret_cast(state_p); if (parent) { // propagate empty entries from the parent @@ -61,12 +61,12 @@ void StructColumnWriter::prepare( } } handleRepeatLevels(state_p, parent); - handleDefineLevels( - state_p, parent, vector, count, ParquetConstants::PARQUET_DEFINE_VALID, maxDefine - 1); + handleDefineLevels(state_p, parent, vector, count, ParquetConstants::PARQUET_DEFINE_VALID, + maxDefine - 1); auto& child_vectors = StructVector::getFieldVectors(vector); for (auto child_idx = 0u; child_idx < childWriters.size(); child_idx++) { - childWriters[child_idx]->prepare( - *state.childStates[child_idx], &state_p, child_vectors[child_idx].get(), count); + childWriters[child_idx]->prepare(*state.childStates[child_idx], &state_p, + child_vectors[child_idx].get(), count); } } @@ -81,8 +81,8 @@ void StructColumnWriter::write(ColumnWriterState& state_p, ValueVector* vector, auto& state = reinterpret_cast(state_p); auto& child_vectors = StructVector::getFieldVectors(vector); for (auto child_idx = 0u; child_idx < childWriters.size(); child_idx++) { - childWriters[child_idx]->write( - *state.childStates[child_idx], child_vectors[child_idx].get(), count); + childWriters[child_idx]->write(*state.childStates[child_idx], + child_vectors[child_idx].get(), count); } } diff --git a/src/processor/operator/physical_operator.cpp b/src/processor/operator/physical_operator.cpp index 625c095303f..df0f508137e 100644 --- a/src/processor/operator/physical_operator.cpp +++ b/src/processor/operator/physical_operator.cpp @@ -1,5 +1,7 @@ #include "processor/operator/physical_operator.h" +#include "common/exception/interrupt.h" + using namespace kuzu::common; namespace kuzu { @@ -7,12 +9,14 @@ namespace processor { // LCOV_EXCL_START std::string PhysicalOperatorUtils::operatorTypeToString(PhysicalOperatorType operatorType) { switch (operatorType) { - case PhysicalOperatorType::ADD_PROPERTY: - return "ADD_PROPERTY"; + case PhysicalOperatorType::ALTER: + return "ALTER"; case PhysicalOperatorType::AGGREGATE: return "AGGREGATE"; case PhysicalOperatorType::AGGREGATE_SCAN: return "AGGREGATE_SCAN"; + case PhysicalOperatorType::ATTACH_DATABASE: + return "ATTACH_DATABASE"; case PhysicalOperatorType::BATCH_INSERT: return "BATCH_INSERT"; case PhysicalOperatorType::STANDALONE_CALL: @@ -23,24 +27,20 @@ std::string PhysicalOperatorUtils::operatorTypeToString(PhysicalOperatorType ope return "COPY_RDF"; case PhysicalOperatorType::CREATE_MACRO: return "CREATE_MACRO"; + case PhysicalOperatorType::DETACH_DATABASE: + return "DETACH_DATABASE"; case PhysicalOperatorType::READER: return "READER"; case PhysicalOperatorType::INSERT: return "INSERT"; - case PhysicalOperatorType::CREATE_NODE_TABLE: - return "CREATE_NODE_TABLE"; - case PhysicalOperatorType::CREATE_REL_TABLE: - return "CREATE_REL_TABLE"; - case PhysicalOperatorType::CREATE_RDF_GRAPH: - return "CREATE_RDF_TABLE"; + case PhysicalOperatorType::CREATE_TABLE: + return "CREATE_TABLE"; case PhysicalOperatorType::CROSS_PRODUCT: return "CROSS_PRODUCT"; case PhysicalOperatorType::DELETE_NODE: return "DELETE_NODE"; case PhysicalOperatorType::DELETE_REL: return "DELETE_REL"; - case PhysicalOperatorType::DROP_PROPERTY: - return "DROP_PROPERTY"; case PhysicalOperatorType::DROP_TABLE: return "DROP_TABLE"; case PhysicalOperatorType::EMPTY_RESULT: @@ -175,12 +175,22 @@ void PhysicalOperator::initLocalState(ResultSet* resultSet_, ExecutionContext* c if (!isSource()) { children[0]->initLocalState(resultSet_, context); } - transaction = context->clientContext->getTx(); resultSet = resultSet_; registerProfilingMetrics(context->profiler); initLocalStateInternal(resultSet_, context); } +bool PhysicalOperator::getNextTuple(ExecutionContext* context) { + if (context->clientContext->interrupted()) { + throw InterruptException{}; + } + metrics->executionTime.start(); + auto result = getNextTuplesInternal(context); + context->clientContext->getProgressBar()->updateProgress(getProgress(context)); + metrics->executionTime.stop(); + return result; +} + void PhysicalOperator::registerProfilingMetrics(Profiler* profiler) { auto executionTime = profiler->registerTimeMetric(getTimeMetricKey()); auto numOutputTuple = profiler->registerNumericMetric(getNumTupleMetricKey()); @@ -215,5 +225,9 @@ std::vector PhysicalOperator::getProfilerAttributes(Profiler& profi return result; } +double PhysicalOperator::getProgress(ExecutionContext* /*context*/) const { + return 0; +} + } // namespace processor } // namespace kuzu diff --git a/src/processor/operator/recursive_extend/path_property_probe.cpp b/src/processor/operator/recursive_extend/path_property_probe.cpp index fc2166d4eed..62d8ea2adc7 100644 --- a/src/processor/operator/recursive_extend/path_property_probe.cpp +++ b/src/processor/operator/recursive_extend/path_property_probe.cpp @@ -7,8 +7,8 @@ using namespace kuzu::common; namespace kuzu { namespace processor { -void PathPropertyProbe::initLocalStateInternal( - ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) { +void PathPropertyProbe::initLocalStateInternal(ResultSet* /*resultSet_*/, + ExecutionContext* /*context*/) { localState = std::make_unique(); vectors = std::make_unique(); auto pathVector = resultSet->getValueVector(info->pathPos); @@ -102,8 +102,8 @@ void PathPropertyProbe::probe(kuzu::processor::JoinHashTable* hashTable, uint64_ for (auto j = 0u; j < propertyVectors.size(); ++j) { auto propertyVector = propertyVectors[j]; auto colIdx = colIndicesToScan[j]; - factorizedTable->readFlatColToFlatVector( - tuple, colIdx, *propertyVector, sizeProbed + i); + factorizedTable->readFlatColToFlatVector(tuple, colIdx, *propertyVector, + sizeProbed + i); } } } diff --git a/src/processor/operator/recursive_extend/recursive_join.cpp b/src/processor/operator/recursive_extend/recursive_join.cpp index a44af6439a4..7b6e31bd0f6 100644 --- a/src/processor/operator/recursive_extend/recursive_join.cpp +++ b/src/processor/operator/recursive_extend/recursive_join.cpp @@ -11,7 +11,7 @@ namespace kuzu { namespace processor { void RecursiveJoin::initLocalStateInternal(ResultSet* /*resultSet_*/, ExecutionContext* context) { - populateTargetDstNodes(); + populateTargetDstNodes(context); vectors = std::make_unique(); vectors->srcNodeIDVector = resultSet->getValueVector(dataInfo->srcNodePos).get(); vectors->dstNodeIDVector = resultSet->getValueVector(dataInfo->dstNodePos).get(); @@ -22,16 +22,16 @@ void RecursiveJoin::initLocalStateInternal(ResultSet* /*resultSet_*/, ExecutionC switch (joinType) { case planner::RecursiveJoinType::TRACK_PATH: { vectors->pathVector = resultSet->getValueVector(dataInfo->pathPos).get(); - bfsState = std::make_unique>( - upperBound, targetDstNodes.get()); + bfsState = std::make_unique>(upperBound, + targetDstNodes.get()); for (auto i = lowerBound; i <= upperBound; ++i) { - scanners.push_back(std::make_unique( - targetDstNodes.get(), i, dataInfo->tableIDToName)); + scanners.push_back(std::make_unique(targetDstNodes.get(), i, + dataInfo->tableIDToName)); } } break; case planner::RecursiveJoinType::TRACK_NONE: { - bfsState = std::make_unique>( - upperBound, targetDstNodes.get()); + bfsState = std::make_unique>(upperBound, + targetDstNodes.get()); for (auto i = lowerBound; i <= upperBound; ++i) { scanners.push_back( std::make_unique(targetDstNodes.get(), i)); @@ -45,16 +45,16 @@ void RecursiveJoin::initLocalStateInternal(ResultSet* /*resultSet_*/, ExecutionC switch (joinType) { case planner::RecursiveJoinType::TRACK_PATH: { vectors->pathVector = resultSet->getValueVector(dataInfo->pathPos).get(); - bfsState = std::make_unique>( - upperBound, targetDstNodes.get()); + bfsState = std::make_unique>(upperBound, + targetDstNodes.get()); for (auto i = lowerBound; i <= upperBound; ++i) { - scanners.push_back(std::make_unique( - targetDstNodes.get(), i, dataInfo->tableIDToName)); + scanners.push_back(std::make_unique(targetDstNodes.get(), i, + dataInfo->tableIDToName)); } } break; case planner::RecursiveJoinType::TRACK_NONE: { - bfsState = std::make_unique>( - upperBound, targetDstNodes.get()); + bfsState = std::make_unique>(upperBound, + targetDstNodes.get()); for (auto i = lowerBound; i <= upperBound; ++i) { scanners.push_back( std::make_unique(targetDstNodes.get(), i)); @@ -68,16 +68,16 @@ void RecursiveJoin::initLocalStateInternal(ResultSet* /*resultSet_*/, ExecutionC switch (joinType) { case planner::RecursiveJoinType::TRACK_PATH: { vectors->pathVector = resultSet->getValueVector(dataInfo->pathPos).get(); - bfsState = std::make_unique>( - upperBound, targetDstNodes.get()); + bfsState = std::make_unique>(upperBound, + targetDstNodes.get()); for (auto i = lowerBound; i <= upperBound; ++i) { - scanners.push_back(std::make_unique( - targetDstNodes.get(), i, dataInfo->tableIDToName)); + scanners.push_back(std::make_unique(targetDstNodes.get(), i, + dataInfo->tableIDToName)); } } break; case planner::RecursiveJoinType::TRACK_NONE: { - bfsState = std::make_unique>( - upperBound, targetDstNodes.get()); + bfsState = std::make_unique>(upperBound, + targetDstNodes.get()); for (auto i = lowerBound; i <= upperBound; ++i) { scanners.push_back( std::make_unique(targetDstNodes.get(), i)); @@ -165,8 +165,8 @@ bool RecursiveJoin::scanOutput() { if (vectors->pathVector != nullptr) { vectors->pathVector->resetAuxiliaryBuffer(); } - frontiersScanner->scan( - vectors.get(), offsetVectorSize, nodeIDDataVectorSize, relIDDataVectorSize); + frontiersScanner->scan(vectors.get(), offsetVectorSize, nodeIDDataVectorSize, + relIDDataVectorSize); if (offsetVectorSize == 0) { return false; } @@ -212,8 +212,8 @@ void RecursiveJoin::initLocalRecursivePlan(ExecutionContext* context) { op = op->getChild(0); } scanFrontier = (ScanFrontier*)op; - localResultSet = std::make_unique( - dataInfo->localResultSetDescriptor.get(), context->clientContext->getMemoryManager()); + localResultSet = std::make_unique(dataInfo->localResultSetDescriptor.get(), + context->clientContext->getMemoryManager()); vectors->recursiveDstNodeIDVector = localResultSet->getValueVector(dataInfo->recursiveDstNodeIDPos).get(); vectors->recursiveEdgeIDVector = @@ -221,12 +221,12 @@ void RecursiveJoin::initLocalRecursivePlan(ExecutionContext* context) { recursiveRoot->initLocalState(localResultSet.get(), context); } -void RecursiveJoin::populateTargetDstNodes() { +void RecursiveJoin::populateTargetDstNodes(ExecutionContext* context) { frontier::node_id_set_t targetNodeIDs; uint64_t numTargetNodes = 0; for (auto& semiMask : sharedState->semiMasks) { auto nodeTable = semiMask->getNodeTable(); - auto numNodes = nodeTable->getMaxNodeOffset(transaction) + 1; + auto numNodes = nodeTable->getMaxNodeOffset(context->clientContext->getTx()) + 1; if (semiMask->isEnabled()) { for (auto offset = 0u; offset < numNodes; ++offset) { if (semiMask->isNodeMasked(offset)) { diff --git a/src/processor/operator/result_collector.cpp b/src/processor/operator/result_collector.cpp index 70c9a809d55..1e7d993599a 100644 --- a/src/processor/operator/result_collector.cpp +++ b/src/processor/operator/result_collector.cpp @@ -11,8 +11,8 @@ void ResultCollector::initLocalStateInternal(ResultSet* resultSet, ExecutionCont for (auto& pos : info->payloadPositions) { payloadVectors.push_back(resultSet->getValueVector(pos).get()); } - localTable = std::make_unique( - context->clientContext->getMemoryManager(), info->tableSchema->copy()); + localTable = std::make_unique(context->clientContext->getMemoryManager(), + info->tableSchema->copy()); } void ResultCollector::executeInternal(ExecutionContext* context) { diff --git a/src/processor/operator/scan/scan_multi_node_tables.cpp b/src/processor/operator/scan/scan_multi_node_tables.cpp index b1c17fae571..806baa03edc 100644 --- a/src/processor/operator/scan/scan_multi_node_tables.cpp +++ b/src/processor/operator/scan/scan_multi_node_tables.cpp @@ -13,9 +13,9 @@ bool ScanMultiNodeTables::getNextTuplesInternal(ExecutionContext* context) { inVector->getValue(inVector->state->selVector->selectedPositions[0]).tableID; KU_ASSERT(readStates.contains(tableID) && tables.contains(tableID)); auto scanTableInfo = tables.at(tableID).get(); - scanTableInfo->table->initializeReadState( - transaction, scanTableInfo->columnIDs, inVector, readStates[tableID].get()); - scanTableInfo->table->read(transaction, *readStates.at(tableID), inVector, outVectors); + scanTableInfo->table->initializeReadState(context->clientContext->getTx(), + scanTableInfo->columnIDs, *inVector, *readStates[tableID]); + scanTableInfo->table->read(context->clientContext->getTx(), *readStates.at(tableID)); return true; } diff --git a/src/processor/operator/scan/scan_multi_rel_tables.cpp b/src/processor/operator/scan/scan_multi_rel_tables.cpp index feb59ce0ec2..ae6a636449f 100644 --- a/src/processor/operator/scan/scan_multi_rel_tables.cpp +++ b/src/processor/operator/scan/scan_multi_rel_tables.cpp @@ -7,10 +7,13 @@ using namespace kuzu::transaction; namespace kuzu { namespace processor { -void RelTableCollectionScanner::init() { +void RelTableCollectionScanner::init(ValueVector* inVector, + const std::vector& outputVectors) { readStates.resize(scanInfos.size()); for (auto i = 0u; i < scanInfos.size(); i++) { - readStates[i] = std::make_unique(); + auto scanInfo = scanInfos[i].get(); + readStates[i] = std::make_unique(*inVector, scanInfo->columnIDs, + outputVectors, scanInfo->direction); } } @@ -19,8 +22,7 @@ bool RelTableCollectionScanner::scan(ValueVector* inVector, while (true) { if (readStates[currentTableIdx]->hasMoreToRead(transaction)) { auto scanInfo = scanInfos[currentTableIdx].get(); - scanInfo->table->read( - transaction, *readStates[currentTableIdx], inVector, outputVectors); + scanInfo->table->read(transaction, *readStates[currentTableIdx]); if (outputVectors[0]->state->selVector->selectedSize > 0) { return true; } @@ -31,7 +33,7 @@ bool RelTableCollectionScanner::scan(ValueVector* inVector, } auto scanInfo = scanInfos[currentTableIdx].get(); scanInfo->table->initializeReadState(transaction, scanInfo->direction, - scanInfo->columnIDs, inVector, readStates[currentTableIdx].get()); + scanInfo->columnIDs, *inVector, *readStates[currentTableIdx]); nextTableIdx++; } } @@ -49,14 +51,15 @@ std::unique_ptr RelTableCollectionScanner::clone() co void ScanMultiRelTable::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { ScanRelTable::initLocalStateInternal(resultSet, context); for (auto& [_, scanner] : scannerPerNodeTable) { - scanner->init(); + scanner->init(inVector, outVectors); } currentScanner = nullptr; } bool ScanMultiRelTable::getNextTuplesInternal(ExecutionContext* context) { while (true) { - if (currentScanner != nullptr && currentScanner->scan(inVector, outVectors, transaction)) { + if (currentScanner != nullptr && + currentScanner->scan(inVector, outVectors, context->clientContext->getTx())) { metrics->numOutputTuple.increase(outVectors[0]->state->selVector->selectedSize); return true; } diff --git a/src/processor/operator/scan/scan_node_table.cpp b/src/processor/operator/scan/scan_node_table.cpp index c0223aebdac..20e03b8e077 100644 --- a/src/processor/operator/scan/scan_node_table.cpp +++ b/src/processor/operator/scan/scan_node_table.cpp @@ -12,8 +12,9 @@ bool ScanSingleNodeTable::getNextTuplesInternal(ExecutionContext* context) { for (auto& outputVector : outVectors) { outputVector->resetAuxiliaryBuffer(); } - info->table->initializeReadState(transaction, info->columnIDs, inVector, readState.get()); - info->table->read(transaction, *readState, inVector, outVectors); + info->table->initializeReadState(context->clientContext->getTx(), info->columnIDs, *inVector, + *readState); + info->table->read(context->clientContext->getTx(), *readState); return true; } diff --git a/src/processor/operator/scan/scan_rel_table.cpp b/src/processor/operator/scan/scan_rel_table.cpp index 2a836fb82db..7f6b8b67987 100644 --- a/src/processor/operator/scan/scan_rel_table.cpp +++ b/src/processor/operator/scan/scan_rel_table.cpp @@ -6,14 +6,14 @@ namespace processor { bool ScanRelTable::getNextTuplesInternal(ExecutionContext* context) { while (true) { if (scanState->hasMoreToRead(context->clientContext->getTx())) { - info->table->read(transaction, *scanState, inVector, outVectors); + info->table->read(context->clientContext->getTx(), *scanState); return true; } if (!children[0]->getNextTuple(context)) { return false; } - info->table->initializeReadState( - transaction, info->direction, info->columnIDs, inVector, scanState.get()); + info->table->initializeReadState(context->clientContext->getTx(), info->direction, + info->columnIDs, *inVector, *scanState); } } diff --git a/src/processor/operator/scan/scan_table.cpp b/src/processor/operator/scan/scan_table.cpp index 58d26f89b51..e6bd82bf52b 100644 --- a/src/processor/operator/scan/scan_table.cpp +++ b/src/processor/operator/scan/scan_table.cpp @@ -3,8 +3,8 @@ namespace kuzu { namespace processor { -void ScanTable::initLocalStateInternal(kuzu::processor::ResultSet* resultSet, - kuzu::processor::ExecutionContext* /*executionContext*/) { +void ScanTable::initLocalStateInternal(ResultSet* resultSet, + ExecutionContext* /*executionContext*/) { inVector = resultSet->getValueVector(inVectorPos).get(); outVectors.reserve(outVectorsPos.size()); for (auto& pos : outVectorsPos) { diff --git a/src/processor/operator/scan_node_id.cpp b/src/processor/operator/scan_node_id.cpp index ef0ea2756fc..61fe3349b3b 100644 --- a/src/processor/operator/scan_node_id.cpp +++ b/src/processor/operator/scan_node_id.cpp @@ -1,6 +1,7 @@ #include "processor/operator/scan_node_id.h" using namespace kuzu::common; +using namespace kuzu::transaction; namespace kuzu { namespace processor { @@ -24,13 +25,16 @@ std::pair NodeTableScanState::getNextRangeToRead() { return std::make_pair(startOffset, startOffset + range); } -void ScanNodeIDSharedState::initialize(transaction::Transaction* transaction) { +void ScanNodeIDSharedState::initialize(Transaction* transaction) { auto numMask = tableStates[0]->getSemiMask()->getNumMasks(); + numNodes = 0; for (auto& tableState : tableStates) { KU_ASSERT(tableState->getSemiMask()->getNumMasks() == numMask); tableState->initializeMaxOffset(transaction); + numNodes += tableState->getTable()->getNumTuples(transaction); } (void)numMask; // For clang-tidy: used for assert. + numNodesScanned = 0; } std::tuple ScanNodeIDSharedState::getNextRangeToRead() { @@ -49,6 +53,7 @@ std::tuple ScanNodeIDSharedState::getNe endOffset = _endOffset; } KU_ASSERT(currentStateIdx < tableStates.size()); + numNodesScanned += endOffset - startOffset; return std::make_tuple(tableStates[currentStateIdx].get(), startOffset, endOffset); } @@ -57,12 +62,13 @@ void ScanNodeID::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* outValueVector->setSequential(); } -bool ScanNodeID::getNextTuplesInternal(ExecutionContext* /*context*/) { +bool ScanNodeID::getNextTuplesInternal(ExecutionContext* context) { do { auto [state, startOffset, endOffset] = sharedState->getNextRangeToRead(); if (state == nullptr) { return false; } + outValueVector->state->selVector->setToUnfiltered(); auto nodeIDValues = (nodeID_t*)(outValueVector->getData()); auto size = endOffset - startOffset; for (auto i = 0u; i < size; ++i) { @@ -70,31 +76,39 @@ bool ScanNodeID::getNextTuplesInternal(ExecutionContext* /*context*/) { nodeIDValues[i].tableID = state->getTable()->getTableID(); } outValueVector->state->initOriginalAndSelectedSize(size); - setSelVector(state, startOffset, endOffset); + setSelVector(context, state, startOffset, endOffset); } while (outValueVector->state->selVector->selectedSize == 0); metrics->numOutputTuple.increase(outValueVector->state->selVector->selectedSize); return true; } -void ScanNodeID::setSelVector( - NodeTableScanState* tableState, offset_t startOffset, offset_t endOffset) { +void ScanNodeID::setSelVector(ExecutionContext* context, NodeTableScanState* tableState, + offset_t startOffset, offset_t endOffset) { + // Apply changes to the selVector from nodes metadata. + tableState->getTable()->setSelVectorForDeletedOffsets(context->clientContext->getTx(), + outValueVector.get()); if (tableState->isSemiMaskEnabled()) { - outValueVector->state->selVector->resetSelectorToValuePosBuffer(); + auto buffer = outValueVector->state->selVector->getMultableBuffer(); + sel_t prevSelectedSize = outValueVector->state->selVector->selectedSize; // Fill selected positions based on node mask for nodes between the given startOffset and // endOffset. If the node is masked (i.e., valid for read), then it is set to the selected // positions. Finally, we update the selectedSize for selVector. sel_t numSelectedValues = 0; for (auto i = 0u; i < (endOffset - startOffset); i++) { - outValueVector->state->selVector->selectedPositions[numSelectedValues] = i; + buffer[numSelectedValues] = i; numSelectedValues += tableState->getSemiMask()->isNodeMasked(i + startOffset); } outValueVector->state->selVector->selectedSize = numSelectedValues; - } else { - // By default, the selected positions is set to the const incremental pos array. - outValueVector->state->selVector->resetSelectorToUnselected(); + if (prevSelectedSize != numSelectedValues) { + outValueVector->state->selVector->setToFiltered(); + } } - // Apply changes to the selVector from nodes metadata. - tableState->getTable()->setSelVectorForDeletedOffsets(transaction, outValueVector); +} + +double ScanNodeID::getProgress(ExecutionContext* /*context*/) const { + uint64_t numNodes = sharedState->getNumNodes(); + uint64_t numReadNodes = sharedState->getNumNodesScanned(); + return numNodes == 0 ? 0.0 : (double)numReadNodes / numNodes; } } // namespace processor diff --git a/src/processor/operator/semi_masker.cpp b/src/processor/operator/semi_masker.cpp index 8b217f5e55f..418ebd7bf93 100644 --- a/src/processor/operator/semi_masker.cpp +++ b/src/processor/operator/semi_masker.cpp @@ -16,11 +16,11 @@ void BaseSemiMasker::initGlobalStateInternal(ExecutionContext* /*context*/) { } } -void BaseSemiMasker::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* /*context*/) { +void BaseSemiMasker::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { keyVector = resultSet->getValueVector(info->keyPos).get(); for (auto& [table, masks] : info->masksPerTable) { for (auto& maskWithIdx : masks) { - maskWithIdx.first->init(transaction); + maskWithIdx.first->init(context->clientContext->getTx()); } } } diff --git a/src/processor/operator/skip.cpp b/src/processor/operator/skip.cpp index a389c541dfb..6d381ebb07b 100644 --- a/src/processor/operator/skip.cpp +++ b/src/processor/operator/skip.cpp @@ -28,17 +28,17 @@ bool Skip::getNextTuplesInternal(ExecutionContext* context) { // If all dataChunks are flat, numTupleAvailable = 1 which means numTupleSkippedBefore = // skipNumber. So execution is handled in above if statement. KU_ASSERT(!dataChunkToSelect->state->isFlat()); - auto selectedPosBuffer = dataChunkToSelect->state->selVector->getSelectedPositionsBuffer(); + auto buffer = dataChunkToSelect->state->selVector->getMultableBuffer(); if (dataChunkToSelect->state->selVector->isUnfiltered()) { for (uint64_t i = numTupleToSkipInCurrentResultSet; i < dataChunkToSelect->state->selVector->selectedSize; ++i) { - selectedPosBuffer[i - numTupleToSkipInCurrentResultSet] = i; + buffer[i - numTupleToSkipInCurrentResultSet] = i; } - dataChunkToSelect->state->selVector->resetSelectorToValuePosBuffer(); + dataChunkToSelect->state->selVector->setToFiltered(); } else { for (uint64_t i = numTupleToSkipInCurrentResultSet; i < dataChunkToSelect->state->selVector->selectedSize; ++i) { - selectedPosBuffer[i - numTupleToSkipInCurrentResultSet] = selectedPosBuffer[i]; + buffer[i - numTupleToSkipInCurrentResultSet] = buffer[i]; } } dataChunkToSelect->state->selVector->selectedSize = diff --git a/src/processor/operator/table_scan/ftable_scan_function.cpp b/src/processor/operator/table_scan/ftable_scan_function.cpp index 709313adb86..88846c94e96 100644 --- a/src/processor/operator/table_scan/ftable_scan_function.cpp +++ b/src/processor/operator/table_scan/ftable_scan_function.cpp @@ -44,8 +44,8 @@ static offset_t tableFunc(TableFuncInput& input, TableFuncOutput& output) { if (morsel.numTuples == 0) { return 0; } - sharedState->table->scan( - output.vectors, morsel.startTupleIdx, morsel.numTuples, bindData->columnIndices); + sharedState->table->scan(output.vectors, morsel.startTupleIdx, morsel.numTuples, + bindData->columnIndices); return morsel.numTuples; } @@ -54,14 +54,14 @@ static std::unique_ptr initSharedState(TableFunctionInitIn return std::make_unique(bindData->table, bindData->morselSize); } -static std::unique_ptr initLocalState( - TableFunctionInitInput&, TableFuncSharedState*, storage::MemoryManager*) { +static std::unique_ptr initLocalState(TableFunctionInitInput&, + TableFuncSharedState*, storage::MemoryManager*) { return std::make_unique(); } function_set FTableScan::getFunctionSet() { function_set functionSet; - functionSet.push_back(std::make_unique(READ_FTABLE_FUNC_NAME, tableFunc, nullptr, + functionSet.push_back(std::make_unique(name, tableFunc, nullptr /*bindFunc*/, initSharedState, initLocalState, std::vector{})); return functionSet; } diff --git a/src/processor/operator/table_scan/union_all_scan.cpp b/src/processor/operator/table_scan/union_all_scan.cpp index 5c7ff2dd44e..77fb0d9bbc2 100644 --- a/src/processor/operator/table_scan/union_all_scan.cpp +++ b/src/processor/operator/table_scan/union_all_scan.cpp @@ -31,8 +31,8 @@ std::unique_ptr UnionAllScanSharedState::getMorselNoLock( return morsel; } -void UnionAllScan::initLocalStateInternal( - ResultSet* /*resultSet_*/, ExecutionContext* /*context*/) { +void UnionAllScan::initLocalStateInternal(ResultSet* /*resultSet_*/, + ExecutionContext* /*context*/) { for (auto& dataPos : info->outputPositions) { vectors.push_back(resultSet->getValueVector(dataPos).get()); } diff --git a/src/processor/operator/unwind.cpp b/src/processor/operator/unwind.cpp index cd3b60fa638..fdc61e2f79d 100644 --- a/src/processor/operator/unwind.cpp +++ b/src/processor/operator/unwind.cpp @@ -8,6 +8,9 @@ namespace processor { void Unwind::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { expressionEvaluator->init(*resultSet, context->clientContext->getMemoryManager()); outValueVector = resultSet->getValueVector(outDataPos); + if (idPos.isValid()) { + idVector = resultSet->getValueVector(idPos).get(); + } } bool Unwind::hasMoreToRead() const { @@ -20,11 +23,20 @@ void Unwind::copyTuplesToOutVector(uint64_t startPos, uint64_t endPos) const { for (auto i = 0u; i < endPos - startPos; i++) { outValueVector->copyFromVectorData(i, listDataVector, listPos++); } + if (idVector != nullptr) { + KU_ASSERT(listDataVector->dataType.getLogicalTypeID() == common::LogicalTypeID::NODE); + auto idFieldVector = StructVector::getFieldVector(listDataVector, 0); + listPos = listEntry.offset + startPos; + for (auto i = 0u; i < endPos - startPos; i++) { + idVector->copyFromVectorData(i, idFieldVector.get(), listPos++); + } + } } bool Unwind::getNextTuplesInternal(ExecutionContext* context) { if (hasMoreToRead()) { - auto totalElementsCopy = std::min(DEFAULT_VECTOR_CAPACITY, listEntry.size - startIndex); + auto totalElementsCopy = + std::min(DEFAULT_VECTOR_CAPACITY, (uint64_t)listEntry.size - startIndex); copyTuplesToOutVector(startIndex, (totalElementsCopy + startIndex)); startIndex += totalElementsCopy; outValueVector->state->initOriginalAndSelectedSize(totalElementsCopy); @@ -42,7 +54,7 @@ bool Unwind::getNextTuplesInternal(ExecutionContext* context) { } listEntry = expressionEvaluator->resultVector->getValue(pos); startIndex = 0; - auto totalElementsCopy = std::min(DEFAULT_VECTOR_CAPACITY, listEntry.size); + auto totalElementsCopy = std::min(DEFAULT_VECTOR_CAPACITY, (uint64_t)listEntry.size); copyTuplesToOutVector(0, totalElementsCopy); startIndex += totalElementsCopy; outValueVector->state->initOriginalAndSelectedSize(startIndex); diff --git a/src/processor/processor.cpp b/src/processor/processor.cpp index 16bce09fa84..d2fdd879075 100644 --- a/src/processor/processor.cpp +++ b/src/processor/processor.cpp @@ -14,8 +14,8 @@ QueryProcessor::QueryProcessor(uint64_t numThreads) { taskScheduler = std::make_unique(numThreads); } -std::shared_ptr QueryProcessor::execute( - PhysicalPlan* physicalPlan, ExecutionContext* context) { +std::shared_ptr QueryProcessor::execute(PhysicalPlan* physicalPlan, + ExecutionContext* context) { auto lastOperator = physicalPlan->lastOperator.get(); auto resultCollector = ku_dynamic_cast(lastOperator); // The root pipeline(task) consists of operators and its prevOperator only, because we @@ -25,12 +25,17 @@ std::shared_ptr QueryProcessor::execute( auto task = std::make_shared(resultCollector, context); decomposePlanIntoTask(lastOperator->getChild(0), task.get(), context); initTask(task.get()); + context->clientContext->getProgressBar()->startProgress(); taskScheduler->scheduleTaskAndWaitOrError(task, context); + context->clientContext->getProgressBar()->endProgress(); return resultCollector->getResultFactorizedTable(); } -void QueryProcessor::decomposePlanIntoTask( - PhysicalOperator* op, Task* task, ExecutionContext* context) { +void QueryProcessor::decomposePlanIntoTask(PhysicalOperator* op, Task* task, + ExecutionContext* context) { + if (op->isSource()) { + context->clientContext->getProgressBar()->addPipeline(); + } if (op->isSink()) { auto childTask = std::make_unique(ku_dynamic_cast(op), context); diff --git a/src/processor/processor_task.cpp b/src/processor/processor_task.cpp index 972b2358336..f5c991675d3 100644 --- a/src/processor/processor_task.cpp +++ b/src/processor/processor_task.cpp @@ -31,11 +31,12 @@ void ProcessorTask::run() { void ProcessorTask::finalizeIfNecessary() { auto resultSet = populateResultSet(sink, executionContext->clientContext->getMemoryManager()); sink->initLocalState(resultSet.get(), executionContext); + executionContext->clientContext->getProgressBar()->finishPipeline(); sink->finalize(executionContext); } -std::unique_ptr ProcessorTask::populateResultSet( - Sink* op, storage::MemoryManager* memoryManager) { +std::unique_ptr ProcessorTask::populateResultSet(Sink* op, + storage::MemoryManager* memoryManager) { auto resultSetDescriptor = op->getResultSetDescriptor(); if (resultSetDescriptor == nullptr) { // Some pipeline does not need a resultSet, e.g. OrderByMerge diff --git a/src/processor/result/CMakeLists.txt b/src/processor/result/CMakeLists.txt index bc19b447128..9bab3f7059f 100644 --- a/src/processor/result/CMakeLists.txt +++ b/src/processor/result/CMakeLists.txt @@ -1,7 +1,9 @@ add_library(kuzu_processor_result OBJECT + base_hash_table.cpp factorized_table.cpp flat_tuple.cpp + mark_hash_table.cpp result_set.cpp result_set_descriptor.cpp ) diff --git a/src/processor/result/base_hash_table.cpp b/src/processor/result/base_hash_table.cpp new file mode 100644 index 00000000000..33ae95b2eff --- /dev/null +++ b/src/processor/result/base_hash_table.cpp @@ -0,0 +1,171 @@ +#include "processor/result/base_hash_table.h" + +#include "math.h" + +#include "common/null_buffer.h" +#include "common/utils.h" +#include "function/comparison/comparison_functions.h" +#include "function/hash/vector_hash_functions.h" + +using namespace kuzu::common; +using namespace kuzu::function; + +namespace kuzu { +namespace processor { + +BaseHashTable::BaseHashTable(storage::MemoryManager& memoryManager, logical_type_vec_t keyTypes) + : maxNumHashSlots{0}, bitmask{0}, numSlotsPerBlockLog2{0}, slotIdxInBlockMask{0}, + memoryManager{memoryManager}, keyTypes{std::move(keyTypes)} { + initCompareFuncs(); + initTmpHashVector(); +} + +void BaseHashTable::setMaxNumHashSlots(uint64_t newSize) { + maxNumHashSlots = newSize; + bitmask = maxNumHashSlots - 1; +} + +void BaseHashTable::computeAndCombineVecHash(const std::vector& unFlatKeyVectors, + uint32_t startVecIdx) { + for (; startVecIdx < unFlatKeyVectors.size(); startVecIdx++) { + auto keyVector = unFlatKeyVectors[startVecIdx]; + auto tmpHashResultVector = + std::make_unique(LogicalTypeID::INT64, &memoryManager); + auto tmpHashCombineResultVector = + std::make_unique(LogicalTypeID::INT64, &memoryManager); + VectorHashFunction::computeHash(keyVector, tmpHashResultVector.get()); + VectorHashFunction::combineHash(hashVector.get(), tmpHashResultVector.get(), + tmpHashCombineResultVector.get()); + hashVector = std::move(tmpHashCombineResultVector); + } +} + +void BaseHashTable::computeVectorHashes(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors) { + if (!flatKeyVectors.empty()) { + VectorHashFunction::computeHash(flatKeyVectors[0], hashVector.get()); + computeAndCombineVecHash(flatKeyVectors, 1 /* startVecIdx */); + computeAndCombineVecHash(unFlatKeyVectors, 0 /* startVecIdx */); + } else { + VectorHashFunction::computeHash(unFlatKeyVectors[0], hashVector.get()); + computeAndCombineVecHash(unFlatKeyVectors, 1 /* startVecIdx */); + } +} + +template +static bool compareEntry(common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { + uint8_t result; + auto key = vector->getData() + vectorPos * vector->getNumBytesPerValue(); + function::Equals::operation(*(T*)key, *(T*)entry, result, nullptr /* leftVector */, + nullptr /* rightVector */); + return result != 0; +} + +static compare_function_t getCompareEntryFunc(PhysicalTypeID type); + +template<> +[[maybe_unused]] bool compareEntry(common::ValueVector* vector, uint32_t vectorPos, + const uint8_t* entry) { + auto dataVector = ListVector::getDataVector(vector); + auto listToCompare = vector->getValue(vectorPos); + auto listEntry = reinterpret_cast(entry); + auto entryNullBytes = reinterpret_cast(listEntry->overflowPtr); + auto entryValues = entryNullBytes + NullBuffer::getNumBytesForNullValues(listEntry->size); + auto rowLayoutSize = LogicalTypeUtils::getRowLayoutSize(dataVector->dataType); + compare_function_t compareFunc = getCompareEntryFunc(dataVector->dataType.getPhysicalType()); + if (listToCompare.size != listEntry->size) { + return false; + } + for (auto i = 0u; i < listEntry->size; i++) { + if (!compareFunc(dataVector, listToCompare.offset + i, entryValues)) { + return false; + } + entryValues += rowLayoutSize; + } + return true; +} + +static bool compareNodeEntry(common::ValueVector* vector, uint32_t vectorPos, + const uint8_t* entry) { + KU_ASSERT(0 == common::StructType::getFieldIdx(&vector->dataType, common::InternalKeyword::ID)); + auto idVector = common::StructVector::getFieldVector(vector, 0).get(); + return compareEntry(idVector, vectorPos, + entry + common::NullBuffer::getNumBytesForNullValues( + common::StructType::getNumFields(&vector->dataType))); +} + +static bool compareRelEntry(common::ValueVector* vector, uint32_t vectorPos, const uint8_t* entry) { + KU_ASSERT(3 == common::StructType::getFieldIdx(&vector->dataType, common::InternalKeyword::ID)); + auto idVector = common::StructVector::getFieldVector(vector, 3).get(); + return compareEntry(idVector, vectorPos, + entry + sizeof(common::internalID_t) * 2 + sizeof(common::ku_string_t) + + common::NullBuffer::getNumBytesForNullValues( + common::StructType::getNumFields(&vector->dataType))); +} + +template<> +[[maybe_unused]] bool compareEntry(common::ValueVector* vector, uint32_t vectorPos, + const uint8_t* entry) { + switch (vector->dataType.getLogicalTypeID()) { + case LogicalTypeID::NODE: { + return compareNodeEntry(vector, vectorPos, entry); + } + case LogicalTypeID::REL: { + return compareRelEntry(vector, vectorPos, entry); + } + case LogicalTypeID::STRUCT: { + auto numFields = StructType::getNumFields(&vector->dataType); + auto entryToCompare = entry + NullBuffer::getNumBytesForNullValues(numFields); + for (auto i = 0u; i < numFields; i++) { + auto isNullInEntry = NullBuffer::isNull(entry, i); + auto fieldVector = StructVector::getFieldVector(vector, i); + compare_function_t compareFunc = + getCompareEntryFunc(fieldVector->dataType.getPhysicalType()); + // Firstly check null on left and right side. + if (isNullInEntry != fieldVector->isNull(vectorPos)) { + return false; + } + // If both not null, compare the value. + if (!isNullInEntry && !compareFunc(fieldVector.get(), vectorPos, entryToCompare)) { + return false; + } + entryToCompare += LogicalTypeUtils::getRowLayoutSize(fieldVector->dataType); + } + return true; + } + default: + KU_UNREACHABLE; + } +} + +static compare_function_t getCompareEntryFunc(PhysicalTypeID type) { + compare_function_t func; + TypeUtils::visit( + type, [&](T) { func = compareEntry; }, [](auto) { KU_UNREACHABLE; }); + return func; +} + +void BaseHashTable::initSlotConstant(uint64_t numSlotsPerBlock_) { + KU_ASSERT(numSlotsPerBlock_ == common::nextPowerOfTwo(numSlotsPerBlock_)); + numSlotsPerBlock = numSlotsPerBlock_; + numSlotsPerBlockLog2 = std::log2(numSlotsPerBlock); + slotIdxInBlockMask = + common::BitmaskUtils::all1sMaskForLeastSignificantBits(numSlotsPerBlockLog2); +} + +void BaseHashTable::initCompareFuncs() { + compareEntryFuncs.reserve(keyTypes.size()); + for (auto i = 0u; i < keyTypes.size(); ++i) { + compareEntryFuncs.push_back(getCompareEntryFunc(keyTypes[i].getPhysicalType())); + } +} + +void BaseHashTable::initTmpHashVector() { + hashState = std::make_shared(); + hashState->setToFlat(); + hashVector = std::make_unique(*LogicalType::HASH(), &memoryManager); + hashVector->state = hashState; +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/result/factorized_table.cpp b/src/processor/result/factorized_table.cpp index f5ca1a99023..bf8b9144b14 100644 --- a/src/processor/result/factorized_table.cpp +++ b/src/processor/result/factorized_table.cpp @@ -106,8 +106,8 @@ void DataBlockCollection::merge(DataBlockCollection& other) { } } -FactorizedTable::FactorizedTable( - MemoryManager* memoryManager, std::unique_ptr tableSchema) +FactorizedTable::FactorizedTable(MemoryManager* memoryManager, + std::unique_ptr tableSchema) : memoryManager{memoryManager}, tableSchema{std::move(tableSchema)}, numTuples{0} { KU_ASSERT(this->tableSchema->getNumBytesPerTuple() <= BufferPoolConstants::PAGE_256KB_SIZE); if (!this->tableSchema->isEmpty()) { @@ -261,20 +261,20 @@ uint8_t* FactorizedTable::getTuple(ft_tuple_idx_t tupleIdx) const { tupleIdxInBlock * tableSchema->getNumBytesPerTuple(); } -void FactorizedTable::updateFlatCell( - uint8_t* tuplePtr, ft_col_idx_t colIdx, ValueVector* valueVector, uint32_t pos) { +void FactorizedTable::updateFlatCell(uint8_t* tuplePtr, ft_col_idx_t colIdx, + ValueVector* valueVector, uint32_t pos) { auto nullBuffer = tuplePtr + tableSchema->getNullMapOffset(); if (valueVector->isNull(pos)) { setNonOverflowColNull(nullBuffer, colIdx); } else { - valueVector->copyToRowData( - pos, tuplePtr + tableSchema->getColOffset(colIdx), inMemOverflowBuffer.get()); + valueVector->copyToRowData(pos, tuplePtr + tableSchema->getColOffset(colIdx), + inMemOverflowBuffer.get()); NullBuffer::setNoNull(nullBuffer, colIdx); } } -bool FactorizedTable::isOverflowColNull( - const uint8_t* nullBuffer, ft_tuple_idx_t tupleIdx, ft_col_idx_t colIdx) const { +bool FactorizedTable::isOverflowColNull(const uint8_t* nullBuffer, ft_tuple_idx_t tupleIdx, + ft_col_idx_t colIdx) const { KU_ASSERT(colIdx < tableSchema->getNumColumns()); if (tableSchema->getColumn(colIdx)->hasNoNullGuarantee()) { return false; @@ -303,8 +303,8 @@ void FactorizedTable::clear() { inMemOverflowBuffer->resetBuffer(); } -void FactorizedTable::setOverflowColNull( - uint8_t* nullBuffer, ft_col_idx_t colIdx, ft_tuple_idx_t tupleIdx) { +void FactorizedTable::setOverflowColNull(uint8_t* nullBuffer, ft_col_idx_t colIdx, + ft_tuple_idx_t tupleIdx) { NullBuffer::setNull(nullBuffer, tupleIdx); tableSchema->setMayContainsNullsToTrue(colIdx); } @@ -345,8 +345,8 @@ std::vector FactorizedTable::allocateFlatTupleBlocks( auto& block = flatTupleBlockCollection->getBlocks().back(); auto numTuplesToAppendInCurBlock = std::min(numTuplesToAppend, block->freeSize / numBytesPerTuple); - appendingInfos.emplace_back( - block->getData() + BufferPoolConstants::PAGE_256KB_SIZE - block->freeSize, + appendingInfos.emplace_back(block->getData() + BufferPoolConstants::PAGE_256KB_SIZE - + block->freeSize, numTuplesToAppendInCurBlock); block->freeSize -= numTuplesToAppendInCurBlock * numBytesPerTuple; block->numTuples += numTuplesToAppendInCurBlock; @@ -372,8 +372,8 @@ uint8_t* FactorizedTable::allocateUnflatTupleBlock(uint32_t numBytes) { return lastBlock->getData(); } -void FactorizedTable::copyFlatVectorToFlatColumn( - const ValueVector& vector, const BlockAppendingInfo& blockAppendInfo, ft_col_idx_t colIdx) { +void FactorizedTable::copyFlatVectorToFlatColumn(const ValueVector& vector, + const BlockAppendingInfo& blockAppendInfo, ft_col_idx_t colIdx) { auto valuePositionInVectorToAppend = vector.state->selVector->selectedPositions[0]; auto colOffsetInDataBlock = tableSchema->getColOffset(colIdx); auto dstDataPtr = blockAppendInfo.data; @@ -424,8 +424,8 @@ void FactorizedTable::copyUnflatVectorToFlatColumn(const ValueVector& vector, if (vector.isNull(pos)) { setNonOverflowColNull(dstTuple + tableSchema->getNullMapOffset(), colIdx); } else { - vector.copyToRowData( - pos, dstTuple + byteOffsetOfColumnInTuple, inMemOverflowBuffer.get()); + vector.copyToRowData(pos, dstTuple + byteOffsetOfColumnInTuple, + inMemOverflowBuffer.get()); } dstTuple += tableSchema->getNumBytesPerTuple(); } @@ -436,8 +436,8 @@ void FactorizedTable::copyUnflatVectorToFlatColumn(const ValueVector& vector, // For an unflat column, only an unflat vector is allowed to copy from, for the column, we only // store an overflow_value_t, which contains a pointer to the overflow dataBlock in the // factorizedTable. NullMasks are stored inside the overflow buffer. -void FactorizedTable::copyVectorToUnflatColumn( - const ValueVector& vector, const BlockAppendingInfo& blockAppendInfo, ft_col_idx_t colIdx) { +void FactorizedTable::copyVectorToUnflatColumn(const ValueVector& vector, + const BlockAppendingInfo& blockAppendInfo, ft_col_idx_t colIdx) { KU_ASSERT(!vector.state->isFlat()); auto unflatTupleValue = appendVectorToUnflatTupleBlocks(vector, colIdx); auto blockPtr = blockAppendInfo.data + tableSchema->getColOffset(colIdx); @@ -456,8 +456,8 @@ void FactorizedTable::copyVectorToColumn(const ValueVector& vector, } } -overflow_value_t FactorizedTable::appendVectorToUnflatTupleBlocks( - const ValueVector& vector, ft_col_idx_t colIdx) { +overflow_value_t FactorizedTable::appendVectorToUnflatTupleBlocks(const ValueVector& vector, + ft_col_idx_t colIdx) { KU_ASSERT(!vector.state->isFlat()); auto numFlatTuplesInVector = vector.state->selVector->selectedSize; auto numBytesPerValue = LogicalTypeUtils::getRowLayoutSize(vector.dataType); @@ -506,8 +506,8 @@ overflow_value_t FactorizedTable::appendVectorToUnflatTupleBlocks( return overflow_value_t{numFlatTuplesInVector, overflowBlockBuffer}; } -void FactorizedTable::readUnflatCol( - uint8_t** tuplesToRead, ft_col_idx_t colIdx, ValueVector& vector) const { +void FactorizedTable::readUnflatCol(uint8_t** tuplesToRead, ft_col_idx_t colIdx, + ValueVector& vector) const { auto overflowColValue = *(overflow_value_t*)(tuplesToRead[0] + tableSchema->getColOffset(colIdx)); KU_ASSERT(vector.state->selVector->isUnfiltered()); @@ -557,16 +557,16 @@ void FactorizedTable::readUnflatCol(const uint8_t* tupleToRead, const SelectionV vector.setNull(i, true); } else { vector.setNull(i, false); - vector.copyFromRowData( - i, vectorOverflowValue.value + pos * vector.getNumBytesPerValue()); + vector.copyFromRowData(i, + vectorOverflowValue.value + pos * vector.getNumBytesPerValue()); } } } vector.state->selVector->selectedSize = selVector->selectedSize; } -void FactorizedTable::readFlatColToFlatVector( - uint8_t* tupleToRead, ft_col_idx_t colIdx, ValueVector& vector, sel_t pos) const { +void FactorizedTable::readFlatColToFlatVector(uint8_t* tupleToRead, ft_col_idx_t colIdx, + ValueVector& vector, sel_t pos) const { if (isNonOverflowColNull(tupleToRead + tableSchema->getNullMapOffset(), colIdx)) { vector.setNull(pos, true); } else { @@ -603,15 +603,15 @@ void FactorizedTable::readFlatColToUnflatVector(uint8_t** tuplesToRead, ft_col_i vector.setNull(positionInVectorToWrite, true); } else { vector.setNull(positionInVectorToWrite, false); - vector.copyFromRowData( - positionInVectorToWrite, dataBuffer + tableSchema->getColOffset(colIdx)); + vector.copyFromRowData(positionInVectorToWrite, + dataBuffer + tableSchema->getColOffset(colIdx)); } } } } -void FactorizedTableUtils::appendStringToTable( - FactorizedTable* factorizedTable, std::string& outputMsg, MemoryManager* memoryManager) { +void FactorizedTableUtils::appendStringToTable(FactorizedTable* factorizedTable, + std::string& outputMsg, MemoryManager* memoryManager) { auto outputMsgVector = std::make_shared(LogicalTypeID::STRING, memoryManager); outputMsgVector->state = DataChunkState::getSingleValueDataChunkState(); auto outputKUStr = ku_string_t(); @@ -636,8 +636,8 @@ std::shared_ptr FactorizedTableUtils::getFactorizedTableForOutp } FlatTupleIterator::FlatTupleIterator(FactorizedTable& factorizedTable, std::vector values) - : factorizedTable{factorizedTable}, numFlatTuples{0}, nextFlatTupleIdx{0}, - nextTupleIdx{1}, values{std::move(values)} { + : factorizedTable{factorizedTable}, numFlatTuples{0}, nextFlatTupleIdx{0}, nextTupleIdx{1}, + values{std::move(values)} { resetState(); KU_ASSERT(this->values.size() == factorizedTable.tableSchema->getNumColumns()); } @@ -699,8 +699,8 @@ void FlatTupleIterator::readFlatColToFlatTuple(ft_col_idx_t colIdx, uint8_t* val valueBuffer + factorizedTable.getTableSchema()->getNullMapOffset(), colIdx); values[colIdx]->setNull(isNull); if (!isNull) { - readValueBufferToValue( - colIdx, valueBuffer + factorizedTable.getTableSchema()->getColOffset(colIdx)); + readValueBufferToValue(colIdx, + valueBuffer + factorizedTable.getTableSchema()->getColOffset(colIdx)); } } diff --git a/src/processor/result/flat_tuple.cpp b/src/processor/result/flat_tuple.cpp index 5bdf56dd64d..4bfe5fac3d5 100644 --- a/src/processor/result/flat_tuple.cpp +++ b/src/processor/result/flat_tuple.cpp @@ -42,8 +42,8 @@ std::string FlatTuple::toString() { return result; } -std::string FlatTuple::toString( - const std::vector& colsWidth, const std::string& delimiter, const uint32_t maxWidth) { +std::string FlatTuple::toString(const std::vector& colsWidth, + const std::string& delimiter, const uint32_t maxWidth) { std::ostringstream result; for (auto i = 0ul; i < values.size(); i++) { std::string value = values[i]->toString(); diff --git a/src/processor/result/mark_hash_table.cpp b/src/processor/result/mark_hash_table.cpp new file mode 100644 index 00000000000..29c515e2d56 --- /dev/null +++ b/src/processor/result/mark_hash_table.cpp @@ -0,0 +1,51 @@ +#include "processor/result/mark_hash_table.h" + +namespace kuzu { +namespace processor { + +MarkHashTable::MarkHashTable(storage::MemoryManager& memoryManager, + std::vector keyDataTypes, + std::vector dependentKeyDataTypes, + const std::vector>& aggregateFunctions, + uint64_t numEntriesToAllocate, std::unique_ptr tableSchema) + : AggregateHashTable(memoryManager, std::move(keyDataTypes), std::move(dependentKeyDataTypes), + std::move(aggregateFunctions), numEntriesToAllocate, std::move(tableSchema)) { + distinctColIdxInFT = hashColIdxInFT - 1; +} + +uint64_t MarkHashTable::matchFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, uint64_t numMayMatches, + uint64_t numNoMatches) { + auto colIdx = 0u; + for (auto& flatKeyVector : flatKeyVectors) { + numMayMatches = + matchFlatVecWithFTColumn(flatKeyVector, numMayMatches, numNoMatches, colIdx++); + } + for (auto& unFlatKeyVector : unFlatKeyVectors) { + numMayMatches = + matchUnFlatVecWithFTColumn(unFlatKeyVector, numMayMatches, numNoMatches, colIdx++); + } + for (auto i = 0u; i < numMayMatches; i++) { + noMatchIdxes[numNoMatches++] = mayMatchIdxes[i]; + onMatchSlotIdxes.emplace(mayMatchIdxes[i]); + } + return numNoMatches; +} + +void MarkHashTable::initializeFTEntries(const std::vector& flatKeyVectors, + const std::vector& unFlatKeyVectors, + const std::vector& dependentKeyVectors, + uint64_t numFTEntriesToInitialize) { + AggregateHashTable::initializeFTEntries(flatKeyVectors, unFlatKeyVectors, dependentKeyVectors, + numFTEntriesToInitialize); + for (auto i = 0u; i < numFTEntriesToInitialize; i++) { + auto entryIdx = entryIdxesToInitialize[i]; + auto entry = hashSlotsToUpdateAggState[entryIdx]->entry; + auto onMatch = !onMatchSlotIdxes.contains(entryIdx); + onMatchSlotIdxes.erase(entryIdx); + factorizedTable->updateFlatCellNoNull(entry, distinctColIdxInFT, &onMatch /* isOnMatch */); + } +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/result/result_set.cpp b/src/processor/result/result_set.cpp index 28134f915c7..6466dcd1ef5 100644 --- a/src/processor/result/result_set.cpp +++ b/src/processor/result/result_set.cpp @@ -5,8 +5,8 @@ using namespace kuzu::common; namespace kuzu { namespace processor { -ResultSet::ResultSet( - ResultSetDescriptor* resultSetDescriptor, storage::MemoryManager* memoryManager) +ResultSet::ResultSet(ResultSetDescriptor* resultSetDescriptor, + storage::MemoryManager* memoryManager) : multiplicity{1} { auto numDataChunks = resultSetDescriptor->dataChunkDescriptors.size(); dataChunks.resize(numDataChunks); diff --git a/src/storage/CMakeLists.txt b/src/storage/CMakeLists.txt index b155d4b2656..e45057a8af7 100644 --- a/src/storage/CMakeLists.txt +++ b/src/storage/CMakeLists.txt @@ -10,9 +10,9 @@ add_subdirectory(wal) add_library(kuzu_storage OBJECT file_handle.cpp - storage_info.cpp storage_manager.cpp storage_utils.cpp + storage_version_info.cpp wal_replayer.cpp wal_replayer_utils.cpp) diff --git a/src/storage/buffer_manager/buffer_manager.cpp b/src/storage/buffer_manager/buffer_manager.cpp index aea817cf05c..15f583a472c 100644 --- a/src/storage/buffer_manager/buffer_manager.cpp +++ b/src/storage/buffer_manager/buffer_manager.cpp @@ -98,8 +98,8 @@ void BufferManager::verifySizeParams(uint64_t bufferPoolSize, uint64_t maxDBSize // should be flushed to disk if it is evicted. // (3) If multiple threads are writing to the page, they should coordinate separately because they // both get access to the same piece of memory. -uint8_t* BufferManager::pin( - BMFileHandle& fileHandle, page_idx_t pageIdx, PageReadPolicy pageReadPolicy) { +uint8_t* BufferManager::pin(BMFileHandle& fileHandle, page_idx_t pageIdx, + PageReadPolicy pageReadPolicy) { auto pageState = fileHandle.getPageState(pageIdx); while (true) { auto currStateAndVersion = pageState->getStateAndVersion(); @@ -185,8 +185,8 @@ inline bool try_func(const std::function& func, uint8_t* frame, return true; } -void BufferManager::optimisticRead( - BMFileHandle& fileHandle, page_idx_t pageIdx, const std::function& func) { +void BufferManager::optimisticRead(BMFileHandle& fileHandle, page_idx_t pageIdx, + const std::function& func) { auto pageState = fileHandle.getPageState(pageIdx); #if defined(_WIN32) // Change the Structured Exception handling just for the scope of this function @@ -239,8 +239,8 @@ void BufferManager::unpin(BMFileHandle& fileHandle, page_idx_t pageIdx) { // or we can find no more pages to be evicted. // Lastly, we double check if the needed memory is available. If not, we free the memory we reserved // and return false, otherwise, we load the page to its corresponding frame and return true. -bool BufferManager::claimAFrame( - BMFileHandle& fileHandle, page_idx_t pageIdx, PageReadPolicy pageReadPolicy) { +bool BufferManager::claimAFrame(BMFileHandle& fileHandle, page_idx_t pageIdx, + PageReadPolicy pageReadPolicy) { page_offset_t pageSizeToClaim = fileHandle.getPageSize(); // Reserve the memory for the page. auto currentUsedMem = reserveUsedMemory(pageSizeToClaim); @@ -278,16 +278,16 @@ bool BufferManager::claimAFrame( return true; } -void BufferManager::addToEvictionQueue( - BMFileHandle* fileHandle, page_idx_t pageIdx, PageState* pageState) { +void BufferManager::addToEvictionQueue(BMFileHandle* fileHandle, page_idx_t pageIdx, + PageState* pageState) { auto currStateAndVersion = pageState->getStateAndVersion(); if (++numEvictionQueueInsertions == BufferPoolConstants::EVICTION_QUEUE_PURGING_INTERVAL) { evictionQueue->removeNonEvictableCandidates(); numEvictionQueueInsertions = 0; } pageState->tryMark(currStateAndVersion); - evictionQueue->enqueue( - fileHandle, pageIdx, pageState, PageState::getVersion(currStateAndVersion)); + evictionQueue->enqueue(fileHandle, pageIdx, pageState, + PageState::getVersion(currStateAndVersion)); } uint64_t BufferManager::tryEvictPage(EvictionCandidate& candidate) { @@ -307,8 +307,8 @@ uint64_t BufferManager::tryEvictPage(EvictionCandidate& candidate) { return numBytesFreed; } -void BufferManager::cachePageIntoFrame( - BMFileHandle& fileHandle, page_idx_t pageIdx, PageReadPolicy pageReadPolicy) { +void BufferManager::cachePageIntoFrame(BMFileHandle& fileHandle, page_idx_t pageIdx, + PageReadPolicy pageReadPolicy) { auto pageState = fileHandle.getPageState(pageIdx); pageState->clearDirty(); if (pageReadPolicy == PageReadPolicy::READ_PAGE) { @@ -334,12 +334,12 @@ void BufferManager::removeFilePagesFromFrames(BMFileHandle& fileHandle) { void BufferManager::flushAllDirtyPagesInFrames(BMFileHandle& fileHandle) { for (auto pageIdx = 0u; pageIdx < fileHandle.getNumPages(); ++pageIdx) { - removePageFromFrame(fileHandle, pageIdx, true /* flush */); + flushIfDirtyWithoutLock(fileHandle, pageIdx); } } -void BufferManager::updateFrameIfPageIsInFrameWithoutLock( - BMFileHandle& fileHandle, uint8_t* newPage, page_idx_t pageIdx) { +void BufferManager::updateFrameIfPageIsInFrameWithoutLock(BMFileHandle& fileHandle, + uint8_t* newPage, page_idx_t pageIdx) { auto pageState = fileHandle.getPageState(pageIdx); if (pageState) { memcpy(getFrame(fileHandle, pageIdx), newPage, BufferPoolConstants::PAGE_4KB_SIZE); @@ -354,14 +354,18 @@ void BufferManager::removePageFromFrameIfNecessary(BMFileHandle& fileHandle, pag } // NOTE: We assume the page is not pinned (locked) here. -void BufferManager::removePageFromFrame( - BMFileHandle& fileHandle, page_idx_t pageIdx, bool shouldFlush) { +void BufferManager::removePageFromFrame(BMFileHandle& fileHandle, page_idx_t pageIdx, + bool shouldFlush) { auto pageState = fileHandle.getPageState(pageIdx); + if (PageState::getState(pageState->getStateAndVersion()) == PageState::EVICTED) { + return; + } pageState->spinLock(pageState->getStateAndVersion()); if (shouldFlush) { flushIfDirtyWithoutLock(fileHandle, pageIdx); } releaseFrameForPage(fileHandle, pageIdx); + freeUsedMemory(fileHandle.getPageSize()); pageState->resetToEvicted(); } diff --git a/src/storage/buffer_manager/vm_region.cpp b/src/storage/buffer_manager/vm_region.cpp index b33eb5c7a3a..2260a66be60 100644 --- a/src/storage/buffer_manager/vm_region.cpp +++ b/src/storage/buffer_manager/vm_region.cpp @@ -47,8 +47,8 @@ VMRegion::VMRegion(PageSizeClass pageSizeClass, uint64_t maxRegionSize) : numFra #ifdef _WIN32 uint8_t* VMRegion::getFrame(frame_idx_t frameIdx) { - auto result = VirtualAlloc( - region + ((std::uint64_t)frameIdx * frameSize), frameSize, MEM_COMMIT, PAGE_READWRITE); + auto result = VirtualAlloc(region + ((std::uint64_t)frameIdx * frameSize), frameSize, + MEM_COMMIT, PAGE_READWRITE); if (result == NULL) { throw BufferManagerException(stringFormat( "VirtualAlloc MEM_COMMIT failed with error code {}: {}.", getMaxRegionSize(), diff --git a/src/storage/compression/compression.cpp b/src/storage/compression/compression.cpp index 63beec19171..d95e76f1661 100644 --- a/src/storage/compression/compression.cpp +++ b/src/storage/compression/compression.cpp @@ -22,19 +22,23 @@ uint32_t getDataTypeSizeInChunk(const common::LogicalType& dataType) { if (dataType.getLogicalTypeID() == LogicalTypeID::SERIAL) { return 0; } - switch (dataType.getPhysicalType()) { + return getDataTypeSizeInChunk(dataType.getPhysicalType()); +} + +uint32_t getDataTypeSizeInChunk(const common::PhysicalTypeID& dataType) { + switch (dataType) { case PhysicalTypeID::STRUCT: { return 0; } case PhysicalTypeID::STRING: { return sizeof(uint32_t); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::LIST: case PhysicalTypeID::INTERNAL_ID: { return sizeof(offset_t); } default: { - auto size = StorageUtils::getDataTypeSize(dataType); + auto size = PhysicalTypeUtils::getFixedTypeSize(dataType); KU_ASSERT(size <= BufferPoolConstants::PAGE_4KB_SIZE); return size; } @@ -58,16 +62,24 @@ bool CompressionMetadata::canAlwaysUpdateInPlace() const { } } -bool CompressionMetadata::canUpdateInPlace( - const uint8_t* data, uint32_t pos, PhysicalTypeID physicalType) const { +bool CompressionMetadata::canUpdateInPlace(const uint8_t* data, uint32_t pos, + PhysicalTypeID physicalType) const { if (canAlwaysUpdateInPlace()) { return true; } switch (compression) { case CompressionType::CONSTANT: { // Value can be updated in place only if it is identical to the value already stored. - auto size = PhysicalTypeUtils::getFixedTypeSize(physicalType); - return memcmp(data + pos * size, this->data.data(), size) == 0; + switch (physicalType) { + case PhysicalTypeID::BOOL: { + return NullMask::isNull(reinterpret_cast(data), pos) == + *reinterpret_cast(this->data.data()); + } break; + default: { + auto size = getDataTypeSizeInChunk(physicalType); + return memcmp(data + pos * size, this->data.data(), size) == 0; + } + } } case CompressionType::BOOLEAN_BITPACKING: case CompressionType::UNCOMPRESSED: { @@ -77,45 +89,46 @@ bool CompressionMetadata::canUpdateInPlace( switch (physicalType) { case PhysicalTypeID::INT64: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } case PhysicalTypeID::INT32: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } case PhysicalTypeID::INT16: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } case PhysicalTypeID::INT8: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } case PhysicalTypeID::STRING: case PhysicalTypeID::UINT32: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } case PhysicalTypeID::UINT16: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } case PhysicalTypeID::UINT8: { auto value = reinterpret_cast(data)[pos]; - return IntegerBitpacking::canUpdateInPlace( - value, BitpackHeader::readHeader(this->data)); + return IntegerBitpacking::canUpdateInPlace(value, + BitpackHeader::readHeader(this->data)); } default: { throw common::StorageException( @@ -150,17 +163,18 @@ uint64_t CompressionMetadata::numValues(uint64_t pageSize, const LogicalType& da return IntegerBitpacking::numValues(pageSize, BitpackHeader::readHeader(data)); case PhysicalTypeID::INT8: return IntegerBitpacking::numValues(pageSize, BitpackHeader::readHeader(data)); - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: - return IntegerBitpacking::numValues( - pageSize, BitpackHeader::readHeader(data)); + return IntegerBitpacking::numValues(pageSize, + BitpackHeader::readHeader(data)); case PhysicalTypeID::STRING: case PhysicalTypeID::UINT32: - return IntegerBitpacking::numValues( - pageSize, BitpackHeader::readHeader(data)); + return IntegerBitpacking::numValues(pageSize, + BitpackHeader::readHeader(data)); case PhysicalTypeID::UINT16: - return IntegerBitpacking::numValues( - pageSize, BitpackHeader::readHeader(data)); + return IntegerBitpacking::numValues(pageSize, + BitpackHeader::readHeader(data)); case PhysicalTypeID::UINT8: return IntegerBitpacking::numValues(pageSize, BitpackHeader::readHeader(data)); default: { @@ -207,7 +221,7 @@ std::optional ConstantCompression::analyze(const ColumnChun } return std::optional(CompressionMetadata(CompressionType::CONSTANT, value)); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::LIST: case PhysicalTypeID::STRING: case PhysicalTypeID::INTERNAL_ID: case PhysicalTypeID::DOUBLE: @@ -268,8 +282,8 @@ void ConstantCompression::decompressFromPage(const uint8_t* /*srcBuffer*/, uint6 uint8_t* dstBuffer, uint64_t dstOffset, uint64_t numValues, const CompressionMetadata& metadata) const { for (auto i = 0u; i < numValues; i++) { - memcpy( - dstBuffer + (dstOffset + i) * numBytesPerValue, metadata.data.data(), numBytesPerValue); + memcpy(dstBuffer + (dstOffset + i) * numBytesPerValue, metadata.data.data(), + numBytesPerValue); } } @@ -277,8 +291,8 @@ void ConstantCompression::copyFromPage(const uint8_t* srcBuffer, uint64_t srcOff uint8_t* dstBuffer, uint64_t dstOffset, uint64_t numValues, const CompressionMetadata& metadata) const { if (dataType == common::PhysicalTypeID::BOOL) { - common::NullMask::setNullRange( - reinterpret_cast(dstBuffer), dstOffset, numValues, metadata.data[0]); + common::NullMask::setNullRange(reinterpret_cast(dstBuffer), dstOffset, numValues, + metadata.data[0]); } else { decompressFromPage(srcBuffer, srcOffset, dstBuffer, dstOffset, numValues, metadata); } @@ -295,8 +309,8 @@ static inline T abs(typename std::enable_if::value, T>::type v } template -BitpackHeader IntegerBitpacking::getBitWidth( - const uint8_t* srcBuffer, uint64_t numValues) const { +BitpackHeader IntegerBitpacking::getBitWidth(const uint8_t* srcBuffer, + uint64_t numValues) const { T max = std::numeric_limits::min(), min = std::numeric_limits::max(); for (auto i = 0u; i < numValues; i++) { T value = ((T*)srcBuffer)[i]; @@ -439,8 +453,8 @@ uint64_t IntegerBitpacking::compressNextPage(const uint8_t*& srcBuffer, // TODO(bmwinger): this is hacky; we need a better system for dynamically choosing between // algorithms when compressing if (metadata.compression == CompressionType::UNCOMPRESSED) { - return Uncompressed(sizeof(T)).compressNextPage( - srcBuffer, numValuesRemaining, dstBuffer, dstBufferSize, metadata); + return Uncompressed(sizeof(T)).compressNextPage(srcBuffer, numValuesRemaining, dstBuffer, + dstBufferSize, metadata); } KU_ASSERT(metadata.compression == CompressionType::INTEGER_BITPACKING); auto header = BitpackHeader::readHeader(metadata.data); @@ -629,7 +643,8 @@ void ReadCompressedValuesFromPageToVector::operator()(const uint8_t* frame, Page return IntegerBitpacking().decompressFromPage(frame, pageCursor.elemPosInPage, resultVector->getData(), posInVector, numValuesToRead, metadata); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: { return IntegerBitpacking().decompressFromPage(frame, pageCursor.elemPosInPage, resultVector->getData(), posInVector, numValuesToRead, metadata); @@ -666,11 +681,11 @@ void ReadCompressedValuesFromPage::operator()(const uint8_t* frame, PageCursor& const CompressionMetadata& metadata) { switch (metadata.compression) { case CompressionType::CONSTANT: - return constant.copyFromPage( - frame, pageCursor.elemPosInPage, result, startPosInResult, numValuesToRead, metadata); + return constant.copyFromPage(frame, pageCursor.elemPosInPage, result, startPosInResult, + numValuesToRead, metadata); case CompressionType::UNCOMPRESSED: - return uncompressed.decompressFromPage( - frame, pageCursor.elemPosInPage, result, startPosInResult, numValuesToRead, metadata); + return uncompressed.decompressFromPage(frame, pageCursor.elemPosInPage, result, + startPosInResult, numValuesToRead, metadata); case CompressionType::INTEGER_BITPACKING: { switch (physicalType) { case PhysicalTypeID::INT64: { @@ -689,7 +704,8 @@ void ReadCompressedValuesFromPage::operator()(const uint8_t* frame, PageCursor& return IntegerBitpacking().decompressFromPage(frame, pageCursor.elemPosInPage, result, startPosInResult, numValuesToRead, metadata); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: { return IntegerBitpacking().decompressFromPage(frame, pageCursor.elemPosInPage, result, startPosInResult, numValuesToRead, metadata); @@ -715,8 +731,8 @@ void ReadCompressedValuesFromPage::operator()(const uint8_t* frame, PageCursor& } case CompressionType::BOOLEAN_BITPACKING: // Reading into ColumnChunks should be done without decompressing for booleans - return booleanBitpacking.copyFromPage( - frame, pageCursor.elemPosInPage, result, startPosInResult, numValuesToRead, metadata); + return booleanBitpacking.copyFromPage(frame, pageCursor.elemPosInPage, result, + startPosInResult, numValuesToRead, metadata); default: KU_UNREACHABLE; } @@ -727,46 +743,47 @@ void WriteCompressedValuesToPage::operator()(uint8_t* frame, uint16_t posInFrame const CompressionMetadata& metadata) { switch (metadata.compression) { case CompressionType::CONSTANT: - return constant.setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return constant.setValuesFromUncompressed(data, dataOffset, frame, posInFrame, numValues, + metadata); case CompressionType::UNCOMPRESSED: - return uncompressed.setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return uncompressed.setValuesFromUncompressed(data, dataOffset, frame, posInFrame, + numValues, metadata); case CompressionType::INTEGER_BITPACKING: { switch (physicalType) { case PhysicalTypeID::INT64: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } case PhysicalTypeID::INT32: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } case PhysicalTypeID::INT16: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } case PhysicalTypeID::INT8: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } case PhysicalTypeID::STRING: case PhysicalTypeID::UINT32: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } case PhysicalTypeID::UINT16: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } case PhysicalTypeID::UINT8: { - return IntegerBitpacking().setValuesFromUncompressed( - data, dataOffset, frame, posInFrame, numValues, metadata); + return IntegerBitpacking().setValuesFromUncompressed(data, dataOffset, frame, + posInFrame, numValues, metadata); } default: { throw NotImplementedException("INTEGER_BITPACKING is not implemented for type " + @@ -775,8 +792,8 @@ void WriteCompressedValuesToPage::operator()(uint8_t* frame, uint16_t posInFrame } } case CompressionType::BOOLEAN_BITPACKING: - return booleanBitpacking.copyFromPage( - data, dataOffset, frame, posInFrame, numValues, metadata); + return booleanBitpacking.copyFromPage(data, dataOffset, frame, posInFrame, numValues, + metadata); default: KU_UNREACHABLE; @@ -786,8 +803,8 @@ void WriteCompressedValuesToPage::operator()(uint8_t* frame, uint16_t posInFrame void WriteCompressedValuesToPage::operator()(uint8_t* frame, uint16_t posInFrame, common::ValueVector* vector, uint32_t posInVector, const CompressionMetadata& metadata) { if (metadata.compression == CompressionType::BOOLEAN_BITPACKING) { - booleanBitpacking.setValuesFromUncompressed( - vector->getData(), posInVector, frame, posInFrame, 1, metadata); + booleanBitpacking.setValuesFromUncompressed(vector->getData(), posInVector, frame, + posInFrame, 1, metadata); } else { (*this)(frame, posInFrame, vector->getData(), posInVector, 1, metadata); } diff --git a/src/storage/index/hash_index.cpp b/src/storage/index/hash_index.cpp index c905eda99fe..829ef2ecd9f 100644 --- a/src/storage/index/hash_index.cpp +++ b/src/storage/index/hash_index.cpp @@ -10,6 +10,7 @@ #include "common/types/types.h" #include "common/vector/value_vector.h" #include "storage/index/hash_index_header.h" +#include "storage/index/hash_index_slot.h" #include "storage/index/hash_index_utils.h" #include "transaction/transaction.h" @@ -25,14 +26,15 @@ enum class HashIndexLocalLookupState : uint8_t { KEY_FOUND, KEY_DELETED, KEY_NOT // all newly inserted entries, and the other (localDeletionIndex) is to keep track of newly deleted // entries (not available in localInsertionIndex). We assume that in a transaction, the insertions // and deletions are very small, thus they can be kept in memory. -template +template class HashIndexLocalStorage { public: + using Key = typename std::conditional, std::string_view, T>::type; // Currently, we assume that reads(lookup) and writes(delete/insert) of the local storage will // never happen concurrently. Thus, lookup requires no local storage lock. Writes are // coordinated to execute in serial with the help of the localStorageMutex. This is a // simplification to the lock scheme, but can be relaxed later if necessary. - HashIndexLocalLookupState lookup(T key, common::offset_t& result) { + HashIndexLocalLookupState lookup(Key key, common::offset_t& result) { if (localDeletions.contains(key)) { return HashIndexLocalLookupState::KEY_DELETED; } @@ -45,16 +47,16 @@ class HashIndexLocalStorage { } } - void deleteKey(T key) { + void deleteKey(Key key) { auto iter = localInsertions.find(key); if (iter != localInsertions.end()) { localInsertions.erase(iter); } else { - localDeletions.insert(static_cast(key)); + localDeletions.insert(static_cast(key)); } } - bool insert(T key, common::offset_t value) { + bool insert(Key key, common::offset_t value) { auto iter = localDeletions.find(key); if (iter != localDeletions.end()) { localDeletions.erase(iter); @@ -62,7 +64,7 @@ class HashIndexLocalStorage { if (localInsertions.contains(key)) { return false; } - localInsertions[static_cast(key)] = value; + localInsertions[static_cast(key)] = value; return true; } @@ -83,25 +85,21 @@ class HashIndexLocalStorage { } } -public: - std::shared_mutex localStorageSharedMutex; - private: // When the storage type is string, allow the key type to be string_view with a custom hash // function - using hash_function = typename std::conditional::value, - common::StringUtils::string_hash, std::hash>::type; - std::unordered_map> localInsertions; - std::unordered_set> localDeletions; + using hash_function = typename std::conditional::value, + common::StringUtils::string_hash, std::hash>::type; + std::unordered_map> localInsertions; + std::unordered_set> localDeletions; }; -template -HashIndex::HashIndex(const DBFileIDAndName& dbFileIDAndName, - const std::shared_ptr& fileHandle, - const std::shared_ptr& overflowFile, uint64_t indexPos, - BufferManager& bufferManager, WAL* wal) +template +HashIndex::HashIndex(const DBFileIDAndName& dbFileIDAndName, + const std::shared_ptr& fileHandle, OverflowFileHandle* overflowFileHandle, + uint64_t indexPos, BufferManager& bufferManager, WAL* wal) : dbFileIDAndName{dbFileIDAndName}, bm{bufferManager}, wal{wal}, fileHandle(fileHandle), - diskOverflowFile(overflowFile) { + overflowFileHandle(overflowFileHandle) { headerArray = std::make_unique>(*fileHandle, dbFileIDAndName.dbFileID, NUM_HEADER_PAGES * indexPos + INDEX_HEADER_ARRAY_HEADER_PAGE_IDX, &bm, wal, Transaction::getDummyReadOnlyTrx().get()); @@ -110,15 +108,15 @@ HashIndex::HashIndex(const DBFileIDAndName& dbFileIDAndName, headerArray->get(INDEX_HEADER_IDX_IN_ARRAY, TransactionType::READ_ONLY)); this->indexHeaderForWriteTrx = std::make_unique(*indexHeaderForReadTrx); KU_ASSERT( - this->indexHeaderForReadTrx->keyDataTypeID == TypeUtils::getPhysicalTypeIDForType()); - pSlots = std::make_unique>>(*fileHandle, dbFileIDAndName.dbFileID, + this->indexHeaderForReadTrx->keyDataTypeID == TypeUtils::getPhysicalTypeIDForType()); + pSlots = std::make_unique>>(*fileHandle, dbFileIDAndName.dbFileID, NUM_HEADER_PAGES * indexPos + P_SLOTS_HEADER_PAGE_IDX, &bm, wal, Transaction::getDummyReadOnlyTrx().get()); - oSlots = std::make_unique>>(*fileHandle, dbFileIDAndName.dbFileID, + oSlots = std::make_unique>>(*fileHandle, dbFileIDAndName.dbFileID, NUM_HEADER_PAGES * indexPos + O_SLOTS_HEADER_PAGE_IDX, &bm, wal, Transaction::getDummyReadOnlyTrx().get()); // Initialize functions. - localStorage = std::make_unique>(); + localStorage = std::make_unique>(); } // For read transactions, local storage is skipped, lookups are performed on the persistent @@ -129,8 +127,8 @@ HashIndex::HashIndex(const DBFileIDAndName& dbFileIDAndName, // - the key has been marked as deleted in the local storage, return false; // - the key is neither deleted nor found in the local storage, lookup in the persistent // storage. -template -bool HashIndex::lookupInternal(Transaction* transaction, T key, offset_t& result) { +template +bool HashIndex::lookupInternal(Transaction* transaction, Key key, offset_t& result) { if (transaction->isReadOnly()) { return lookupInPersistentIndex(transaction->getType(), key, result); } else { @@ -149,8 +147,8 @@ bool HashIndex::lookupInternal(Transaction* transaction, T key, offset_t& // For deletions, we don't check if the deleted keys exist or not. Thus, we don't need to check // in the persistent storage and directly delete keys in the local storage. -template -void HashIndex::deleteInternal(T key) const { +template +void HashIndex::deleteInternal(Key key) const { localStorage->deleteKey(key); } @@ -160,8 +158,8 @@ void HashIndex::deleteInternal(T key) const { // - the key doesn't exist in the local storage, check if the key exists in the persistent // index, if // so, return false, else insert the key to the local storage. -template -bool HashIndex::insertInternal(T key, offset_t value) { +template +bool HashIndex::insertInternal(Key key, offset_t value) { offset_t tmpResult; auto localLookupState = localStorage->lookup(key, tmpResult); if (localLookupState == HashIndexLocalLookupState::KEY_FOUND) { @@ -174,8 +172,8 @@ bool HashIndex::insertInternal(T key, offset_t value) { return localStorage->insert(key, value); } -template -bool HashIndex::lookupInPersistentIndex(TransactionType trxType, T key, offset_t& result) { +template +bool HashIndex::lookupInPersistentIndex(TransactionType trxType, Key key, offset_t& result) { auto& header = trxType == TransactionType::READ_ONLY ? *this->indexHeaderForReadTrx : *this->indexHeaderForWriteTrx; auto hashValue = HashIndexUtils::hash(key); @@ -185,36 +183,36 @@ bool HashIndex::lookupInPersistentIndex(TransactionType trxType, T key, of do { auto entryPos = findMatchedEntryInSlot(trxType, iter.slot, key, fingerprint); if (entryPos != SlotHeader::INVALID_ENTRY_POS) { - result = *(common::offset_t*)(iter.slot.entries[entryPos].data + header.numBytesPerKey); + result = iter.slot.entries[entryPos].value; return true; } } while (nextChainedSlot(trxType, iter)); return false; } -template -void HashIndex::insertIntoPersistentIndex(T key, offset_t value) { +template +void HashIndex::insertIntoPersistentIndex(Key key, offset_t value) { auto& header = *this->indexHeaderForWriteTrx; slot_id_t numRequiredEntries = HashIndexUtils::getNumRequiredEntries(header.numEntries, 1); while (numRequiredEntries > - pSlots->getNumElements(TransactionType::WRITE) * getSlotCapacity()) { + pSlots->getNumElements(TransactionType::WRITE) * getSlotCapacity()) { this->splitSlot(header); } auto hashValue = HashIndexUtils::hash(key); auto fingerprint = HashIndexUtils::getFingerprintForHash(hashValue); - auto iter = getSlotIterator( - HashIndexUtils::getPrimarySlotIdForHash(header, hashValue), TransactionType::WRITE); + auto iter = getSlotIterator(HashIndexUtils::getPrimarySlotIdForHash(header, hashValue), + TransactionType::WRITE); // Find a slot with free entries - while (iter.slot.header.numEntries() == getSlotCapacity() && + while (iter.slot.header.numEntries() == getSlotCapacity() && nextChainedSlot(TransactionType::WRITE, iter)) ; - copyKVOrEntryToSlot( - iter.slotInfo, iter.slot, key, value, fingerprint); + copyKVOrEntryToSlot(iter.slotInfo, iter.slot, key, value, + fingerprint); header.numEntries++; } -template -void HashIndex::deleteFromPersistentIndex(T key) { +template +void HashIndex::deleteFromPersistentIndex(Key key) { auto trxType = TransactionType::WRITE; auto header = *this->indexHeaderForWriteTrx; auto hashValue = HashIndexUtils::hash(key); @@ -232,49 +230,52 @@ void HashIndex::deleteFromPersistentIndex(T key) { } template<> -inline common::hash_t HashIndex::hashStored( - transaction::TransactionType /*trxType*/, const ku_string_t& key) const { +inline common::hash_t HashIndex::hashStored(transaction::TransactionType /*trxType*/, + const ku_string_t& key) const { common::hash_t hash; - auto str = diskOverflowFile->readString(TransactionType::WRITE, key); + auto str = overflowFileHandle->readString(TransactionType::WRITE, key); function::Hash::operation(str, hash); return hash; } -template -entry_pos_t HashIndex::findMatchedEntryInSlot( - TransactionType trxType, const Slot& slot, T key, uint8_t fingerprint) const { - for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { +template +entry_pos_t HashIndex::findMatchedEntryInSlot(TransactionType trxType, const Slot& slot, + Key key, uint8_t fingerprint) const { + for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { if (slot.header.isEntryValid(entryPos) && slot.header.fingerprints[entryPos] == fingerprint && - equals(trxType, key, *(S*)slot.entries[entryPos].data)) { + equals(trxType, key, slot.entries[entryPos].key)) { return entryPos; } } return SlotHeader::INVALID_ENTRY_POS; } -template -void HashIndex::prepareCommit() { - std::unique_lock xlock{localStorage->localStorageSharedMutex}; +template +void HashIndex::prepareCommit() { if (localStorage->hasUpdates()) { wal->addToUpdatedTables(dbFileIDAndName.dbFileID.nodeIndexID.tableID); localStorage->applyLocalChanges( - [this](T key) -> void { this->deleteFromPersistentIndex(key); }, - [this](T key, offset_t value) -> void { this->insertIntoPersistentIndex(key, value); }); + [this](Key key) -> void { this->deleteFromPersistentIndex(key); }, + [this](Key key, offset_t value) -> void { + this->insertIntoPersistentIndex(key, value); + }); headerArray->update(INDEX_HEADER_IDX_IN_ARRAY, *indexHeaderForWriteTrx); + headerArray->prepareCommit(); + pSlots->prepareCommit(); + oSlots->prepareCommit(); } } -template -void HashIndex::prepareRollback() { - std::unique_lock xlock{localStorage->localStorageSharedMutex}; +template +void HashIndex::prepareRollback() { if (localStorage->hasUpdates()) { wal->addToUpdatedTables(dbFileIDAndName.dbFileID.nodeIndexID.tableID); } } -template -void HashIndex::checkpointInMemory() { +template +void HashIndex::checkpointInMemory() { if (!localStorage->hasUpdates()) { return; } @@ -283,10 +284,13 @@ void HashIndex::checkpointInMemory() { pSlots->checkpointInMemoryIfNecessary(); oSlots->checkpointInMemoryIfNecessary(); localStorage->clear(); + if constexpr (std::same_as) { + overflowFileHandle->checkpointInMemory(); + } } -template -void HashIndex::rollbackInMemory() { +template +void HashIndex::rollbackInMemory() { if (!localStorage->hasUpdates()) { return; } @@ -298,46 +302,45 @@ void HashIndex::rollbackInMemory() { } template<> -inline bool HashIndex::equals(transaction::TransactionType trxType, +inline bool HashIndex::equals(transaction::TransactionType trxType, std::string_view keyToLookup, const ku_string_t& keyInEntry) const { if (HashIndexUtils::areStringPrefixAndLenEqual(keyToLookup, keyInEntry)) { - auto entryKeyString = diskOverflowFile->readString(trxType, keyInEntry); + auto entryKeyString = overflowFileHandle->readString(trxType, keyInEntry); return memcmp(keyToLookup.data(), entryKeyString.c_str(), entryKeyString.length()) == 0; } return false; } template<> -inline void HashIndex::insert( - std::string_view key, uint8_t* entry, common::offset_t offset) { - auto kuString = diskOverflowFile->writeString(key); - memcpy(entry, &kuString, NUM_BYTES_FOR_STRING_KEY); - memcpy(entry + NUM_BYTES_FOR_STRING_KEY, &offset, sizeof(common::offset_t)); +inline void HashIndex::insert(std::string_view key, SlotEntry& entry, + common::offset_t offset) { + entry.key = overflowFileHandle->writeString(key); + entry.value = offset; } -template -void HashIndex::rehashSlots(HashIndexHeader& header) { +template +void HashIndex::rehashSlots(HashIndexHeader& header) { auto slotsToSplit = getChainedSlots(header.nextSplitSlotId); for (auto& [slotInfo, slot] : slotsToSplit) { auto slotHeader = slot.header; slot.header.reset(); updateSlot(slotInfo, slot); - for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { + for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { if (!slotHeader.isEntryValid(entryPos)) { continue; // Skip invalid entries. } - auto key = (S*)slot.entries[entryPos].data; - hash_t hash = this->hashStored(TransactionType::WRITE, *key); + const auto& key = slot.entries[entryPos].key; + hash_t hash = this->hashStored(TransactionType::WRITE, key); auto fingerprint = HashIndexUtils::getFingerprintForHash(hash); auto newSlotId = hash & header.higherLevelHashMask; - copyEntryToSlot(newSlotId, *key, fingerprint); + copyEntryToSlot(newSlotId, key, fingerprint); } } } -template -std::vector>> HashIndex::getChainedSlots(slot_id_t pSlotId) { - std::vector>> slots; +template +std::vector>> HashIndex::getChainedSlots(slot_id_t pSlotId) { + std::vector>> slots; SlotInfo slotInfo{pSlotId, SlotType::PRIMARY}; while (slotInfo.slotType == SlotType::PRIMARY || slotInfo.slotId != 0) { auto slot = getSlot(TransactionType::WRITE, slotInfo); @@ -348,22 +351,22 @@ std::vector>> HashIndex::getChainedSlots(slot_ return slots; } -template -void HashIndex::copyEntryToSlot(slot_id_t slotId, const S& entry, uint8_t fingerprint) { +template +void HashIndex::copyEntryToSlot(slot_id_t slotId, const T& entry, uint8_t fingerprint) { auto iter = getSlotIterator(slotId, TransactionType::WRITE); do { - if (iter.slot.header.numEntries() < getSlotCapacity()) { + if (iter.slot.header.numEntries() < getSlotCapacity()) { // Found a slot with empty space. break; } } while (nextChainedSlot(TransactionType::WRITE, iter)); - copyKVOrEntryToSlot( - iter.slotInfo, iter.slot, entry, UINT32_MAX, fingerprint); + copyKVOrEntryToSlot(iter.slotInfo, iter.slot, entry, + UINT32_MAX, fingerprint); updateSlot(iter.slotInfo, iter.slot); } -template -HashIndex::~HashIndex() = default; +template +HashIndex::~HashIndex() = default; template class HashIndex; template class HashIndex; @@ -376,7 +379,7 @@ template class HashIndex; template class HashIndex; template class HashIndex; template class HashIndex; -template class HashIndex; +template class HashIndex; PrimaryKeyIndex::PrimaryKeyIndex(const DBFileIDAndName& dbFileIDAndName, bool readOnly, common::PhysicalTypeID keyDataType, BufferManager& bufferManager, WAL* wal, @@ -389,25 +392,25 @@ PrimaryKeyIndex::PrimaryKeyIndex(const DBFileIDAndName& dbFileIDAndName, bool re if (keyDataTypeID == PhysicalTypeID::STRING) { overflowFile = - std::make_shared(dbFileIDAndName, &bufferManager, wal, readOnly, vfs); + std::make_unique(dbFileIDAndName, &bufferManager, wal, readOnly, vfs); } hashIndices.reserve(NUM_HASH_INDEXES); - TypeUtils::visit(keyDataTypeID, [&](T) { - if constexpr (std::is_same_v) { + TypeUtils::visit( + keyDataTypeID, + [&](ku_string_t) { for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { - hashIndices.push_back(std::make_unique>( - dbFileIDAndName, fileHandle, overflowFile, i, bufferManager, wal)); + hashIndices.push_back(std::make_unique>(dbFileIDAndName, + fileHandle, overflowFile->addHandle(), i, bufferManager, wal)); } - } else if constexpr (HashablePrimitive) { + }, + [&](T) { for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { - hashIndices.push_back(std::make_unique>( - dbFileIDAndName, fileHandle, overflowFile, i, bufferManager, wal)); + hashIndices.push_back(std::make_unique>(dbFileIDAndName, fileHandle, + nullptr, i, bufferManager, wal)); } - } else { - KU_UNREACHABLE; - } - }); + }, + [&](auto) { KU_UNREACHABLE; }); } bool PrimaryKeyIndex::lookup(Transaction* trx, common::ValueVector* keyVector, uint64_t vectorPos, @@ -423,8 +426,8 @@ bool PrimaryKeyIndex::lookup(Transaction* trx, common::ValueVector* keyVector, u return retVal; } -bool PrimaryKeyIndex::insert( - common::ValueVector* keyVector, uint64_t vectorPos, common::offset_t value) { +bool PrimaryKeyIndex::insert(common::ValueVector* keyVector, uint64_t vectorPos, + common::offset_t value) { bool result = false; TypeUtils::visit( keyDataTypeID, @@ -456,18 +459,27 @@ void PrimaryKeyIndex::checkpointInMemory() { for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { hashIndices[i]->checkpointInMemory(); } + if (overflowFile) { + overflowFile->checkpointInMemory(); + } } void PrimaryKeyIndex::rollbackInMemory() { for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { hashIndices[i]->rollbackInMemory(); } + if (overflowFile) { + overflowFile->rollbackInMemory(); + } } void PrimaryKeyIndex::prepareCommit() { for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { hashIndices[i]->prepareCommit(); } + if (overflowFile) { + overflowFile->prepareCommit(); + } } void PrimaryKeyIndex::prepareRollback() { diff --git a/src/storage/index/hash_index_builder.cpp b/src/storage/index/hash_index_builder.cpp index 0584d005964..b5c80286bc5 100644 --- a/src/storage/index/hash_index_builder.cpp +++ b/src/storage/index/hash_index_builder.cpp @@ -9,60 +9,61 @@ #include "common/types/types.h" #include "storage/index/hash_index_slot.h" #include "storage/index/hash_index_utils.h" -#include "storage/storage_structure/in_mem_file.h" +#include "storage/storage_structure/overflow_file.h" using namespace kuzu::common; namespace kuzu { namespace storage { -template -HashIndexBuilder::HashIndexBuilder(const std::shared_ptr& fileHandle, - std::unique_ptr overflowFile, uint64_t indexPos, PhysicalTypeID keyDataType) - : fileHandle(fileHandle), inMemOverflowFile(std::move(overflowFile)) { +template +HashIndexBuilder::HashIndexBuilder(const std::shared_ptr& fileHandle, + OverflowFileHandle* overflowFileHandle, uint64_t indexPos, PhysicalTypeID keyDataType) + : fileHandle(fileHandle), overflowFileHandle(overflowFileHandle) { this->indexHeader = std::make_unique(keyDataType); headerArray = std::make_unique>(*fileHandle, NUM_HEADER_PAGES * indexPos + INDEX_HEADER_ARRAY_HEADER_PAGE_IDX, 0 /* numElements */); - pSlots = std::make_unique>>( - *fileHandle, NUM_HEADER_PAGES * indexPos + P_SLOTS_HEADER_PAGE_IDX, 0 /* numElements */); + pSlots = std::make_unique>>(*fileHandle, + NUM_HEADER_PAGES * indexPos + P_SLOTS_HEADER_PAGE_IDX, 0 /* numElements */); // Reserve a slot for oSlots, which is always skipped, as we treat slot idx 0 as NULL. - oSlots = std::make_unique>>( - *fileHandle, NUM_HEADER_PAGES * indexPos + O_SLOTS_HEADER_PAGE_IDX, 1 /* numElements */); + oSlots = std::make_unique>>(*fileHandle, + NUM_HEADER_PAGES * indexPos + O_SLOTS_HEADER_PAGE_IDX, 1 /* numElements */); allocatePSlots(1u << this->indexHeader->currentLevel); } -template -void HashIndexBuilder::bulkReserve(uint32_t numEntries_) { +template +void HashIndexBuilder::bulkReserve(uint32_t numEntries_) { slot_id_t numRequiredEntries = HashIndexUtils::getNumRequiredEntries(this->indexHeader->numEntries, numEntries_); // Build from scratch. - auto numRequiredSlots = (numRequiredEntries + getSlotCapacity() - 1) / getSlotCapacity(); + auto numRequiredSlots = (numRequiredEntries + getSlotCapacity() - 1) / getSlotCapacity(); auto numSlotsOfCurrentLevel = 1u << this->indexHeader->currentLevel; - while ((numSlotsOfCurrentLevel << 1) < numRequiredSlots) { + while ((numSlotsOfCurrentLevel << 1) <= numRequiredSlots) { this->indexHeader->incrementLevel(); numSlotsOfCurrentLevel <<= 1; } - if (numRequiredSlots > numSlotsOfCurrentLevel) { + if (numRequiredSlots >= numSlotsOfCurrentLevel) { this->indexHeader->nextSplitSlotId = numRequiredSlots - numSlotsOfCurrentLevel; } + // The next slot to split should always be within the slots covered by the current level + // The level should be increased if it goes beyond that point + KU_ASSERT(this->indexHeader->nextSplitSlotId <= this->indexHeader->levelHashMask); auto existingSlots = pSlots->getNumElements(); if (numRequiredSlots > existingSlots) { allocatePSlots(numRequiredSlots - existingSlots); } } -template -void HashIndexBuilder::copy( - const uint8_t* oldEntry, slot_id_t newSlotId, uint8_t fingerprint) { +template +void HashIndexBuilder::copy(const uint8_t* oldEntry, slot_id_t newSlotId, uint8_t fingerprint) { SlotIterator iter(newSlotId, this); do { - for (auto newEntryPos = 0u; newEntryPos < getSlotCapacity(); newEntryPos++) { + for (auto newEntryPos = 0u; newEntryPos < getSlotCapacity(); newEntryPos++) { if (!iter.slot->header.isEntryValid(newEntryPos)) { // The original slot was marked as unused, but // copying to the original slot is unnecessary and will cause undefined behaviour - if (oldEntry != iter.slot->entries[newEntryPos].data) { - memcpy(iter.slot->entries[newEntryPos].data, oldEntry, - this->indexHeader->numBytesPerEntry); + if (oldEntry != iter.slot->entries[newEntryPos].data()) { + iter.slot->entries[newEntryPos].copyFrom(oldEntry); } iter.slot->header.setEntryValid(newEntryPos, fingerprint); return; @@ -74,12 +75,12 @@ void HashIndexBuilder::copy( iter.slot->header.nextOvfSlotId = newOvfSlotId; auto newOvfSlot = getSlot(SlotInfo{newOvfSlotId, SlotType::OVF}); auto newEntryPos = 0u; // Always insert to the first entry when there is a new slot. - memcpy(newOvfSlot->entries[newEntryPos].data, oldEntry, this->indexHeader->numBytesPerEntry); + newOvfSlot->entries[newEntryPos].copyFrom(oldEntry); newOvfSlot->header.setEntryValid(newEntryPos, fingerprint); } -template -void HashIndexBuilder::splitSlot(HashIndexHeader& header) { +template +void HashIndexBuilder::splitSlot(HashIndexHeader& header) { // Add new slot allocatePSlots(1); @@ -91,36 +92,50 @@ void HashIndexBuilder::splitSlot(HashIndexHeader& header) { // Reset everything except the next overflow id so we can reuse the overflow slot iter.slot->header.reset(); iter.slot->header.nextOvfSlotId = slotHeader.nextOvfSlotId; - for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { + for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { if (!slotHeader.isEntryValid(entryPos)) { continue; // Skip invalid entries. } - const auto* data = (iter.slot->entries[entryPos].data); - hash_t hash = this->hashStored(*reinterpret_cast(data)); + const auto& entry = iter.slot->entries[entryPos]; + hash_t hash = this->hashStored(entry.key); auto fingerprint = HashIndexUtils::getFingerprintForHash(hash); auto newSlotId = hash & header.higherLevelHashMask; - copy(data, newSlotId, fingerprint); + copy(entry.data(), newSlotId, fingerprint); } } while (nextChainedSlot(iter)); header.incrementNextSplitSlotId(); } -template -bool HashIndexBuilder::append(T key, offset_t value) { +template +size_t HashIndexBuilder::append(const IndexBuffer& buffer) { slot_id_t numRequiredEntries = - HashIndexUtils::getNumRequiredEntries(this->indexHeader->numEntries, 1); - while (numRequiredEntries > pSlots->getNumElements() * getSlotCapacity()) { + HashIndexUtils::getNumRequiredEntries(this->indexHeader->numEntries, buffer.size()); + while (numRequiredEntries > pSlots->getNumElements() * getSlotCapacity()) { this->splitSlot(*this->indexHeader); } // Do both searches after splitting. Returning early if the key already exists isn't a // particular concern and doing both after splitting allows the slotID to be reused - auto hashValue = HashIndexUtils::hash(key); - auto fingerprint = HashIndexUtils::getFingerprintForHash(hashValue); - auto slotID = HashIndexUtils::getPrimarySlotIdForHash(*this->indexHeader, hashValue); + common::hash_t hashes[BUFFER_SIZE]; + for (size_t i = 0; i < buffer.size(); i++) { + hashes[i] = HashIndexUtils::hash(buffer[i].first); + } + for (size_t i = 0; i < buffer.size(); i++) { + auto& [key, value] = buffer[i]; + if (!appendInternal(key, value, hashes[i])) { + return i; + } + } + return buffer.size(); +} + +template +bool HashIndexBuilder::appendInternal(Key key, common::offset_t value, common::hash_t hash) { + auto fingerprint = HashIndexUtils::getFingerprintForHash(hash); + auto slotID = HashIndexUtils::getPrimarySlotIdForHash(*this->indexHeader, hash); SlotIterator iter(slotID, this); do { - for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { + for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { if (!iter.slot->header.isEntryValid(entryPos)) { // Insert to this position // The builder never keeps holes and doesn't support deletions, so this must be the @@ -130,7 +145,7 @@ bool HashIndexBuilder::append(T key, offset_t value) { this->indexHeader->numEntries++; return true; } else if (iter.slot->header.fingerprints[entryPos] == fingerprint && - equals(key, *(S*)iter.slot->entries[entryPos].data)) { + equals(key, iter.slot->entries[entryPos].key)) { // Value already exists return false; } @@ -142,20 +157,19 @@ bool HashIndexBuilder::append(T key, offset_t value) { return true; } -template -bool HashIndexBuilder::lookup(T key, offset_t& result) { +template +bool HashIndexBuilder::lookup(Key key, offset_t& result) { auto hashValue = HashIndexUtils::hash(key); auto fingerprint = HashIndexUtils::getFingerprintForHash(hashValue); auto slotId = HashIndexUtils::getPrimarySlotIdForHash(*this->indexHeader, hashValue); SlotIterator iter(slotId, this); do { - for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { + for (auto entryPos = 0u; entryPos < getSlotCapacity(); entryPos++) { if (iter.slot->header.isEntryValid(entryPos) && iter.slot->header.fingerprints[entryPos] == fingerprint && - equals(key, *(S*)iter.slot->entries[entryPos].data)) { + equals(key, iter.slot->entries[entryPos].key)) { // Value already exists - result = *(common::offset_t*)(iter.slot->entries[entryPos].data + - this->indexHeader->numBytesPerKey); + result = iter.slot->entries[entryPos].value; return true; } } @@ -163,24 +177,24 @@ bool HashIndexBuilder::lookup(T key, offset_t& result) { return false; } -template -uint32_t HashIndexBuilder::allocatePSlots(uint32_t numSlotsToAllocate) { +template +uint32_t HashIndexBuilder::allocatePSlots(uint32_t numSlotsToAllocate) { auto oldNumSlots = pSlots->getNumElements(); auto newNumSlots = oldNumSlots + numSlotsToAllocate; pSlots->resize(newNumSlots, true /* setToZero */); return oldNumSlots; } -template -uint32_t HashIndexBuilder::allocateAOSlot() { +template +uint32_t HashIndexBuilder::allocateAOSlot() { auto oldNumSlots = oSlots->getNumElements(); auto newNumSlots = oldNumSlots + 1; oSlots->resize(newNumSlots, true /* setToZero */); return oldNumSlots; } -template -Slot* HashIndexBuilder::getSlot(const SlotInfo& slotInfo) { +template +Slot* HashIndexBuilder::getSlot(const SlotInfo& slotInfo) { if (slotInfo.slotType == SlotType::PRIMARY) { return &pSlots->operator[](slotInfo.slotId); } else { @@ -188,21 +202,18 @@ Slot* HashIndexBuilder::getSlot(const SlotInfo& slotInfo) { } } -template -void HashIndexBuilder::flush() { +template +void HashIndexBuilder::flush() { headerArray->resize(1, true /* setToZero */); headerArray->operator[](0) = *this->indexHeader; headerArray->saveToDisk(); pSlots->saveToDisk(); oSlots->saveToDisk(); - if constexpr (std::is_same_v) { - inMemOverflowFile->flush(); - } } -template -inline void HashIndexBuilder::insertToNewOvfSlot( - T key, Slot* previousSlot, common::offset_t offset, uint8_t fingerprint) { +template +inline void HashIndexBuilder::insertToNewOvfSlot(Key key, Slot* previousSlot, + common::offset_t offset, uint8_t fingerprint) { auto newSlotId = allocateAOSlot(); previousSlot->header.nextOvfSlotId = newSlotId; auto newSlot = getSlot(SlotInfo{newSlotId, SlotType::OVF}); @@ -211,29 +222,29 @@ inline void HashIndexBuilder::insertToNewOvfSlot( } template<> -void HashIndexBuilder::insert(std::string_view key, - Slot* slot, uint8_t entryPos, offset_t offset, uint8_t fingerprint) { - auto entry = slot->entries[entryPos].data; - inMemOverflowFile->appendString(key, *(ku_string_t*)entry); - memcpy(entry + NUM_BYTES_FOR_STRING_KEY, &offset, sizeof(common::offset_t)); +void HashIndexBuilder::insert(std::string_view key, Slot* slot, + uint8_t entryPos, offset_t offset, uint8_t fingerprint) { + auto& entry = slot->entries[entryPos]; + entry.key = overflowFileHandle->writeString(key); + entry.value = offset; slot->header.setEntryValid(entryPos, fingerprint); } -template -common::hash_t HashIndexBuilder::hashStored(const S& key) const { +template +common::hash_t HashIndexBuilder::hashStored(const T& key) const { return HashIndexUtils::hash(key); } template<> -common::hash_t HashIndexBuilder::hashStored( - const ku_string_t& key) const { +common::hash_t HashIndexBuilder::hashStored(const ku_string_t& key) const { auto kuString = key; - return HashIndexUtils::hash(inMemOverflowFile->readString(&kuString)); + return HashIndexUtils::hash( + overflowFileHandle->readString(transaction::TransactionType::WRITE, kuString)); } template<> -bool HashIndexBuilder::equals( - std::string_view keyToLookup, const ku_string_t& keyInEntry) const { +bool HashIndexBuilder::equals(std::string_view keyToLookup, + const ku_string_t& keyInEntry) const { // Checks if prefix and len matches first. if (!HashIndexUtils::areStringPrefixAndLenEqual(keyToLookup, keyInEntry)) { return false; @@ -247,7 +258,8 @@ bool HashIndexBuilder::equals( return memcmp(keyToLookup.data(), keyInEntry.prefix, keyInEntry.len) == 0; } else { // For long strings, compare with overflow data - return inMemOverflowFile->equals(keyToLookup, keyInEntry); + return overflowFileHandle->equals(transaction::TransactionType::WRITE, keyToLookup, + keyInEntry); } } @@ -262,11 +274,11 @@ template class HashIndexBuilder; template class HashIndexBuilder; template class HashIndexBuilder; template class HashIndexBuilder; -template class HashIndexBuilder; +template class HashIndexBuilder; -PrimaryKeyIndexBuilder::PrimaryKeyIndexBuilder( - const std::string& fName, PhysicalTypeID keyDataType, VirtualFileSystem* vfs) - : keyDataTypeID{keyDataType}, overflowPageCounter(0) { +PrimaryKeyIndexBuilder::PrimaryKeyIndexBuilder(const std::string& fName, PhysicalTypeID keyDataType, + VirtualFileSystem* vfs) + : keyDataTypeID{keyDataType} { auto fileHandle = std::make_shared(fName, FileHandle::O_PERSISTENT_FILE_CREATE_NOT_EXISTS, vfs); fileHandle->addNewPages(NUM_HEADER_PAGES * NUM_HASH_INDEXES); @@ -275,20 +287,16 @@ PrimaryKeyIndexBuilder::PrimaryKeyIndexBuilder( keyDataTypeID, [&](T) { if constexpr (std::is_same_v) { - auto overflowFileInfo = std::shared_ptr(vfs->openFile( - StorageUtils::getOverflowFileName(fileHandle->getFileInfo()->path), - O_CREAT | O_WRONLY)); + overflowFile = std::make_unique( + StorageUtils::getOverflowFileName(fileHandle->getFileInfo()->path), vfs); for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { - auto overflowFile = - std::make_unique(overflowFileInfo, overflowPageCounter); - hashIndexBuilders.push_back( - std::make_unique>( - fileHandle, std::move(overflowFile), i, keyDataType)); + hashIndexBuilders.push_back(std::make_unique>( + fileHandle, overflowFile->addHandle(), i, keyDataType)); } } else if constexpr (HashablePrimitive) { for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { - hashIndexBuilders.push_back(std::make_unique>( - fileHandle, std::unique_ptr(), i, keyDataType)); + hashIndexBuilders.push_back( + std::make_unique>(fileHandle, nullptr, i, keyDataType)); } } else { KU_UNREACHABLE; @@ -305,6 +313,9 @@ void PrimaryKeyIndexBuilder::bulkReserve(uint32_t numEntries) { } void PrimaryKeyIndexBuilder::flush() { + if (overflowFile) { + overflowFile->prepareCommit(); + } for (auto i = 0u; i < NUM_HASH_INDEXES; i++) { hashIndexBuilders[i]->flush(); } diff --git a/src/storage/local_storage/local_node_table.cpp b/src/storage/local_storage/local_node_table.cpp index b9356602922..2a98e63127a 100644 --- a/src/storage/local_storage/local_node_table.cpp +++ b/src/storage/local_storage/local_node_table.cpp @@ -2,6 +2,7 @@ #include "common/cast.h" #include "storage/storage_utils.h" +#include "storage/store/node_table.h" using namespace kuzu::common; @@ -13,7 +14,6 @@ void LocalNodeNG::scan(ValueVector* nodeIDVector, const std::vector KU_ASSERT(columnIDs.size() == outputVectors.size()); for (auto i = 0u; i < columnIDs.size(); i++) { auto columnID = columnIDs[i]; - KU_ASSERT(columnID < chunks.size()); for (auto pos = 0u; pos < nodeIDVector->state->selVector->selectedSize; pos++) { auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[pos]; auto nodeOffset = nodeIDVector->getValue(nodeIDPos).offset; @@ -23,75 +23,73 @@ void LocalNodeNG::scan(ValueVector* nodeIDVector, const std::vector } } -void LocalNodeNG::lookup( - offset_t nodeOffset, column_id_t columnID, ValueVector* outputVector, sel_t posInOutputVector) { - KU_ASSERT(columnID < chunks.size()); - row_idx_t rowIdx = getRowIdx(columnID, nodeOffset - nodeGroupStartOffset); - if (rowIdx != INVALID_ROW_IDX) { - chunks[columnID]->read(rowIdx, outputVector, posInOutputVector); +void LocalNodeNG::lookup(offset_t nodeOffset, column_id_t columnID, ValueVector* outputVector, + sel_t posInOutputVector) { + if (deleteInfo.containsOffset(nodeOffset)) { + // Node has been deleted. + return; + } + if (insertChunks.read(nodeOffset, columnID, outputVector, posInOutputVector)) { + // Node has been newly inserted. + return; } + updateChunks[columnID].read(nodeOffset, 0 /*columnID*/, outputVector, posInOutputVector); } -void LocalNodeNG::insert( - ValueVector* nodeIDVector, const std::vector& propertyVectors) { - KU_ASSERT(propertyVectors.size() == chunks.size() && - nodeIDVector->state->selVector->selectedSize == 1); +bool LocalNodeNG::insert(std::vector nodeIDVectors, + std::vector propertyVectors) { + KU_ASSERT(nodeIDVectors.size() == 1); + auto nodeIDVector = nodeIDVectors[0]; + KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[0]; if (nodeIDVector->isNull(nodeIDPos)) { - return; + return false; } + // The nodeOffset here should be the offset within the node group. auto nodeOffset = nodeIDVector->getValue(nodeIDPos).offset - nodeGroupStartOffset; KU_ASSERT(nodeOffset < StorageConstants::NODE_GROUP_SIZE); - for (auto columnID = 0u; columnID < chunks.size(); columnID++) { - auto rowIdx = chunks[columnID]->append(propertyVectors[columnID]); - KU_ASSERT(!updateInfo[columnID].contains(nodeOffset)); - insertInfo[columnID][nodeOffset] = rowIdx; - } + insertChunks.append(nodeOffset, propertyVectors); + return true; } -void LocalNodeNG::update( - ValueVector* nodeIDVector, column_id_t columnID, ValueVector* propertyVector) { - KU_ASSERT(columnID < chunks.size() && nodeIDVector->state->selVector->selectedSize == 1); +bool LocalNodeNG::update(std::vector nodeIDVectors, + common::column_id_t columnID, common::ValueVector* propertyVector) { + KU_ASSERT(nodeIDVectors.size() == 1); + auto nodeIDVector = nodeIDVectors[0]; + KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[0]; if (nodeIDVector->isNull(nodeIDPos)) { - return; + return false; } auto nodeOffset = nodeIDVector->getValue(nodeIDPos).offset - nodeGroupStartOffset; - KU_ASSERT(nodeOffset < StorageConstants::NODE_GROUP_SIZE); - auto rowIdx = chunks[columnID]->append(propertyVector); - if (insertInfo[columnID].contains(nodeOffset)) { - // This node is in local storage, and had been newly inserted. - insertInfo.at(columnID)[nodeOffset] = rowIdx; + KU_ASSERT(nodeOffset < StorageConstants::NODE_GROUP_SIZE && columnID < updateChunks.size()); + // Check if the node is newly inserted or in persistent storage. + if (insertChunks.hasOffset(nodeOffset)) { + insertChunks.update(nodeOffset, columnID, propertyVector); } else { - updateInfo[columnID][nodeOffset] = rowIdx; + updateChunks[columnID].append(nodeOffset, {propertyVector}); } + return true; } -void LocalNodeNG::delete_(ValueVector* nodeIDVector) { +bool LocalNodeNG::delete_(common::ValueVector* nodeIDVector, common::ValueVector* /*extraVector*/) { KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[0]; if (nodeIDVector->isNull(nodeIDPos)) { - return; + return false; } auto nodeOffset = nodeIDVector->getValue(nodeIDPos).offset - nodeGroupStartOffset; KU_ASSERT(nodeOffset < StorageConstants::NODE_GROUP_SIZE); - for (auto i = 0u; i < chunks.size(); i++) { - insertInfo[i].erase(nodeOffset); - updateInfo[i].erase(nodeOffset); - } -} - -row_idx_t LocalNodeNG::getRowIdx(column_id_t columnID, offset_t offsetInChunk) { - KU_ASSERT(columnID < chunks.size()); - if (updateInfo[columnID].contains(offsetInChunk)) { - // This node is in persistent storage, and had been updated. - return updateInfo[columnID][offsetInChunk]; - } else if (insertInfo[columnID].contains(offsetInChunk)) { - // This node is in local storage, and had been newly inserted. - return insertInfo[columnID][offsetInChunk]; + // Check if the node is newly inserted or in persistent storage. + if (insertChunks.hasOffset(nodeOffset)) { + insertChunks.remove(nodeOffset); } else { - return INVALID_ROW_IDX; + for (auto i = 0u; i < updateChunks.size(); i++) { + updateChunks[i].remove(nodeOffset); + } + deleteInfo.deleteOffset(nodeOffset); } + return true; } void LocalNodeTableData::scan(ValueVector* nodeIDVector, const std::vector& columnIDs, @@ -125,46 +123,59 @@ void LocalNodeTableData::lookup(ValueVector* nodeIDVector, } } -void LocalNodeTableData::insert( - ValueVector* nodeIDVector, const std::vector& propertyVectors) { - KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); - auto localNodeGroup = - ku_dynamic_cast(getOrCreateLocalNodeGroup(nodeIDVector)); - KU_ASSERT(localNodeGroup); - localNodeGroup->insert(nodeIDVector, propertyVectors); -} - -void LocalNodeTableData::update( - ValueVector* nodeIDVector, column_id_t columnID, ValueVector* propertyVector) { - auto localNodeGroup = - ku_dynamic_cast(getOrCreateLocalNodeGroup(nodeIDVector)); - KU_ASSERT(localNodeGroup); - localNodeGroup->update(nodeIDVector, columnID, propertyVector); -} - -void LocalNodeTableData::delete_(ValueVector* nodeIDVector) { - auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[0]; - auto nodeOffset = nodeIDVector->getValue(nodeIDPos).offset; - auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(nodeOffset); - if (!nodeGroups.contains(nodeGroupIdx)) { - return; - } - auto localNodeGroup = - ku_dynamic_cast(nodeGroups.at(nodeGroupIdx).get()); - localNodeGroup->delete_(nodeIDVector); -} - LocalNodeGroup* LocalNodeTableData::getOrCreateLocalNodeGroup(common::ValueVector* nodeIDVector) { auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[0]; auto nodeOffset = nodeIDVector->getValue(nodeIDPos).offset; auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(nodeOffset); if (!nodeGroups.contains(nodeGroupIdx)) { auto nodeGroupStartOffset = StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); - nodeGroups[nodeGroupIdx] = - std::make_unique(nodeGroupStartOffset, dataTypes, mm); + nodeGroups[nodeGroupIdx] = std::make_unique(nodeGroupStartOffset, dataTypes); } return nodeGroups.at(nodeGroupIdx).get(); } +LocalNodeTable::LocalNodeTable(Table& table) : LocalTable{table} { + auto& nodeTable = ku_dynamic_cast(table); + std::vector types; + types.reserve(nodeTable.getNumColumns()); + for (auto i = 0u; i < nodeTable.getNumColumns(); i++) { + types.push_back(nodeTable.getColumn(i)->getDataType()); + } + localTableDataCollection.push_back(std::make_unique(types)); +} + +bool LocalNodeTable::insert(TableInsertState& state) { + auto& insertState = ku_dynamic_cast(state); + return localTableDataCollection[0]->insert({&insertState.nodeIDVector}, + insertState.propertyVectors); +} + +bool LocalNodeTable::update(TableUpdateState& state) { + auto& updateState = ku_dynamic_cast(state); + return localTableDataCollection[0]->update( + {const_cast(&updateState.nodeIDVector)}, updateState.columnID, + const_cast(&updateState.propertyVector)); +} + +bool LocalNodeTable::delete_(TableDeleteState& deleteState) { + auto& deleteState_ = ku_dynamic_cast(deleteState); + return localTableDataCollection[0]->delete_( + const_cast(&deleteState_.nodeIDVector), nullptr); +} + +void LocalNodeTable::scan(TableReadState& state) { + auto localTableData = + ku_dynamic_cast(localTableDataCollection[0].get()); + localTableData->scan(const_cast(&state.nodeIDVector), state.columnIDs, + state.outputVectors); +} + +void LocalNodeTable::lookup(TableReadState& state) { + auto localTableData = + ku_dynamic_cast(localTableDataCollection[0].get()); + localTableData->lookup(const_cast(&state.nodeIDVector), state.columnIDs, + state.outputVectors); +} + } // namespace storage } // namespace kuzu diff --git a/src/storage/local_storage/local_rel_table.cpp b/src/storage/local_storage/local_rel_table.cpp index ffdc53a8a07..6dd9af07700 100644 --- a/src/storage/local_storage/local_rel_table.cpp +++ b/src/storage/local_storage/local_rel_table.cpp @@ -1,282 +1,197 @@ #include "storage/local_storage/local_rel_table.h" -#include "common/cast.h" #include "storage/storage_utils.h" +#include "storage/store/rel_table.h" using namespace kuzu::common; namespace kuzu { namespace storage { -bool RelNGInfo::insert(offset_t srcOffsetInChunk, offset_t relOffset, row_idx_t adjNodeRowIdx, - const std::vector& propertyNodesRowIdx) { - KU_ASSERT(propertyNodesRowIdx.size() == insertInfoPerChunk.size()); - if (deleteInfo.contains(srcOffsetInChunk) && - contains(deleteInfo.at(srcOffsetInChunk), relOffset)) { - deleteInfo.at(srcOffsetInChunk).erase(relOffset); - } - if (adjInsertInfo.contains(srcOffsetInChunk)) { - if (multiplicity == RelMultiplicity::ONE) { - throw RuntimeException("Inserting multiple edges to a single node in a " - "ONE_ONE/MANY_ONE relationship is not allowed."); - } - adjInsertInfo.at(srcOffsetInChunk)[relOffset] = adjNodeRowIdx; - } else { - adjInsertInfo[srcOffsetInChunk] = {{relOffset, adjNodeRowIdx}}; - } - for (auto i = 0u; i < propertyNodesRowIdx.size(); ++i) { - if (insertInfoPerChunk[i].contains(srcOffsetInChunk)) { - insertInfoPerChunk[i].at(srcOffsetInChunk)[relOffset] = propertyNodesRowIdx[i]; - } else { - insertInfoPerChunk[i][srcOffsetInChunk] = {{relOffset, propertyNodesRowIdx[i]}}; - } - } - return false; -} - -void RelNGInfo::update( - offset_t srcOffsetInChunk, offset_t relOffset, column_id_t columnID, row_idx_t rowIdx) { - // REL_ID_COLUMN_ID is immutable. - KU_ASSERT(columnID != REL_ID_COLUMN_ID && columnID < updateInfoPerChunk.size()); - if (deleteInfo.contains(srcOffsetInChunk) && - contains(deleteInfo.at(srcOffsetInChunk), relOffset)) { - // We choose to ignore the update operation if the node is deleted. - return; - } - if (insertInfoPerChunk[columnID].contains(srcOffsetInChunk) && - insertInfoPerChunk[columnID].at(srcOffsetInChunk).contains(relOffset)) { - // Update newly inserted value. - insertInfoPerChunk[columnID].at(srcOffsetInChunk)[relOffset] = rowIdx; - } else { - if (updateInfoPerChunk[columnID].contains(srcOffsetInChunk)) { - updateInfoPerChunk[columnID].at(srcOffsetInChunk)[relOffset] = rowIdx; - } else { - updateInfoPerChunk[columnID][srcOffsetInChunk] = {{relOffset, rowIdx}}; - } - } -} - -bool RelNGInfo::delete_(offset_t srcOffsetInChunk, offset_t relOffset) { - if (adjInsertInfo.contains(srcOffsetInChunk) && - adjInsertInfo.at(srcOffsetInChunk).contains(relOffset)) { - // Delete newly inserted tuple. - adjInsertInfo.at(srcOffsetInChunk).erase(relOffset); - for (auto& insertInfo : insertInfoPerChunk) { - insertInfo.at(srcOffsetInChunk).erase(relOffset); - } - } else { - if (deleteInfo.contains(srcOffsetInChunk)) { - if (deleteInfo.at(srcOffsetInChunk).contains(relOffset)) { - // The node is already deleted. - return false; - } else { - deleteInfo.at(srcOffsetInChunk).insert(relOffset); - } - } else { - deleteInfo[srcOffsetInChunk] = {relOffset}; - } - } - return true; -} - -bool RelNGInfo::hasUpdates() { - for (auto& updateInfo : updateInfoPerChunk) { - if (!updateInfo.empty()) { - return true; - } - } - return false; -} - -const update_insert_info_t& RelNGInfo::getEmptyInfo() { - static update_insert_info_t emptyInfo; - return emptyInfo; -} +LocalRelNG::LocalRelNG(offset_t nodeGroupStartOffset, std::vector dataTypes) + : LocalNodeGroup{nodeGroupStartOffset, std::move(dataTypes)} {} -uint64_t RelNGInfo::getNumInsertedTuples(offset_t srcOffsetInChunk) { - return adjInsertInfo.contains(srcOffsetInChunk) ? adjInsertInfo.at(srcOffsetInChunk).size() : 0; -} - -LocalRelNG::LocalRelNG(offset_t nodeGroupStartOffset, std::vector dataTypes, - MemoryManager* mm, common::RelMultiplicity multiplicity) - : LocalNodeGroup{nodeGroupStartOffset, std::move(dataTypes), mm} { - relNGInfo = std::make_unique(multiplicity, chunks.size()); - adjChunk = std::make_unique(LogicalType::INTERNAL_ID(), mm); -} - -// TODO(Guodong): We should change the map between relID and rowIdx to a vector of pairs, which is -// more friendly for scan. row_idx_t LocalRelNG::scanCSR(offset_t srcOffsetInChunk, offset_t posToReadForOffset, const std::vector& columnIDs, const std::vector& outputVectors) { - KU_ASSERT(columnIDs.size() + 1 == outputVectors.size()); - KU_ASSERT(relNGInfo->adjInsertInfo.contains(srcOffsetInChunk)); - uint64_t posInVector = 0; - auto iteratorIdx = 0u; - for (auto& [relID, rowIdx] : relNGInfo->adjInsertInfo.at(srcOffsetInChunk)) { - if (iteratorIdx++ < posToReadForOffset) { - continue; + KU_ASSERT(columnIDs.size() == outputVectors.size()); + std::vector rowIdxesToRead; + rowIdxesToRead.reserve(DEFAULT_VECTOR_CAPACITY); + auto& insertedRelOffsets = insertChunks.getRelOffsetsFromSrcOffset(srcOffsetInChunk); + for (auto i = posToReadForOffset; i < insertedRelOffsets.size(); i++) { + if (rowIdxesToRead.size() == DEFAULT_VECTOR_CAPACITY) { + break; } - auto posInLocalVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - outputVectors[0]->copyFromVectorData( - posInVector++, adjChunk->getLocalVector(rowIdx)->getVector(), posInLocalVector); + rowIdxesToRead.push_back(insertChunks.getRowIdxFromOffset(insertedRelOffsets[i])); } - for (auto i = 0u; i < columnIDs.size(); ++i) { - auto columnID = columnIDs[i]; - posInVector = 0; - iteratorIdx = 0u; - auto& insertInfo = relNGInfo->insertInfoPerChunk[columnID]; - KU_ASSERT(insertInfo.contains(srcOffsetInChunk)); - for (auto& [relID, rowIdx] : insertInfo.at(srcOffsetInChunk)) { - if (iteratorIdx++ < posToReadForOffset) { - continue; - } - auto posInLocalVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - outputVectors[i + 1]->copyFromVectorData(posInVector++, - chunks[columnID]->getLocalVector(rowIdx)->getVector(), posInLocalVector); + for (auto i = 0u; i < columnIDs.size(); i++) { + uint64_t posInOutputVector = 0; + for (auto rowIdx : rowIdxesToRead) { + insertChunks.readValueAtRowIdx(rowIdx, columnIDs[i], outputVectors[i], + posInOutputVector++); } } - outputVectors[0]->state->selVector->resetSelectorToUnselectedWithSize(posInVector); - return posInVector; + auto numRelsRead = rowIdxesToRead.size(); + outputVectors[0]->state->selVector->setToUnfiltered(numRelsRead); + return numRelsRead; } -void LocalRelNG::applyLocalChangesForCSRColumns(offset_t srcOffsetInChunk, +void LocalRelNG::applyLocalChangesToScannedVectors(offset_t srcOffset, const std::vector& columnIDs, ValueVector* relIDVector, const std::vector& outputVectors) { - KU_ASSERT(columnIDs.size() + 1 == outputVectors.size()); + KU_ASSERT(columnIDs.size() == outputVectors.size()); // Apply updates first, as applying deletions might change selected state. for (auto i = 0u; i < columnIDs.size(); ++i) { - applyCSRUpdates(srcOffsetInChunk, columnIDs[i], relIDVector, outputVectors[i + 1]); + applyCSRUpdates(columnIDs[i], relIDVector, outputVectors[i]); } // Apply deletions and update selVector if necessary. - if (relNGInfo->deleteInfo.contains(srcOffsetInChunk) && - relNGInfo->deleteInfo.at(srcOffsetInChunk).size() > 0) { - applyCSRDeletions(srcOffsetInChunk, relNGInfo->deleteInfo, relIDVector); - } + applyCSRDeletions(srcOffset, relIDVector); } -void LocalRelNG::applyCSRUpdates(offset_t srcOffsetInChunk, column_id_t columnID, - ValueVector* relIDVector, ValueVector* outputVector) { - auto updateInfo = relNGInfo->updateInfoPerChunk[columnID]; - if (!updateInfo.contains(srcOffsetInChunk) || updateInfo.at(srcOffsetInChunk).empty()) { - return; - } - auto& updateInfoForOffset = updateInfo.at(srcOffsetInChunk); +void LocalRelNG::applyCSRUpdates(column_id_t columnID, ValueVector* relIDVector, + ValueVector* outputVector) { + auto& updateChunk = updateChunks[columnID]; for (auto i = 0u; i < relIDVector->state->selVector->selectedSize; i++) { auto pos = relIDVector->state->selVector->selectedPositions[i]; auto relOffset = relIDVector->getValue(pos).offset; - if (updateInfoForOffset.contains(relOffset)) { - auto rowIdx = updateInfoForOffset.at(relOffset); - auto posInLocalVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - outputVector->copyFromVectorData( - pos, chunks[columnID]->getLocalVector(rowIdx)->getVector(), posInLocalVector); + if (updateChunk.hasOffset(relOffset)) { + updateChunk.read(relOffset, 0, outputVector, pos); } } } -void LocalRelNG::applyCSRDeletions( - offset_t srcOffsetInChunk, const delete_info_t& deleteInfo, ValueVector* relIDVector) { - auto& deleteInfoForOffset = deleteInfo.at(srcOffsetInChunk); +void LocalRelNG::applyCSRDeletions(offset_t srcOffset, ValueVector* relIDVector) { + if (deleteInfo.isEmpty(srcOffset)) { + return; + } auto selectPos = 0u; auto selVector = std::make_unique(DEFAULT_VECTOR_CAPACITY); - selVector->resetSelectorToValuePosBuffer(); + selVector->setToFiltered(); for (auto i = 0u; i < relIDVector->state->selVector->selectedSize; i++) { auto relIDPos = relIDVector->state->selVector->selectedPositions[i]; auto relOffset = relIDVector->getValue(relIDPos).offset; - if (deleteInfoForOffset.contains(relOffset)) { + if (deleteInfo.containsOffset(relOffset)) { continue; } selVector->selectedPositions[selectPos++] = relIDPos; } if (selectPos != relIDVector->state->selVector->selectedSize) { - relIDVector->state->selVector->resetSelectorToValuePosBuffer(); + relIDVector->state->selVector->setToFiltered(); memcpy(relIDVector->state->selVector->selectedPositions, selVector->selectedPositions, selectPos * sizeof(sel_t)); relIDVector->state->selVector->selectedSize = selectPos; } } -bool LocalRelNG::insert(ValueVector* srcNodeIDVector, ValueVector* dstNodeIDVector, - const std::vector& propertyVectors) { - KU_ASSERT(propertyVectors.size() == chunks.size() && propertyVectors.size() >= 1); - auto adjNodeIDRowIdx = adjChunk->append(dstNodeIDVector); - std::vector propertyValuesRowIdx; - propertyValuesRowIdx.reserve(propertyVectors.size()); - for (auto i = 0u; i < propertyVectors.size(); ++i) { - propertyValuesRowIdx.push_back(chunks[i]->append(propertyVectors[i])); - } +// nodeIDVectors: srcNodeIDVector, dstNodeIDVector. +bool LocalRelNG::insert(std::vector nodeIDVectors, + std::vector propertyVectors) { + KU_ASSERT(nodeIDVectors.size() == 2); + auto srcNodeIDVector = nodeIDVectors[0]; + auto dstNodeIDVector = nodeIDVectors[1]; + KU_ASSERT(srcNodeIDVector->state->selVector->selectedSize == 1 && + dstNodeIDVector->state->selVector->selectedSize == 1); auto srcNodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; + auto dstNodeIDPos = dstNodeIDVector->state->selVector->selectedPositions[0]; + if (srcNodeIDVector->isNull(srcNodeIDPos) || dstNodeIDVector->isNull(dstNodeIDPos)) { + return false; + } auto srcNodeOffset = srcNodeIDVector->getValue(srcNodeIDPos).offset - nodeGroupStartOffset; KU_ASSERT(srcNodeOffset < StorageConstants::NODE_GROUP_SIZE); - auto relIDPos = propertyVectors[REL_ID_COLUMN_ID]->state->selVector->selectedPositions[0]; - auto relOffset = propertyVectors[REL_ID_COLUMN_ID]->getValue(relIDPos).offset; - return relNGInfo->insert(srcNodeOffset, relOffset, adjNodeIDRowIdx, propertyValuesRowIdx); + std::vector vectorsToInsert; + vectorsToInsert.push_back(dstNodeIDVector); + for (auto i = 0u; i < propertyVectors.size(); i++) { + vectorsToInsert.push_back(propertyVectors[i]); + } + auto relIDPos = vectorsToInsert[LOCAL_REL_ID_COLUMN_ID]->state->selVector->selectedPositions[0]; + auto relOffset = vectorsToInsert[LOCAL_REL_ID_COLUMN_ID]->getValue(relIDPos).offset; + insertChunks.append(srcNodeOffset, relOffset, vectorsToInsert); + return true; } -void LocalRelNG::update(ValueVector* srcNodeIDVector, ValueVector* relIDVector, - column_id_t columnID, ValueVector* propertyVector) { - KU_ASSERT(columnID < chunks.size()); - auto rowIdx = chunks[columnID]->append(propertyVector); +// IDVectors: srcNodeIDVector, relIDVector. +bool LocalRelNG::update(std::vector IDVectors, column_id_t columnID, + ValueVector* propertyVector) { + KU_ASSERT(IDVectors.size() == 2); + auto srcNodeIDVector = IDVectors[0]; + auto relIDVector = IDVectors[1]; + KU_ASSERT(srcNodeIDVector->state->selVector->selectedSize == 1 && + relIDVector->state->selVector->selectedSize == 1); auto srcNodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; + auto relIDPos = relIDVector->state->selVector->selectedPositions[0]; + if (srcNodeIDVector->isNull(srcNodeIDPos) || relIDVector->isNull(relIDPos)) { + return false; + } auto srcNodeOffset = srcNodeIDVector->getValue(srcNodeIDPos).offset - nodeGroupStartOffset; - KU_ASSERT(srcNodeOffset < StorageConstants::NODE_GROUP_SIZE); - auto relIDPos = relIDVector->state->selVector->selectedPositions[0]; + KU_ASSERT(srcNodeOffset < StorageConstants::NODE_GROUP_SIZE && columnID < updateChunks.size()); auto relOffset = relIDVector->getValue(relIDPos).offset; - relNGInfo->update(srcNodeOffset, relOffset, columnID, rowIdx); + // Check if the rel is newly inserted or in persistent storage. + if (insertChunks.hasOffset(relOffset)) { + insertChunks.update(relOffset, columnID, propertyVector); + } else { + updateChunks[columnID].append(srcNodeOffset, relOffset, {propertyVector}); + } + return true; } -bool LocalRelNG::delete_(ValueVector* srcNodeIDVector, ValueVector* relIDVector) { - auto srcNodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; - auto srcNodeOffset = - srcNodeIDVector->getValue(srcNodeIDPos).offset - nodeGroupStartOffset; - KU_ASSERT(srcNodeOffset < StorageConstants::NODE_GROUP_SIZE); +bool LocalRelNG::delete_(ValueVector* srcNodeVector, ValueVector* relIDVector) { + KU_ASSERT(srcNodeVector->state->selVector->selectedSize == 1 && + relIDVector->state->selVector->selectedSize == 1); + auto srcNodePos = srcNodeVector->state->selVector->selectedPositions[0]; auto relIDPos = relIDVector->state->selVector->selectedPositions[0]; + if (srcNodeVector->isNull(srcNodePos) || relIDVector->isNull(relIDPos)) { + return false; + } + auto srcNodeOffset = + srcNodeVector->getValue(srcNodePos).offset - nodeGroupStartOffset; auto relOffset = relIDVector->getValue(relIDPos).offset; - return relNGInfo->delete_(srcNodeOffset, relOffset); -} - -bool LocalRelTableData::insert(ValueVector* srcNodeIDVector, ValueVector* dstNodeIDVector, - const std::vector& propertyVectors) { - KU_ASSERT(srcNodeIDVector->state->selVector->selectedSize == 1 && - dstNodeIDVector->state->selVector->selectedSize == 1); - auto srcNodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; - auto dstNodeIDPos = dstNodeIDVector->state->selVector->selectedPositions[0]; - if (srcNodeIDVector->isNull(srcNodeIDPos) || dstNodeIDVector->isNull(dstNodeIDPos)) { + // If the rel is newly inserted, remove the rel from insertChunks. + if (insertChunks.hasOffset(relOffset)) { + insertChunks.remove(srcNodeOffset, relOffset); + return true; + } + // If the rel is updated, remove the rel from updateChunks if exists. + for (auto i = 0u; i < updateChunks.size(); i++) { + if (updateChunks[i].hasOffset(relOffset)) { + updateChunks[i].remove(srcNodeOffset, relOffset); + } + } + if (!deleteInfo.deleteOffset(relOffset)) { return false; } - auto localNodeGroup = - ku_dynamic_cast(getOrCreateLocalNodeGroup(srcNodeIDVector)); - return localNodeGroup->insert(srcNodeIDVector, dstNodeIDVector, propertyVectors); + deleteInfo.deleteRelAux(srcNodeOffset, relOffset); + return true; } -void LocalRelTableData::update(ValueVector* srcNodeIDVector, ValueVector* relIDVector, - column_id_t columnID, ValueVector* propertyVector) { - KU_ASSERT(srcNodeIDVector->state->selVector->selectedSize == 1 && - relIDVector->state->selVector->selectedSize == 1); - auto srcNodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; - auto relIDPos = relIDVector->state->selVector->selectedPositions[0]; - if (srcNodeIDVector->isNull(srcNodeIDPos) || relIDVector->isNull(relIDPos)) { - return; +offset_t LocalRelNG::getNumInsertedRels(offset_t srcOffset) const { + if (!insertChunks.hasRelOffsetsFromSrcOffset(srcOffset)) { + return 0; } - auto localNodeGroup = - ku_dynamic_cast(getOrCreateLocalNodeGroup(srcNodeIDVector)); - localNodeGroup->update(srcNodeIDVector, relIDVector, columnID, propertyVector); + return insertChunks.getNumRelsFromSrcOffset(srcOffset); } -bool LocalRelTableData::delete_( - ValueVector* srcNodeIDVector, ValueVector* dstNodeIDVector, ValueVector* relIDVector) { - KU_ASSERT(srcNodeIDVector->state->selVector->selectedSize == 1 && - dstNodeIDVector->state->selVector->selectedSize == 1 && - relIDVector->state->selVector->selectedSize == 1); - auto srcNodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; - auto dstNodeIDPos = dstNodeIDVector->state->selVector->selectedPositions[0]; - if (srcNodeIDVector->isNull(srcNodeIDPos) || dstNodeIDVector->isNull(dstNodeIDPos)) { - return false; +void LocalRelNG::getChangesPerCSRSegment(std::vector& sizeChangesPerSegment, + std::vector& hasChangesPerSegment) { + auto numSegments = StorageConstants::NODE_GROUP_SIZE / StorageConstants::CSR_SEGMENT_SIZE; + sizeChangesPerSegment.resize(numSegments, 0 /*initValue*/); + hasChangesPerSegment.resize(numSegments, false /*initValue*/); + for (auto& [srcOffset, insertions] : insertChunks.getSrcNodeOffsetToRelOffsets()) { + auto segmentIdx = getSegmentIdx(srcOffset); + sizeChangesPerSegment[segmentIdx] += insertions.size(); + hasChangesPerSegment[segmentIdx] = true; + } + for (auto& [srcOffset, deletions] : deleteInfo.getSrcNodeOffsetToRelOffsetVec()) { + auto segmentIdx = getSegmentIdx(srcOffset); + sizeChangesPerSegment[segmentIdx] -= deletions.size(); + hasChangesPerSegment[segmentIdx] = true; + } + for (auto& updateChunk : updateChunks) { + for (auto& [srcOffset, _] : updateChunk.getSrcNodeOffsetToRelOffsets()) { + auto segmentIdx = getSegmentIdx(srcOffset); + hasChangesPerSegment[segmentIdx] = true; + } } - auto localNodeGroup = - ku_dynamic_cast(getOrCreateLocalNodeGroup(srcNodeIDVector)); - return localNodeGroup->delete_(srcNodeIDVector, relIDVector); } LocalNodeGroup* LocalRelTableData::getOrCreateLocalNodeGroup(ValueVector* nodeIDVector) { @@ -285,11 +200,74 @@ LocalNodeGroup* LocalRelTableData::getOrCreateLocalNodeGroup(ValueVector* nodeID auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(nodeOffset); if (!nodeGroups.contains(nodeGroupIdx)) { auto nodeGroupStartOffset = StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); - nodeGroups[nodeGroupIdx] = - std::make_unique(nodeGroupStartOffset, dataTypes, mm, multiplicity); + nodeGroups[nodeGroupIdx] = std::make_unique(nodeGroupStartOffset, dataTypes); } return nodeGroups.at(nodeGroupIdx).get(); } +LocalRelTable::LocalRelTable(Table& table) : LocalTable{table} { + auto& relTable = ku_dynamic_cast(table); + std::vector types; + types.reserve(relTable.getNumColumns()); + for (auto i = 0u; i < relTable.getNumColumns(); i++) { + types.push_back(relTable.getColumn(i, RelDataDirection::FWD)->getDataType()); + } + // FWD and BWD local rel table data. + localTableDataCollection.push_back(std::make_unique(types)); + localTableDataCollection.push_back(std::make_unique(types)); +} + +bool LocalRelTable::insert(TableInsertState& state) { + auto& insertState = ku_dynamic_cast(state); + auto fwdIDVectors = + std::vector{const_cast(&insertState.srcNodeIDVector), + const_cast(&insertState.dstNodeIDVector)}; + auto bwdIDVectors = + std::vector{const_cast(&insertState.dstNodeIDVector), + const_cast(&insertState.srcNodeIDVector)}; + auto fwdInserted = + getTableData(RelDataDirection::FWD)->insert(fwdIDVectors, insertState.propertyVectors); + auto bwdInserted = + getTableData(RelDataDirection::BWD)->insert(bwdIDVectors, insertState.propertyVectors); + KU_ASSERT(fwdInserted == bwdInserted); + return fwdInserted && bwdInserted; +} + +bool LocalRelTable::update(TableUpdateState& updateState) { + auto& state = ku_dynamic_cast(updateState); + auto fwdIDVectors = std::vector{const_cast(&state.srcNodeIDVector), + const_cast(&state.relIDVector)}; + auto bwdIDVectors = std::vector{const_cast(&state.dstNodeIDVector), + const_cast(&state.relIDVector)}; + auto fwdUpdated = + getTableData(RelDataDirection::FWD) + ->update(fwdIDVectors, state.columnID, const_cast(&state.propertyVector)); + auto bwdUpdated = + getTableData(RelDataDirection::BWD) + ->update(bwdIDVectors, state.columnID, const_cast(&state.propertyVector)); + KU_ASSERT(fwdUpdated == bwdUpdated); + return fwdUpdated && bwdUpdated; +} + +bool LocalRelTable::delete_(TableDeleteState& deleteState) { + auto& state = ku_dynamic_cast(deleteState); + auto fwdDeleted = getTableData(RelDataDirection::FWD) + ->delete_(const_cast(&state.srcNodeIDVector), + const_cast(&state.relIDVector)); + auto bwdDeleted = getTableData(RelDataDirection::BWD) + ->delete_(const_cast(&state.dstNodeIDVector), + const_cast(&state.relIDVector)); + KU_ASSERT(fwdDeleted == bwdDeleted); + return fwdDeleted && bwdDeleted; +} + +void LocalRelTable::scan(TableReadState&) { + KU_UNREACHABLE; +} + +void LocalRelTable::lookup(TableReadState&) { + KU_UNREACHABLE; +} + } // namespace storage } // namespace kuzu diff --git a/src/storage/local_storage/local_storage.cpp b/src/storage/local_storage/local_storage.cpp index 1b06bd581dd..788298050fb 100644 --- a/src/storage/local_storage/local_storage.cpp +++ b/src/storage/local_storage/local_storage.cpp @@ -1,7 +1,10 @@ #include "storage/local_storage/local_storage.h" +#include "storage/local_storage/local_node_table.h" +#include "storage/local_storage/local_rel_table.h" #include "storage/local_storage/local_table.h" -#include "storage/store/column.h" +#include "storage/storage_manager.h" +#include "storage/store/table.h" using namespace kuzu::common; using namespace kuzu::transaction; @@ -9,37 +12,44 @@ using namespace kuzu::transaction; namespace kuzu { namespace storage { -LocalStorage::LocalStorage(MemoryManager* mm) : mm{mm} {} - -LocalTableData* LocalStorage::getOrCreateLocalTableData(common::table_id_t tableID, - const std::vector>& columns, TableType tableType, - common::vector_idx_t dataIdx, RelMultiplicity multiplicity) { - if (!tables.contains(tableID)) { - tables[tableID] = std::make_unique(tableType); - } - return tables.at(tableID)->getOrCreateLocalTableData(columns, mm, dataIdx, multiplicity); -} - -LocalTable* LocalStorage::getLocalTable(table_id_t tableID) { +LocalTable* LocalStorage::getLocalTable(table_id_t tableID, NotExistAction action) { if (!tables.contains(tableID)) { - return nullptr; + switch (action) { + case NotExistAction::CREATE: { + auto table = clientContext.getStorageManager()->getTable(tableID); + switch (table->getTableType()) { + case TableType::NODE: { + tables[tableID] = std::make_unique(*table); + } break; + case TableType::REL: { + tables[tableID] = std::make_unique(*table); + } break; + default: + KU_UNREACHABLE; + } + } break; + case NotExistAction::RETURN_NULL: { + return nullptr; + } + default: + KU_UNREACHABLE; + } } return tables.at(tableID).get(); } -LocalTableData* LocalStorage::getLocalTableData(table_id_t tableID, vector_idx_t dataIdx) { - if (!tables.contains(tableID)) { - return nullptr; +void LocalStorage::prepareCommit() { + for (auto& [tableID, localTable] : tables) { + auto table = clientContext.getStorageManager()->getTable(tableID); + table->prepareCommit(clientContext.getTx(), localTable.get()); } - return tables.at(tableID)->getLocalTableData(dataIdx); } -std::unordered_set LocalStorage::getTableIDsWithUpdates() { - std::unordered_set tableSetToUpdate; - for (auto& [tableID, _] : tables) { - tableSetToUpdate.insert(tableID); +void LocalStorage::prepareRollback() { + for (auto& [tableID, localTable] : tables) { + auto table = clientContext.getStorageManager()->getTable(tableID); + table->prepareRollback(localTable.get()); } - return tableSetToUpdate; } } // namespace storage diff --git a/src/storage/local_storage/local_table.cpp b/src/storage/local_storage/local_table.cpp index 1310e2904d7..7a63d825dde 100644 --- a/src/storage/local_storage/local_table.cpp +++ b/src/storage/local_storage/local_table.cpp @@ -1,116 +1,125 @@ #include "storage/local_storage/local_table.h" -#include "storage/local_storage/local_node_table.h" -#include "storage/local_storage/local_rel_table.h" -#include "storage/store/column.h" - using namespace kuzu::common; namespace kuzu { namespace storage { -void LocalVector::read( - sel_t offsetInLocalVector, ValueVector* resultVector, sel_t offsetInResultVector) { - resultVector->copyFromVectorData(offsetInResultVector, vector.get(), offsetInLocalVector); +LocalNodeGroup::LocalNodeGroup(offset_t nodeGroupStartOffset, + const std::vector& dataTypes) + : nodeGroupStartOffset{nodeGroupStartOffset}, insertChunks{LogicalType::copy(dataTypes)} { + updateChunks.reserve(dataTypes.size()); + for (auto i = 0u; i < dataTypes.size(); i++) { + std::vector chunkCollectionTypes; + chunkCollectionTypes.push_back(*dataTypes[i].copy()); + LocalChunkedGroupCollection localDataChunkCollection(std::move(chunkCollectionTypes)); + updateChunks.push_back(std::move(localDataChunkCollection)); + } } -void LocalVector::append(ValueVector* valueVector) { - KU_ASSERT(valueVector->state->selVector->selectedSize == 1); - auto pos = valueVector->state->selVector->selectedPositions[0]; - vector->copyFromVectorData(numValues, valueVector, pos); - numValues++; +bool LocalNodeGroup::hasUpdatesOrDeletions() const { + if (!deleteInfo.isEmpty()) { + return true; + } + for (auto& updateChunk : updateChunks) { + if (!updateChunk.isEmpty()) { + return true; + } + } + return false; } -void LocalVectorCollection::read( - row_idx_t rowIdx, ValueVector* outputVector, sel_t posInOutputVector) { - auto vectorIdx = rowIdx >> DEFAULT_VECTOR_CAPACITY_LOG_2; - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - KU_ASSERT(vectorIdx < vectors.size()); - vectors[vectorIdx]->read(offsetInVector, outputVector, posInOutputVector); +void LocalChunkedGroupCollection::appendChunkedGroup(ColumnChunk* srcOffsetChunk, + std::unique_ptr chunkedGroup) { + KU_ASSERT(chunkedGroup->getNumColumns() == dataTypes.size()); + for (auto i = 0u; i < chunkedGroup->getNumColumns(); i++) { + KU_ASSERT(chunkedGroup->getColumnChunk(i).getDataType() == dataTypes[i]); + } + auto rowIdx = chunkedGroups.getNumChunkedGroups() * ChunkedNodeGroupCollection::CHUNK_CAPACITY; + auto& relOffsetChunk = chunkedGroup->getColumnChunk(REL_ID_COLUMN_ID); + for (auto i = 0u; i < srcOffsetChunk->getNumValues(); i++) { + auto relOffset = relOffsetChunk.getValue(i); + KU_ASSERT(!offsetToRowIdx.contains(relOffset)); + offsetToRowIdx[relOffset] = rowIdx++; + auto srcOffset = srcOffsetChunk->getValue(i); + srcNodeOffsetToRelOffsets[srcOffset].push_back(relOffset); + } + chunkedGroups.merge(std::move(chunkedGroup)); } -row_idx_t LocalVectorCollection::append(ValueVector* vector) { - prepareAppend(); - auto lastVector = vectors.back().get(); - KU_ASSERT(!lastVector->isFull()); - lastVector->append(vector); - return numRows++; +void LocalChunkedGroupCollection::readValueAtRowIdx(row_idx_t rowIdx, column_id_t columnID, + ValueVector* outputVector, sel_t posInOutputVector) const { + auto [chunkIdx, offsetInChunk] = getChunkIdxAndOffsetInChunk(rowIdx); + auto& chunk = chunkedGroups.getChunkedGroup(chunkIdx)->getColumnChunk(columnID); + chunk.lookup(offsetInChunk, *outputVector, posInOutputVector); } -void LocalVectorCollection::prepareAppend() { - if (vectors.empty()) { - vectors.emplace_back(std::make_unique(*dataType, mm)); - } - auto lastVector = vectors.back().get(); - if (lastVector->isFull()) { - vectors.emplace_back(std::make_unique(*dataType, mm)); +bool LocalChunkedGroupCollection::read(offset_t offset, column_id_t columnID, + ValueVector* outputVector, sel_t posInOutputVector) { + if (!offsetToRowIdx.contains(offset)) { + return false; } + auto rowIdx = offsetToRowIdx.at(offset); + readValueAtRowIdx(rowIdx, columnID, outputVector, posInOutputVector); + return true; } -std::unique_ptr LocalVectorCollection::getStructChildVectorCollection( - common::struct_field_idx_t idx) { - auto childCollection = std::make_unique( - StructType::getField(dataType.get(), idx)->getType()->copy(), mm); - - for (auto i = 0u; i < numRows; i++) { - auto fieldVector = - common::StructVector::getFieldVector(getLocalVector(i)->getVector(), idx); - fieldVector->state->selVector->selectedPositions[0] = i & (DEFAULT_VECTOR_CAPACITY - 1); - childCollection->append(fieldVector.get()); - } - return childCollection; +void LocalChunkedGroupCollection::update(offset_t offset, column_id_t columnID, + ValueVector* propertyVector) { + KU_ASSERT(offsetToRowIdx.contains(offset)); + auto rowIdx = offsetToRowIdx.at(offset); + auto [chunkIdx, offsetInChunk] = getChunkIdxAndOffsetInChunk(rowIdx); + auto& chunk = chunkedGroups.getChunkedGroupUnsafe(chunkIdx)->getColumnChunkUnsafe(columnID); + auto pos = propertyVector->state->selVector->selectedPositions[0]; + chunk.write(propertyVector, pos, offsetInChunk); } -LocalNodeGroup::LocalNodeGroup( - offset_t nodeGroupStartOffset, std::vector dataTypes, MemoryManager* mm) - : nodeGroupStartOffset{nodeGroupStartOffset} { - chunks.resize(dataTypes.size()); - for (auto i = 0u; i < dataTypes.size(); ++i) { - // To avoid unnecessary memory consumption, we chunk local changes of each column in the - // node group into chunks of size DEFAULT_VECTOR_CAPACITY. - chunks[i] = std::make_unique(dataTypes[i]->copy(), mm); +void LocalChunkedGroupCollection::remove(offset_t srcNodeOffset, offset_t relOffset) { + KU_ASSERT(srcNodeOffsetToRelOffsets.contains(srcNodeOffset)); + remove(relOffset); + offsetToRowIdx.erase(relOffset); + auto& vec = srcNodeOffsetToRelOffsets.at(srcNodeOffset); + vec.erase(std::remove(vec.begin(), vec.end(), relOffset), vec.end()); + if (vec.empty()) { + srcNodeOffsetToRelOffsets.erase(srcNodeOffset); } } -LocalTableData* LocalTable::getOrCreateLocalTableData( - const std::vector>& columns, MemoryManager* mm, vector_idx_t dataIdx, - RelMultiplicity multiplicity) { - if (localTableDataCollection.empty()) { - std::vector dataTypes; - dataTypes.reserve(columns.size()); - for (auto& column : columns) { - dataTypes.push_back(&column->getDataType()); - } - switch (tableType) { - case TableType::NODE: { - localTableDataCollection.reserve(1); - localTableDataCollection.push_back( - std::make_unique(std::move(dataTypes), mm)); - } break; - case TableType::REL: { - KU_ASSERT(dataIdx < 2); - localTableDataCollection.resize(2); - localTableDataCollection[dataIdx] = - std::make_unique(multiplicity, std::move(dataTypes), mm); - } break; - default: { - KU_UNREACHABLE; - } - } +row_idx_t LocalChunkedGroupCollection::append(std::vector vectors) { + KU_ASSERT(vectors.size() == dataTypes.size()); + if (chunkedGroups.getNumChunkedGroups() == 0 || + chunkedGroups.getChunkedGroup(chunkedGroups.getNumChunkedGroups() - 1)->getNumRows() == + ChunkedNodeGroupCollection::CHUNK_CAPACITY) { + chunkedGroups.merge(std::make_unique(dataTypes, + false /*enableCompression*/, ChunkedNodeGroupCollection::CHUNK_CAPACITY)); } - KU_ASSERT(dataIdx < localTableDataCollection.size()); - if (!localTableDataCollection[dataIdx]) { - KU_ASSERT(tableType == TableType::REL); - std::vector dataTypes; - dataTypes.reserve(columns.size()); - for (auto& column : columns) { - dataTypes.push_back(&column->getDataType()); - } - localTableDataCollection[dataIdx] = - std::make_unique(multiplicity, std::move(dataTypes), mm); + auto lastChunkGroup = + chunkedGroups.getChunkedGroupUnsafe(chunkedGroups.getNumChunkedGroups() - 1); + for (auto i = 0u; i < vectors.size(); i++) { + KU_ASSERT(vectors[i]->state->selVector->selectedSize == 1); + lastChunkGroup->getColumnChunkUnsafe(i).append(vectors[i], *vectors[i]->state->selVector); } - KU_ASSERT(localTableDataCollection[dataIdx] != nullptr); - return localTableDataCollection[dataIdx].get(); + lastChunkGroup->setNumRows(lastChunkGroup->getNumRows() + 1); + return numRows++; +} + +bool LocalTableData::insert(std::vector nodeIDVectors, + std::vector propertyVectors) { + KU_ASSERT(nodeIDVectors.size() >= 1); + auto localNodeGroup = getOrCreateLocalNodeGroup(nodeIDVectors[0]); + return localNodeGroup->insert(nodeIDVectors, propertyVectors); +} + +bool LocalTableData::update(std::vector nodeIDVectors, column_id_t columnID, + ValueVector* propertyVector) { + KU_ASSERT(nodeIDVectors.size() >= 1); + auto localNodeGroup = getOrCreateLocalNodeGroup(nodeIDVectors[0]); + return localNodeGroup->update(nodeIDVectors, columnID, propertyVector); +} + +bool LocalTableData::delete_(ValueVector* nodeIDVector, ValueVector* extraVector) { + auto localNodeGroup = getOrCreateLocalNodeGroup(nodeIDVector); + return localNodeGroup->delete_(nodeIDVector, extraVector); } } // namespace storage diff --git a/src/storage/stats/node_table_statistics.cpp b/src/storage/stats/node_table_statistics.cpp index 07f01751c27..ba3f5c8ad26 100644 --- a/src/storage/stats/node_table_statistics.cpp +++ b/src/storage/stats/node_table_statistics.cpp @@ -17,13 +17,13 @@ NodeTableStatsAndDeletedIDs::NodeTableStatsAndDeletedIDs(BMFileHandle* metadataF metadataDAHInfos.clear(); metadataDAHInfos.reserve(entry.getNumProperties()); for (auto& property : entry.getPropertiesRef()) { - metadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( - *property.getDataType(), *metadataFH, bufferManager, wal)); + metadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo(*property.getDataType(), + *metadataFH, bufferManager, wal)); } } -NodeTableStatsAndDeletedIDs::NodeTableStatsAndDeletedIDs( - table_id_t tableID, offset_t maxNodeOffset, const std::vector& deletedNodeOffsets) +NodeTableStatsAndDeletedIDs::NodeTableStatsAndDeletedIDs(table_id_t tableID, offset_t maxNodeOffset, + const std::vector& deletedNodeOffsets) : NodeTableStatsAndDeletedIDs{tableID, maxNodeOffset, deletedNodeOffsets, {}} {} NodeTableStatsAndDeletedIDs::NodeTableStatsAndDeletedIDs(const NodeTableStatsAndDeletedIDs& other) @@ -104,33 +104,32 @@ void NodeTableStatsAndDeletedIDs::deleteNode(offset_t nodeOffset) { // Note: this function will always be called right after scanNodeID, so we have the guarantee // that the nodeOffsetVector is always unselected. -void NodeTableStatsAndDeletedIDs::setDeletedNodeOffsetsForMorsel( - const std::shared_ptr& nodeOffsetVector) { - auto morselIdxAndOffset = StorageUtils::getQuotientRemainder( - nodeOffsetVector->readNodeOffset(0), DEFAULT_VECTOR_CAPACITY); - if (hasDeletedNodesPerMorsel[morselIdxAndOffset.first]) { - auto deletedNodeOffsets = deletedNodeOffsetsPerMorsel[morselIdxAndOffset.first]; - uint64_t morselBeginOffset = morselIdxAndOffset.first * DEFAULT_VECTOR_CAPACITY; - nodeOffsetVector->state->selVector->resetSelectorToValuePosBuffer(); +void NodeTableStatsAndDeletedIDs::setDeletedNodeOffsetsForMorsel(ValueVector* nodeIDVector) const { + auto [morselIdx, _] = StorageUtils::getQuotientRemainder(nodeIDVector->readNodeOffset(0), + DEFAULT_VECTOR_CAPACITY); + if (hasDeletedNodesPerMorsel[morselIdx]) { + auto& deletedNodeOffsets = deletedNodeOffsetsPerMorsel.at(morselIdx); + uint64_t morselBeginOffset = morselIdx * DEFAULT_VECTOR_CAPACITY; + auto originalSize = nodeIDVector->state->getOriginalSize(); auto itr = deletedNodeOffsets.begin(); - sel_t nextDeletedNodeOffset = *itr - morselBeginOffset; - uint64_t nextSelectedPosition = 0; - for (auto pos = 0u; pos < nodeOffsetVector->state->getOriginalSize(); ++pos) { - if (pos == nextDeletedNodeOffset) { + common::sel_t numSelectedValue = 0; + auto selectedBuffer = nodeIDVector->state->selVector->getMultableBuffer(); + KU_ASSERT(nodeIDVector->state->selVector->isUnfiltered()); + for (auto pos = 0u; pos < nodeIDVector->state->getOriginalSize(); ++pos) { + if (itr == deletedNodeOffsets.end()) { // no more deleted offset to check. + selectedBuffer[numSelectedValue++] = pos; + continue; + } + if (pos + morselBeginOffset == *itr) { // node has been deleted. itr++; - if (itr == deletedNodeOffsets.end()) { - nextDeletedNodeOffset = UINT16_MAX; - // We do not break because we need to keep setting the positions after - // the last deletedNodeOffset. - continue; - } - nextDeletedNodeOffset = *itr - morselBeginOffset; continue; } - nodeOffsetVector->state->selVector->selectedPositions[nextSelectedPosition++] = pos; + selectedBuffer[numSelectedValue++] = pos; + } + if (numSelectedValue != originalSize) { + nodeIDVector->state->selVector->setToFiltered(); } - nodeOffsetVector->state->selVector->selectedSize = - nodeOffsetVector->state->getOriginalSize() - deletedNodeOffsets.size(); + nodeIDVector->state->selVector->selectedSize = numSelectedValue; } } diff --git a/src/storage/stats/nodes_store_statistics.cpp b/src/storage/stats/nodes_store_statistics.cpp index 1a96ad360f2..34b32acf287 100644 --- a/src/storage/stats/nodes_store_statistics.cpp +++ b/src/storage/stats/nodes_store_statistics.cpp @@ -1,36 +1,35 @@ #include "storage/stats/nodes_store_statistics.h" using namespace kuzu::common; +using namespace kuzu::transaction; namespace kuzu { namespace storage { -offset_t NodesStoreStatsAndDeletedIDs::getMaxNodeOffset( - transaction::Transaction* transaction, table_id_t tableID) { +offset_t NodesStoreStatsAndDeletedIDs::getMaxNodeOffset(transaction::Transaction* transaction, + table_id_t tableID) { KU_ASSERT(transaction); if (transaction->getType() == transaction::TransactionType::READ_ONLY) { - return getNodeStatisticsAndDeletedIDs(tableID)->getMaxNodeOffset(); + return getNodeStatisticsAndDeletedIDs(transaction, tableID)->getMaxNodeOffset(); } else { std::unique_lock xLck{mtx}; return readWriteVersion == nullptr ? - getNodeStatisticsAndDeletedIDs(tableID)->getMaxNodeOffset() : + getNodeStatisticsAndDeletedIDs(transaction, tableID)->getMaxNodeOffset() : getNodeTableStats(transaction::TransactionType::WRITE, tableID) ->getMaxNodeOffset(); } } -std::map NodesStoreStatsAndDeletedIDs::getMaxNodeOffsetPerTable() const { - std::map retVal; - for (auto& tableIDStatistics : readOnlyVersion->tableStatisticPerTable) { - retVal[tableIDStatistics.first] = - getNodeStatisticsAndDeletedIDs(tableIDStatistics.first)->getMaxNodeOffset(); - } - return retVal; +void NodesStoreStatsAndDeletedIDs::updateNumTuplesByValue(table_id_t tableID, int64_t value) { + initTableStatisticsForWriteTrx(); + KU_ASSERT(readWriteVersion && readWriteVersion->tableStatisticPerTable.contains(tableID)); + setToUpdated(); + auto tableStats = getNodeTableStats(transaction::TransactionType::WRITE, tableID); + tableStats->setNumTuples(tableStats->getNumTuples() + value); } -void NodesStoreStatsAndDeletedIDs::setDeletedNodeOffsetsForMorsel( - transaction::Transaction* transaction, const std::shared_ptr& nodeOffsetVector, - table_id_t tableID) { +void NodesStoreStatsAndDeletedIDs::setDeletedNodeOffsetsForMorsel(transaction::Transaction* tx, + ValueVector* nodeIDVector, table_id_t tableID) { // NOTE: We can remove the lock under the following assumptions, that should currently hold: // 1) During the phases when nodeStatisticsAndDeletedIDsPerTableForReadOnlyTrx change, which // is during checkpointing, this function, which is called during scans, cannot be called. @@ -40,10 +39,16 @@ void NodesStoreStatsAndDeletedIDs::setDeletedNodeOffsetsForMorsel( // query where scans/reads happen in a write transaction cannot run concurrently with the // pipeline that performs an add/delete node. lock_t lck{mtx}; - (transaction->isReadOnly() || readWriteVersion == nullptr) ? - getNodeStatisticsAndDeletedIDs(tableID)->setDeletedNodeOffsetsForMorsel(nodeOffsetVector) : - ((NodeTableStatsAndDeletedIDs*)readWriteVersion->tableStatisticPerTable[tableID].get()) - ->setDeletedNodeOffsetsForMorsel(nodeOffsetVector); + const TablesStatisticsContent* content; + if (tx->isReadOnly() || readWriteVersion == nullptr) { + content = getVersion(TransactionType::READ_ONLY); + } else { + content = getVersion(TransactionType::WRITE); + } + auto tableStat = content->getTableStat(tableID); + auto nodeStat = + ku_dynamic_cast(tableStat); + nodeStat->setDeletedNodeOffsetsForMorsel(nodeIDVector); } void NodesStoreStatsAndDeletedIDs::addNodeStatisticsAndDeletedIDs( @@ -55,8 +60,8 @@ void NodesStoreStatsAndDeletedIDs::addNodeStatisticsAndDeletedIDs( constructTableStatistic(nodeTableEntry); } -void NodesStoreStatsAndDeletedIDs::addMetadataDAHInfo( - table_id_t tableID, const LogicalType& dataType) { +void NodesStoreStatsAndDeletedIDs::addMetadataDAHInfo(table_id_t tableID, + const LogicalType& dataType) { initTableStatisticsForWriteTrx(); KU_ASSERT(readWriteVersion); setToUpdated(); diff --git a/src/storage/stats/property_statistics.cpp b/src/storage/stats/property_statistics.cpp index 23c59ed0da3..3bdeb096e3e 100644 --- a/src/storage/stats/property_statistics.cpp +++ b/src/storage/stats/property_statistics.cpp @@ -26,8 +26,8 @@ std::unique_ptr PropertyStatistics::deserialize( // overwrite them and invalidate the reference bool RWPropertyStats::mayHaveNull(const transaction::Transaction& transaction) { // Columns internal to the storage, i.e., not mapping to a property in table schema, are not - // tracked in statistics. For example, offset of var list column, csr offset column, etc. - // TODO(Guodong): INVALID_PROPERTY_ID is used here because we have a column, i.e., adjColumn, + // tracked in statistics. For example, offset of list column, csr offset column, etc. + // TODO(Guodong): INVALID_PROPERTY_ID is used here because we have a column, i.e., nbrIDColumn, // not exposed as property in table schema, but still have nullColumn. Should be fixed once we // properly align properties and chunks. if (propertyID == common::INVALID_PROPERTY_ID) { @@ -40,7 +40,7 @@ bool RWPropertyStats::mayHaveNull(const transaction::Transaction& transaction) { } void RWPropertyStats::setHasNull(const transaction::Transaction& transaction) { - // TODO(Guodong): INVALID_PROPERTY_ID is used here because we have a column, i.e., adjColumn, + // TODO(Guodong): INVALID_PROPERTY_ID is used here because we have a column, i.e., nbrIDColumn, // not exposed as property in table schema, but still have nullColumn. Should be fixed once we // properly align properties and chunks. if (propertyID != common::INVALID_PROPERTY_ID) { diff --git a/src/storage/stats/rel_table_statistics.cpp b/src/storage/stats/rel_table_statistics.cpp index bc85da64365..f52197367b8 100644 --- a/src/storage/stats/rel_table_statistics.cpp +++ b/src/storage/stats/rel_table_statistics.cpp @@ -22,18 +22,17 @@ RelTableStats::RelTableStats(BMFileHandle* metadataFH, const catalog::TableCatal LogicalType{LogicalTypeID::INT64}, *metadataFH, bufferManager, wal); bwdCSRLengthMetadataDAHInfo = TablesStatistics::createMetadataDAHInfo( LogicalType{LogicalTypeID::INT64}, *metadataFH, bufferManager, wal); - fwdAdjMetadataDAHInfo = TablesStatistics::createMetadataDAHInfo( - LogicalType{LogicalTypeID::INTERNAL_ID}, *metadataFH, bufferManager, wal); - bwdAdjMetadataDAHInfo = TablesStatistics::createMetadataDAHInfo( - LogicalType{LogicalTypeID::INTERNAL_ID}, *metadataFH, bufferManager, wal); - fwdPropertyMetadataDAHInfos.clear(); - bwdPropertyMetadataDAHInfos.clear(); - fwdPropertyMetadataDAHInfos.reserve(tableEntry.getNumProperties()); - bwdPropertyMetadataDAHInfos.reserve(tableEntry.getNumProperties()); + KU_ASSERT(fwdMetadataDAHInfos.empty() && bwdMetadataDAHInfos.empty()); + fwdMetadataDAHInfos.reserve(tableEntry.getNumProperties() + 1); + bwdMetadataDAHInfos.reserve(tableEntry.getNumProperties() + 1); + fwdMetadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( + LogicalType{LogicalTypeID::INTERNAL_ID}, *metadataFH, bufferManager, wal)); + bwdMetadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( + LogicalType{LogicalTypeID::INTERNAL_ID}, *metadataFH, bufferManager, wal)); for (auto& property : tableEntry.getPropertiesRef()) { - fwdPropertyMetadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( + fwdMetadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( *property.getDataType(), *metadataFH, bufferManager, wal)); - bwdPropertyMetadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( + bwdMetadataDAHInfos.push_back(TablesStatistics::createMetadataDAHInfo( *property.getDataType(), *metadataFH, bufferManager, wal)); } } @@ -48,17 +47,15 @@ RelTableStats::RelTableStats(const RelTableStats& other) : TableStatistics{other bwdCSROffsetMetadataDAHInfo = other.bwdCSROffsetMetadataDAHInfo->copy(); bwdCSRLengthMetadataDAHInfo = other.bwdCSRLengthMetadataDAHInfo->copy(); } - fwdAdjMetadataDAHInfo = other.fwdAdjMetadataDAHInfo->copy(); - bwdAdjMetadataDAHInfo = other.bwdAdjMetadataDAHInfo->copy(); - fwdPropertyMetadataDAHInfos.clear(); - fwdPropertyMetadataDAHInfos.reserve(other.fwdPropertyMetadataDAHInfos.size()); - for (auto& metadataDAHInfo : other.fwdPropertyMetadataDAHInfos) { - fwdPropertyMetadataDAHInfos.push_back(metadataDAHInfo->copy()); + fwdMetadataDAHInfos.clear(); + fwdMetadataDAHInfos.reserve(other.fwdMetadataDAHInfos.size()); + for (auto& metadataDAHInfo : other.fwdMetadataDAHInfos) { + fwdMetadataDAHInfos.push_back(metadataDAHInfo->copy()); } - bwdPropertyMetadataDAHInfos.clear(); - bwdPropertyMetadataDAHInfos.reserve(other.bwdPropertyMetadataDAHInfos.size()); - for (auto& metadataDAHInfo : other.bwdPropertyMetadataDAHInfos) { - bwdPropertyMetadataDAHInfos.push_back(metadataDAHInfo->copy()); + bwdMetadataDAHInfos.clear(); + bwdMetadataDAHInfos.reserve(other.bwdMetadataDAHInfos.size()); + for (auto& metadataDAHInfo : other.bwdMetadataDAHInfos) { + bwdMetadataDAHInfos.push_back(metadataDAHInfo->copy()); } } @@ -68,14 +65,12 @@ void RelTableStats::serializeInternal(Serializer& serializer) { serializer.serializeOptionalValue(bwdCSROffsetMetadataDAHInfo); serializer.serializeOptionalValue(fwdCSRLengthMetadataDAHInfo); serializer.serializeOptionalValue(bwdCSRLengthMetadataDAHInfo); - fwdAdjMetadataDAHInfo->serialize(serializer); - bwdAdjMetadataDAHInfo->serialize(serializer); - serializer.serializeVectorOfPtrs(fwdPropertyMetadataDAHInfos); - serializer.serializeVectorOfPtrs(bwdPropertyMetadataDAHInfos); + serializer.serializeVectorOfPtrs(fwdMetadataDAHInfos); + serializer.serializeVectorOfPtrs(bwdMetadataDAHInfos); } -std::unique_ptr RelTableStats::deserialize( - uint64_t numRels, table_id_t tableID, Deserializer& deserializer) { +std::unique_ptr RelTableStats::deserialize(uint64_t numRels, table_id_t tableID, + Deserializer& deserializer) { offset_t nextRelOffset; deserializer.deserializeValue(nextRelOffset); std::unique_ptr fwdCSROffsetMetadataDAHInfo, bwdCSROffsetMetadataDAHInfo, @@ -84,8 +79,6 @@ std::unique_ptr RelTableStats::deserialize( deserializer.deserializeOptionalValue(bwdCSROffsetMetadataDAHInfo); deserializer.deserializeOptionalValue(fwdCSRLengthMetadataDAHInfo); deserializer.deserializeOptionalValue(bwdCSRLengthMetadataDAHInfo); - auto fwdNbrIDMetadataDAHInfo = MetadataDAHInfo::deserialize(deserializer); - auto bwdNbrIDMetadataDAHInfo = MetadataDAHInfo::deserialize(deserializer); std::vector> fwdPropertyMetadataDAHInfos; std::vector> bwdPropertyMetadataDAHInfos; deserializer.deserializeVectorOfPtrs(fwdPropertyMetadataDAHInfos); @@ -95,10 +88,8 @@ std::unique_ptr RelTableStats::deserialize( result->bwdCSROffsetMetadataDAHInfo = std::move(bwdCSROffsetMetadataDAHInfo); result->fwdCSRLengthMetadataDAHInfo = std::move(fwdCSRLengthMetadataDAHInfo); result->bwdCSRLengthMetadataDAHInfo = std::move(bwdCSRLengthMetadataDAHInfo); - result->fwdAdjMetadataDAHInfo = std::move(fwdNbrIDMetadataDAHInfo); - result->bwdAdjMetadataDAHInfo = std::move(bwdNbrIDMetadataDAHInfo); - result->fwdPropertyMetadataDAHInfos = std::move(fwdPropertyMetadataDAHInfos); - result->bwdPropertyMetadataDAHInfos = std::move(bwdPropertyMetadataDAHInfos); + result->fwdMetadataDAHInfos = std::move(fwdPropertyMetadataDAHInfos); + result->bwdMetadataDAHInfos = std::move(bwdPropertyMetadataDAHInfos); return result; } diff --git a/src/storage/stats/rels_store_statistics.cpp b/src/storage/stats/rels_store_statistics.cpp index 26d17385593..03e4e4ffcf7 100644 --- a/src/storage/stats/rels_store_statistics.cpp +++ b/src/storage/stats/rels_store_statistics.cpp @@ -10,41 +10,29 @@ using namespace kuzu::transaction; namespace kuzu { namespace storage { -RelsStoreStats::RelsStoreStats( - BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, VirtualFileSystem* vfs) +RelsStoreStats::RelsStoreStats(BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, + VirtualFileSystem* vfs) : TablesStatistics{metadataFH, bufferManager, wal, vfs} { readFromFile(); } -// We should only call this function after we call setNumRelsPerDirectionBoundTableID. -void RelsStoreStats::setNumTuplesForTable(table_id_t relTableID, uint64_t numRels) { - std::unique_lock lck{mtx}; - initTableStatisticsForWriteTrxNoLock(); - KU_ASSERT(readWriteVersion && readWriteVersion->tableStatisticPerTable.contains(relTableID)); - setToUpdated(); - auto relStatistics = (RelTableStats*)readWriteVersion->tableStatisticPerTable[relTableID].get(); - increaseNextRelOffset(relTableID, numRels - relStatistics->getNumTuples()); - relStatistics->setNumTuples(numRels); -} - -void RelsStoreStats::updateNumRelsByValue(table_id_t relTableID, int64_t value) { +void RelsStoreStats::updateNumTuplesByValue(table_id_t relTableID, int64_t value) { std::unique_lock lck{mtx}; initTableStatisticsForWriteTrxNoLock(); KU_ASSERT(readWriteVersion && readWriteVersion->tableStatisticPerTable.contains(relTableID)); setToUpdated(); auto relStatistics = (RelTableStats*)readWriteVersion->tableStatisticPerTable[relTableID].get(); auto numRelsBeforeUpdate = relStatistics->getNumTuples(); + (void)numRelsBeforeUpdate; // Avoid unused variable warning. KU_ASSERT(!(numRelsBeforeUpdate == 0 && value < 0)); - auto numRelsAfterUpdate = relStatistics->getNumTuples() + value; - relStatistics->setNumTuples(numRelsAfterUpdate); + relStatistics->setNumTuples(numRelsBeforeUpdate + value); // Update the nextRelID only when we are inserting rels. if (value > 0) { increaseNextRelOffset(relTableID, value); } } -offset_t RelsStoreStats::getNextRelOffset( - transaction::Transaction* transaction, table_id_t tableID) { +offset_t RelsStoreStats::getNextRelOffset(Transaction* transaction, table_id_t tableID) { std::unique_lock lck{mtx}; auto& tableStatisticContent = (transaction->isReadOnly() || readWriteVersion == nullptr) ? readOnlyVersion : @@ -75,8 +63,8 @@ void RelsStoreStats::removeMetadataDAHInfo(table_id_t tableID, column_id_t colum tableStats->removeMetadataDAHInfoForColumn(columnID, RelDataDirection::BWD); } -MetadataDAHInfo* RelsStoreStats::getCSROffsetMetadataDAHInfo( - Transaction* transaction, table_id_t tableID, RelDataDirection direction) { +MetadataDAHInfo* RelsStoreStats::getCSROffsetMetadataDAHInfo(Transaction* transaction, + table_id_t tableID, RelDataDirection direction) { if (transaction->isWriteTransaction()) { initTableStatisticsForWriteTrx(); } @@ -84,8 +72,8 @@ MetadataDAHInfo* RelsStoreStats::getCSROffsetMetadataDAHInfo( return tableStats->getCSROffsetMetadataDAHInfo(direction); } -MetadataDAHInfo* RelsStoreStats::getCSRLengthMetadataDAHInfo( - Transaction* transaction, table_id_t tableID, RelDataDirection direction) { +MetadataDAHInfo* RelsStoreStats::getCSRLengthMetadataDAHInfo(Transaction* transaction, + table_id_t tableID, RelDataDirection direction) { if (transaction->isWriteTransaction()) { initTableStatisticsForWriteTrx(); } @@ -93,22 +81,13 @@ MetadataDAHInfo* RelsStoreStats::getCSRLengthMetadataDAHInfo( return tableStats->getCSRLengthMetadataDAHInfo(direction); } -MetadataDAHInfo* RelsStoreStats::getAdjMetadataDAHInfo( - Transaction* transaction, table_id_t tableID, RelDataDirection direction) { - if (transaction->isWriteTransaction()) { - initTableStatisticsForWriteTrx(); - } - auto tableStats = getRelStatistics(tableID, transaction); - return tableStats->getAdjMetadataDAHInfo(direction); -} - -MetadataDAHInfo* RelsStoreStats::getPropertyMetadataDAHInfo(transaction::Transaction* transaction, +MetadataDAHInfo* RelsStoreStats::getColumnMetadataDAHInfo(Transaction* transaction, table_id_t tableID, column_id_t columnID, RelDataDirection direction) { if (transaction->isWriteTransaction()) { initTableStatisticsForWriteTrx(); } auto relTableStats = getRelStatistics(tableID, transaction); - return relTableStats->getPropertyMetadataDAHInfo(columnID, direction); + return relTableStats->getColumnMetadataDAHInfo(columnID, direction); } } // namespace storage diff --git a/src/storage/stats/table_statistics.cpp b/src/storage/stats/table_statistics.cpp index 6acd94fe3b9..4fee186ce59 100644 --- a/src/storage/stats/table_statistics.cpp +++ b/src/storage/stats/table_statistics.cpp @@ -22,8 +22,8 @@ TableStatistics::TableStatistics(common::TableType tableType, uint64_t numTuples common::table_id_t tableID, std::unordered_map>&& propertyStatistics) - : tableType{tableType}, numTuples{numTuples}, tableID{tableID}, propertyStatistics{std::move( - propertyStatistics)} { + : tableType{tableType}, numTuples{numTuples}, tableID{tableID}, + propertyStatistics{std::move(propertyStatistics)} { KU_ASSERT(numTuples != UINT64_MAX); } diff --git a/src/storage/stats/table_statistics_collection.cpp b/src/storage/stats/table_statistics_collection.cpp index f423066e746..b07ac250705 100644 --- a/src/storage/stats/table_statistics_collection.cpp +++ b/src/storage/stats/table_statistics_collection.cpp @@ -71,8 +71,8 @@ PropertyStatistics& TablesStatistics::getPropertyStatisticsForTable( } } -void TablesStatistics::setPropertyStatisticsForTable( - table_id_t tableID, property_id_t propertyID, PropertyStatistics stats) { +void TablesStatistics::setPropertyStatisticsForTable(table_id_t tableID, property_id_t propertyID, + PropertyStatistics stats) { initTableStatisticsForWriteTrx(); KU_ASSERT(readWriteVersion && readWriteVersion->tableStatisticPerTable.contains(tableID)); setToUpdated(); @@ -96,9 +96,11 @@ std::unique_ptr TablesStatistics::createMetadataDAHInfo( createMetadataDAHInfo(*fields[i]->getType(), metadataFH, bm, wal); } } break; - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { metadataDAHInfo->childrenInfos.push_back( - createMetadataDAHInfo(*VarListType::getChildType(&dataType), metadataFH, bm, wal)); + createMetadataDAHInfo(*LogicalType::UINT32(), metadataFH, bm, wal)); + metadataDAHInfo->childrenInfos.push_back( + createMetadataDAHInfo(*ListType::getChildType(&dataType), metadataFH, bm, wal)); } break; case PhysicalTypeID::STRING: { auto dataMetadataDAHInfo = std::make_unique(); diff --git a/src/storage/storage_manager.cpp b/src/storage/storage_manager.cpp index 8cf5f99e047..65d91ba97d5 100644 --- a/src/storage/storage_manager.cpp +++ b/src/storage/storage_manager.cpp @@ -1,7 +1,9 @@ #include "storage/storage_manager.h" #include "catalog/catalog_entry/rdf_graph_catalog_entry.h" +#include "catalog/catalog_entry/rel_group_catalog_entry.h" #include "storage/stats/nodes_store_statistics.h" +#include "storage/store/node_table.h" #include "storage/wal_replayer.h" #include "storage/wal_replayer_utils.h" @@ -25,20 +27,22 @@ StorageManager::StorageManager(bool readOnly, const Catalog& catalog, MemoryMana readOnly ? FileHandle::O_PERSISTENT_FILE_READ_ONLY : FileHandle::O_PERSISTENT_FILE_CREATE_NOT_EXISTS, BMFileHandle::FileVersionedType::VERSIONED_FILE, vfs); - nodesStatisticsAndDeletedIDs = std::make_unique( - metadataFH.get(), memoryManager.getBufferManager(), wal, vfs); - relsStatistics = std::make_unique( - metadataFH.get(), memoryManager.getBufferManager(), wal, vfs); + nodesStatisticsAndDeletedIDs = std::make_unique(metadataFH.get(), + memoryManager.getBufferManager(), wal, vfs); + relsStatistics = std::make_unique(metadataFH.get(), + memoryManager.getBufferManager(), wal, vfs); loadTables(readOnly, catalog); } -static void setCommonTableIDToRdfRelTable( - RelTable* relTable, std::vector rdfEntries) { +static void setCommonTableIDToRdfRelTable(RelTable* relTable, + std::vector rdfEntries) { for (auto rdfEntry : rdfEntries) { if (rdfEntry->isParent(relTable->getTableID())) { std::vector columns; - columns.push_back(relTable->getDirectedTableData(RelDataDirection::FWD)->getColumn(1)); - columns.push_back(relTable->getDirectedTableData(RelDataDirection::BWD)->getColumn(1)); + // TODO(Guodong): This is a hack. We should not use constant 2 and should move the + // setting logic inside RelTableData. + columns.push_back(relTable->getDirectedTableData(RelDataDirection::FWD)->getColumn(2)); + columns.push_back(relTable->getDirectedTableData(RelDataDirection::BWD)->getColumn(2)); for (auto& column : columns) { ku_dynamic_cast(column) ->setCommonTableID(rdfEntry->getResourceTableID()); @@ -65,6 +69,7 @@ void StorageManager::loadTables(bool readOnly, const Catalog& catalog) { } void StorageManager::createNodeTable(table_id_t tableID, NodeTableCatalogEntry* nodeTableEntry) { + nodesStatisticsAndDeletedIDs->addNodeStatisticsAndDeletedIDs(nodeTableEntry); WALReplayerUtils::createEmptyHashIndexFiles(nodeTableEntry, wal->getDirectory(), vfs); tables[tableID] = std::make_unique(dataFH.get(), metadataFH.get(), nodeTableEntry, nodesStatisticsAndDeletedIDs.get(), &memoryManager, wal, false /* readOnly */, @@ -73,24 +78,66 @@ void StorageManager::createNodeTable(table_id_t tableID, NodeTableCatalogEntry* void StorageManager::createRelTable(table_id_t tableID, RelTableCatalogEntry* relTableEntry, Catalog* catalog, Transaction* transaction) { + relsStatistics->addTableStatistic(relTableEntry); auto relTable = std::make_unique(dataFH.get(), metadataFH.get(), relsStatistics.get(), &memoryManager, relTableEntry, wal, enableCompression); setCommonTableIDToRdfRelTable(relTable.get(), catalog->getRdfGraphEntries(transaction)); tables[tableID] = std::move(relTable); } +void StorageManager::createRelTableGroup(table_id_t, RelGroupCatalogEntry* tableSchema, + Catalog* catalog, Transaction* transaction) { + for (auto relTableID : tableSchema->getRelTableIDs()) { + createRelTable(relTableID, + ku_dynamic_cast( + catalog->getTableCatalogEntry(transaction, relTableID)), + catalog, transaction); + } +} + +void StorageManager::createRdfGraph(table_id_t, RDFGraphCatalogEntry* tableSchema, Catalog* catalog, + Transaction* transaction) { + auto rdfGraphSchema = ku_dynamic_cast(tableSchema); + auto resourceTableID = rdfGraphSchema->getResourceTableID(); + auto resourceTableEntry = ku_dynamic_cast( + catalog->getTableCatalogEntry(transaction, resourceTableID)); + createNodeTable(resourceTableID, resourceTableEntry); + auto literalTableID = rdfGraphSchema->getLiteralTableID(); + auto literalTableEntry = ku_dynamic_cast( + catalog->getTableCatalogEntry(transaction, literalTableID)); + createNodeTable(literalTableID, literalTableEntry); + auto resourceTripleTableID = rdfGraphSchema->getResourceTripleTableID(); + auto resourceTripleTableEntry = ku_dynamic_cast( + catalog->getTableCatalogEntry(transaction, resourceTripleTableID)); + createRelTable(resourceTripleTableID, resourceTripleTableEntry, catalog, transaction); + auto literalTripleTableID = rdfGraphSchema->getLiteralTripleTableID(); + auto literalTripleTableEntry = ku_dynamic_cast( + catalog->getTableCatalogEntry(transaction, literalTripleTableID)); + createRelTable(literalTripleTableID, literalTripleTableEntry, catalog, transaction); +} + void StorageManager::createTable(table_id_t tableID, Catalog* catalog, Transaction* transaction) { auto tableEntry = catalog->getTableCatalogEntry(transaction, tableID); switch (tableEntry->getTableType()) { case TableType::NODE: { - createNodeTable( - tableID, ku_dynamic_cast(tableEntry)); + createNodeTable(tableID, + ku_dynamic_cast(tableEntry)); } break; case TableType::REL: { createRelTable(tableID, ku_dynamic_cast(tableEntry), catalog, transaction); } break; + case TableType::REL_GROUP: { + createRelTableGroup(tableID, + ku_dynamic_cast(tableEntry), catalog, + transaction); + } break; + case TableType::RDF: { + createRdfGraph(tableID, + ku_dynamic_cast(tableEntry), catalog, + transaction); + } break; default: { KU_UNREACHABLE; } @@ -122,11 +169,15 @@ void StorageManager::dropTable(table_id_t tableID) { tables.erase(tableID); } -void StorageManager::prepareCommit(transaction::Transaction* transaction) { - auto localStorage = transaction->getLocalStorage(); - for (auto tableID : localStorage->getTableIDsWithUpdates()) { - KU_ASSERT(tables.contains(tableID)); - tables.at(tableID)->prepareCommit(transaction, localStorage->getLocalTable(tableID)); +void StorageManager::prepareCommit(Transaction* transaction) { + transaction->getLocalStorage()->prepareCommit(); + // Tables which are created but not inserted into may have pending writes + // which need to be flushed (specifically, the metadata disk array header) + // TODO(bmwinger): wal->getUpdatedTables isn't the ideal place to store this information + for (auto tableID : wal->getUpdatedTables()) { + if (transaction->getLocalStorage()->getLocalTable(tableID) == nullptr) { + getTable(tableID)->prepareCommit(); + } } if (nodesStatisticsAndDeletedIDs->hasUpdates()) { wal->logTableStatisticsRecord(true /* isNodeTable */); @@ -138,18 +189,14 @@ void StorageManager::prepareCommit(transaction::Transaction* transaction) { } } -void StorageManager::prepareRollback(transaction::Transaction* transaction) { +void StorageManager::prepareRollback(Transaction* transaction) { if (nodesStatisticsAndDeletedIDs->hasUpdates()) { wal->logTableStatisticsRecord(true /* isNodeTable */); } if (relsStatistics->hasUpdates()) { wal->logTableStatisticsRecord(false /* isNodeTable */); } - auto localStorage = transaction->getLocalStorage(); - for (auto tableID : localStorage->getTableIDsWithUpdates()) { - KU_ASSERT(tables.contains(tableID)); - tables.at(tableID)->prepareRollback(localStorage->getLocalTableData(tableID)); - } + transaction->getLocalStorage()->prepareRollback(); } void StorageManager::checkpointInMemory() { diff --git a/src/storage/storage_structure/CMakeLists.txt b/src/storage/storage_structure/CMakeLists.txt index 5b86666bedc..479d01c47f0 100644 --- a/src/storage/storage_structure/CMakeLists.txt +++ b/src/storage/storage_structure/CMakeLists.txt @@ -1,8 +1,7 @@ add_library(kuzu_storage_structure OBJECT disk_array.cpp - disk_overflow_file.cpp - in_mem_file.cpp + overflow_file.cpp in_mem_page.cpp db_file_utils.cpp) diff --git a/src/storage/storage_structure/db_file_utils.cpp b/src/storage/storage_structure/db_file_utils.cpp index a079e737c32..eae1d5ab324 100644 --- a/src/storage/storage_structure/db_file_utils.cpp +++ b/src/storage/storage_structure/db_file_utils.cpp @@ -6,13 +6,13 @@ namespace kuzu { namespace storage { struct WALPageIdxAndFrame { - WALPageIdxAndFrame( - common::page_idx_t originalPageIdx, common::page_idx_t pageIdxInWAL, uint8_t* frame) + WALPageIdxAndFrame(common::page_idx_t originalPageIdx, common::page_idx_t pageIdxInWAL, + uint8_t* frame) : originalPageIdx{originalPageIdx}, pageIdxInWAL{pageIdxInWAL}, frame{frame} {} WALPageIdxAndFrame(WALPageIdxAndFrame& other) - : originalPageIdx{other.originalPageIdx}, - pageIdxInWAL{other.pageIdxInWAL}, frame{other.frame} {} + : originalPageIdx{other.originalPageIdx}, pageIdxInWAL{other.pageIdxInWAL}, + frame{other.frame} {} common::page_idx_t originalPageIdx; common::page_idx_t pageIdxInWAL; @@ -26,22 +26,29 @@ WALPageIdxAndFrame createWALVersionIfNecessaryAndPinPage(page_idx_t originalPage page_idx_t pageIdxInWAL; uint8_t* walFrame; fileHandle.acquireWALPageIdxLock(originalPageIdx); - if (fileHandle.hasWALPageVersionNoWALPageIdxLock(originalPageIdx)) { - pageIdxInWAL = fileHandle.getWALPageIdxNoWALPageIdxLock(originalPageIdx); - walFrame = bufferManager.pin( - *wal.fileHandle, pageIdxInWAL, BufferManager::PageReadPolicy::READ_PAGE); - } else { - pageIdxInWAL = - wal.logPageUpdateRecord(dbFileID, originalPageIdx /* pageIdxInOriginalFile */); - walFrame = bufferManager.pin( - *wal.fileHandle, pageIdxInWAL, BufferManager::PageReadPolicy::DONT_READ_PAGE); - if (!insertingNewPage) { - bufferManager.optimisticRead(fileHandle, originalPageIdx, [&](uint8_t* frame) -> void { - memcpy(walFrame, frame, BufferPoolConstants::PAGE_4KB_SIZE); - }); + try { + if (fileHandle.hasWALPageVersionNoWALPageIdxLock(originalPageIdx)) { + pageIdxInWAL = fileHandle.getWALPageIdxNoWALPageIdxLock(originalPageIdx); + walFrame = bufferManager.pin(*wal.fileHandle, pageIdxInWAL, + BufferManager::PageReadPolicy::READ_PAGE); + } else { + pageIdxInWAL = + wal.logPageUpdateRecord(dbFileID, originalPageIdx /* pageIdxInOriginalFile */); + walFrame = bufferManager.pin(*wal.fileHandle, pageIdxInWAL, + BufferManager::PageReadPolicy::DONT_READ_PAGE); + if (!insertingNewPage) { + bufferManager.optimisticRead(fileHandle, originalPageIdx, + [&](uint8_t* frame) -> void { + memcpy(walFrame, frame, BufferPoolConstants::PAGE_4KB_SIZE); + }); + } + fileHandle.setWALPageIdxNoLock(originalPageIdx /* pageIdxInOriginalFile */, + pageIdxInWAL); + wal.fileHandle->setLockedPageDirty(pageIdxInWAL); } - fileHandle.setWALPageIdxNoLock(originalPageIdx /* pageIdxInOriginalFile */, pageIdxInWAL); - wal.fileHandle->setLockedPageDirty(pageIdxInWAL); + } catch (Exception& e) { + fileHandle.releaseWALPageIdxLock(originalPageIdx); + throw; } return {originalPageIdx, pageIdxInWAL, walFrame}; } @@ -67,8 +74,8 @@ std::pair DBFileUtils::getFileHandleAndPhysicalPageId !fileHandle.hasWALPageVersionNoWALPageIdxLock(physicalPageIdx)) { return std::make_pair(&fileHandle, physicalPageIdx); } else { - return std::make_pair( - wal.fileHandle.get(), fileHandle.getWALPageIdxNoWALPageIdxLock(physicalPageIdx)); + return std::make_pair(wal.fileHandle.get(), + fileHandle.getWALPageIdxNoWALPageIdxLock(physicalPageIdx)); } } @@ -76,8 +83,8 @@ common::page_idx_t DBFileUtils::insertNewPage(BMFileHandle& fileHandle, DBFileID BufferManager& bufferManager, WAL& wal, const std::function& insertOp) { auto newOriginalPage = fileHandle.addNewPage(); auto newWALPage = wal.logPageInsertRecord(dbFileID, newOriginalPage); - auto walFrame = bufferManager.pin( - *wal.fileHandle, newWALPage, BufferManager::PageReadPolicy::DONT_READ_PAGE); + auto walFrame = bufferManager.pin(*wal.fileHandle, newWALPage, + BufferManager::PageReadPolicy::DONT_READ_PAGE); fileHandle.addWALPageIdxGroupIfNecessary(newOriginalPage); fileHandle.setWALPageIdx(newOriginalPage, newWALPage); insertOp(walFrame); @@ -89,8 +96,8 @@ common::page_idx_t DBFileUtils::insertNewPage(BMFileHandle& fileHandle, DBFileID void DBFileUtils::updatePage(BMFileHandle& fileHandle, DBFileID dbFileID, page_idx_t originalPageIdx, bool isInsertingNewPage, BufferManager& bufferManager, WAL& wal, const std::function& updateOp) { - auto walPageIdxAndFrame = createWALVersionIfNecessaryAndPinPage( - originalPageIdx, isInsertingNewPage, fileHandle, dbFileID, bufferManager, wal); + auto walPageIdxAndFrame = createWALVersionIfNecessaryAndPinPage(originalPageIdx, + isInsertingNewPage, fileHandle, dbFileID, bufferManager, wal); try { updateOp(walPageIdxAndFrame.frame); } catch (Exception& e) { @@ -106,8 +113,8 @@ void DBFileUtils::readWALVersionOfPage(BMFileHandle& fileHandle, page_idx_t orig auto frame = bufferManager.pin(*wal.fileHandle, pageIdxInWAL, BufferManager::PageReadPolicy::READ_PAGE); readOp(frame); - unpinPageIdxInWALAndReleaseOriginalPageLock( - pageIdxInWAL, originalPageIdx, fileHandle, bufferManager, wal); + unpinPageIdxInWALAndReleaseOriginalPageLock(pageIdxInWAL, originalPageIdx, fileHandle, + bufferManager, wal); } } // namespace storage diff --git a/src/storage/storage_structure/disk_array.cpp b/src/storage/storage_structure/disk_array.cpp index ca30441d9d2..04c3124cf40 100644 --- a/src/storage/storage_structure/disk_array.cpp +++ b/src/storage/storage_structure/disk_array.cpp @@ -3,6 +3,9 @@ #include "common/cast.h" #include "common/string_format.h" #include "common/utils.h" +#include "storage/buffer_manager/bm_file_handle.h" +#include "storage/file_handle.h" +#include "storage/storage_structure/db_file_utils.h" using namespace kuzu::common; using namespace kuzu::transaction; @@ -30,10 +33,11 @@ PIPWrapper::PIPWrapper(FileHandle& fileHandle, page_idx_t pipPageIdx) : pipPageI fileHandle.readPage(reinterpret_cast(&pipContents), pipPageIdx); } -BaseDiskArrayInternal::BaseDiskArrayInternal( - FileHandle& fileHandle, page_idx_t headerPageIdx, uint64_t elementSize) +BaseDiskArrayInternal::BaseDiskArrayInternal(FileHandle& fileHandle, page_idx_t headerPageIdx, + uint64_t elementSize) : header{elementSize}, fileHandle{fileHandle}, headerPageIdx{headerPageIdx}, - hasTransactionalUpdates{false}, bufferManager{nullptr}, wal{nullptr} {} + headerForWriteTrx{header}, hasTransactionalUpdates{false}, bufferManager{nullptr}, + wal{nullptr} {} BaseDiskArrayInternal::BaseDiskArrayInternal(FileHandle& fileHandle, DBFileID dbFileID, page_idx_t headerPageIdx, BufferManager* bufferManager, WAL* wal, @@ -45,6 +49,7 @@ BaseDiskArrayInternal::BaseDiskArrayInternal(FileHandle& fileHandle, DBFileID db transaction->getType()); bufferManager->optimisticRead(*fileHandleToPin, pageIdxToPin, [&](uint8_t* frame) -> void { memcpy(&header, frame, sizeof(DiskArrayHeader)); }); + headerForWriteTrx = header; if (this->header.firstPIPPageIdx != DBFileUtils::NULL_PAGE_IDX) { pips.emplace_back(fileHandle, header.firstPIPPageIdx); while (pips[pips.size() - 1].pipContents.nextPipPageIdx != DBFileUtils::NULL_PAGE_IDX) { @@ -58,11 +63,6 @@ uint64_t BaseDiskArrayInternal::getNumElements(TransactionType trxType) { return getNumElementsNoLock(trxType); } -uint64_t BaseDiskArrayInternal::getNumElementsNoLock(TransactionType trxType) { - return readUInt64HeaderFieldNoLock(trxType, - [](DiskArrayHeader* diskArrayHeader) -> uint64_t { return diskArrayHeader->numElements; }); -} - bool BaseDiskArrayInternal::checkOutOfBoundAccess(TransactionType trxType, uint64_t idx) { auto currentNumElements = getNumElementsNoLock(trxType); if (idx >= currentNumElements) { @@ -135,30 +135,19 @@ uint64_t BaseDiskArrayInternal::resize(uint64_t newNumElements, std::span val) { - uint64_t elementIdx; - DBFileUtils::updatePage((BMFileHandle&)(fileHandle), dbFileID, headerPageIdx, - false /* not inserting a new page */, *bufferManager, *wal, - [this, &val, &elementIdx](uint8_t* frame) -> void { - auto updatedDiskArrayHeader = ((DiskArrayHeader*)frame); - elementIdx = updatedDiskArrayHeader->numElements; - auto apCursor = getAPIdxAndOffsetInAP(elementIdx); - auto [apPageIdx, isNewlyAdded] = getAPPageIdxAndAddAPToPIPIfNecessaryForWriteTrxNoLock( - (DiskArrayHeader*)frame, apCursor.pageIdx); - // Now do the push back. - DBFileUtils::updatePage((BMFileHandle&)(fileHandle), dbFileID, apPageIdx, isNewlyAdded, - *bufferManager, *wal, [&apCursor, &val](uint8_t* frame) -> void { - memcpy(frame + apCursor.elemPosInPage, val.data(), val.size()); - }); - updatedDiskArrayHeader->numElements++; + uint64_t elementIdx = headerForWriteTrx.numElements; + auto apCursor = getAPIdxAndOffsetInAP(elementIdx); + auto [apPageIdx, isNewlyAdded] = + getAPPageIdxAndAddAPToPIPIfNecessaryForWriteTrxNoLock(&headerForWriteTrx, apCursor.pageIdx); + // Now do the push back. + DBFileUtils::updatePage((BMFileHandle&)(fileHandle), dbFileID, apPageIdx, isNewlyAdded, + *bufferManager, *wal, [&apCursor, &val](uint8_t* frame) -> void { + memcpy(frame + apCursor.elemPosInPage, val.data(), val.size()); }); + headerForWriteTrx.numElements++; return elementIdx; } -uint64_t BaseDiskArrayInternal::getNumAPsNoLock(TransactionType trxType) { - return readUInt64HeaderFieldNoLock(trxType, - [](DiskArrayHeader* diskArrayHeader) -> uint64_t { return diskArrayHeader->numAPs; }); -} - void BaseDiskArrayInternal::setNextPIPPageIDxOfPIPNoLock(DiskArrayHeader* updatedDiskArrayHeader, uint64_t pipIdxOfPreviousPIP, page_idx_t nextPIPPageIdx) { // This happens if the first pip is being inserted, in which case we need to change the header. @@ -197,11 +186,19 @@ page_idx_t BaseDiskArrayInternal::getAPPageIdxNoLock(page_idx_t apIdx, Transacti } else { page_idx_t retVal; page_idx_t pageIdxOfUpdatedPip = getUpdatedPageIdxOfPipNoLock(pipIdx); - ((BMFileHandle&)fileHandle).acquireWALPageIdxLock(pageIdxOfUpdatedPip); - DBFileUtils::readWALVersionOfPage((BMFileHandle&)fileHandle, pageIdxOfUpdatedPip, - *bufferManager, *wal, [&retVal, &offsetInPIP](const uint8_t* frame) -> void { - retVal = ((PIP*)frame)->pageIdxs[offsetInPIP]; - }); + if (ku_dynamic_cast(fileHandle) + .hasWALPageVersionNoWALPageIdxLock(pageIdxOfUpdatedPip)) { + ((BMFileHandle&)fileHandle).acquireWALPageIdxLock(pageIdxOfUpdatedPip); + DBFileUtils::readWALVersionOfPage((BMFileHandle&)fileHandle, pageIdxOfUpdatedPip, + *bufferManager, *wal, [&retVal, &offsetInPIP](const uint8_t* frame) -> void { + retVal = ((PIP*)frame)->pageIdxs[offsetInPIP]; + }); + } else { + bufferManager->optimisticRead((BMFileHandle&)fileHandle, pageIdxOfUpdatedPip, + [&retVal, &offsetInPIP](const uint8_t* frame) -> void { + retVal = ((PIP*)frame)->pageIdxs[offsetInPIP]; + }); + } return retVal; } } @@ -223,10 +220,10 @@ void BaseDiskArrayInternal::checkpointOrRollbackInMemoryIfNecessaryNoLock(bool i if (!hasTransactionalUpdates) { return; } - // Note: We update the header regardless (even if it has not changed). We can optimize this - // by adding logic that keep track of whether the header has been updated. if (isCheckpoint) { - header.readFromFile(this->fileHandle, headerPageIdx); + header = headerForWriteTrx; + } else { + headerForWriteTrx = header; } clearWALPageVersionAndRemovePageFromFrameIfNecessary(headerPageIdx); for (uint64_t pipIdxOfUpdatedPIP : pipUpdates.updatedPipIdxs) { @@ -254,6 +251,17 @@ void BaseDiskArrayInternal::checkpointOrRollbackInMemoryIfNecessaryNoLock(bool i hasTransactionalUpdates = false; } +void BaseDiskArrayInternal::prepareCommit() { + // Update header if it has changed + if (headerForWriteTrx != header) { + DBFileUtils::updatePage((BMFileHandle&)(fileHandle), dbFileID, headerPageIdx, + false /* not inserting a new page */, *bufferManager, *wal, + [&](uint8_t* frame) -> void { + memcpy(frame, &headerForWriteTrx, sizeof(headerForWriteTrx)); + }); + } +} + bool BaseDiskArrayInternal::hasPIPUpdatesNoLock(uint64_t pipIdx) { // This is a request to a pipIdx > pips.size(). Since pips.size() is the original number of pips // we started with before the write transaction is updated, we return true, i.e., this PIP is @@ -264,24 +272,6 @@ bool BaseDiskArrayInternal::hasPIPUpdatesNoLock(uint64_t pipIdx) { return pipUpdates.updatedPipIdxs.contains(pipIdx); } -uint64_t BaseDiskArrayInternal::readUInt64HeaderFieldNoLock( - TransactionType trxType, std::function readOp) { - // TODO(Guodong): Fix the casting here, which can be incorrect for HashIndexBuilder. - auto bmFileHandle = reinterpret_cast(&fileHandle); - if ((trxType == TransactionType::READ_ONLY) || - !bmFileHandle->hasWALPageVersionNoWALPageIdxLock(headerPageIdx)) { - return readOp(&this->header); - } else { - uint64_t retVal; - ((BMFileHandle&)fileHandle).acquireWALPageIdxLock(headerPageIdx); - DBFileUtils::readWALVersionOfPage((BMFileHandle&)fileHandle, headerPageIdx, *bufferManager, - *wal, [&retVal, &readOp](uint8_t* frame) -> void { - retVal = readOp((DiskArrayHeader*)frame); - }); - return retVal; - } -} - std::pair BaseDiskArrayInternal::getAPPageIdxAndAddAPToPIPIfNecessaryForWriteTrxNoLock( DiskArrayHeader* updatedDiskArrayHeader, page_idx_t apIdx) { @@ -345,8 +335,8 @@ BaseInMemDiskArray::BaseInMemDiskArray(FileHandle& fileHandle, DBFileID dbFileID } } -BaseInMemDiskArray::BaseInMemDiskArray( - FileHandle& fileHandle, page_idx_t headerPageIdx, uint64_t elementSize) +BaseInMemDiskArray::BaseInMemDiskArray(FileHandle& fileHandle, page_idx_t headerPageIdx, + uint64_t elementSize) : BaseDiskArrayInternal(fileHandle, headerPageIdx, elementSize) {} // [] operator to be used when building an InMemDiskArrayBuilder without transactional updates. @@ -363,74 +353,8 @@ void BaseInMemDiskArray::addInMemoryArrayPageAndReadFromFile(page_idx_t apPageId } void BaseInMemDiskArray::readArrayPageFromFile(uint64_t apIdx, page_idx_t apPageIdx) { - this->fileHandle.readPage( - reinterpret_cast(this->inMemArrayPages[apIdx].get()), apPageIdx); -} - -InMemDiskArrayInternal::InMemDiskArrayInternal(FileHandle& fileHandle, DBFileID dbFileID, - page_idx_t headerPageIdx, BufferManager* bufferManager, WAL* wal, - transaction::Transaction* transaction) - : BaseInMemDiskArray(fileHandle, dbFileID, headerPageIdx, bufferManager, wal, transaction) {} - -void InMemDiskArrayInternal::checkpointOrRollbackInMemoryIfNecessaryNoLock(bool isCheckpoint) { - if (!this->hasTransactionalUpdates) { - return; - } - uint64_t numOldAPs = this->getNumAPsNoLock(TransactionType::READ_ONLY); - for (uint64_t apIdx = 0; apIdx < numOldAPs; ++apIdx) { - uint64_t apPageIdx = this->getAPPageIdxNoLock(apIdx, TransactionType::READ_ONLY); - if (ku_dynamic_cast(this->fileHandle) - .hasWALPageVersionNoWALPageIdxLock(apPageIdx)) { - // Note we can directly read the new image from disk because the WALReplayer checkpoints - // the disk image of the page before calling - // InMemDiskArray::checkpointInMemoryIfNecessary. - if (isCheckpoint) { - this->readArrayPageFromFile(apIdx, apPageIdx); - } - this->clearWALPageVersionAndRemovePageFromFrameIfNecessary(apPageIdx); - } - } - uint64_t newNumAPs = this->getNumAPsNoLock(TransactionType::WRITE); - // When rolling back, unlike removing new PIPs in - // BaseDiskArray::checkpointOrRollbackInMemoryIfNecessaryNoLock when rolling back, we cannot - // directly truncate each page. Instead we need to keep track of the minimum apPageIdx we - // saw that we want to truncate to first. Then we call - // BaseDiskArray::checkpointOrRollbackInMemoryIfNecessaryNoLock, which can do its own - // truncation due to newly added PIPs. Then finally we truncate. The reason is this: suppose - // we added a new apIdx=1 with pageIdx 20 in the fileHandle, which suppose caused a new PIP - // to be inserted with pageIdx 21, and we further added one more new apIdx=2 with - // pageIdx 22. Now this function will loop through the newly added apIdxs, so apIdx=1 and 2 - // in that order. If we directly truncate to the pageIdx of apIdx=1, which is 20, then we - // will remove 21 and 22. But then we will loop through apIdx=2 and we need to convert it to - // its pageIdx to clear its updated WAL version. But that requires reading the newly added - // PIP's WAL version, which had pageIdx 22 but no longer exists. That would lead to a seg - // fault somewhere. So we do not truncate these in order not to accidentally remove newly - // added PIPs, which we would need if we kept calling removePageIdxAndTruncateIfNecessary - // for each newly added array pages. - page_idx_t minNewAPPageIdxToTruncateTo = INVALID_PAGE_IDX; - for (uint64_t apIdx = this->header.numAPs; apIdx < newNumAPs; apIdx++) { - page_idx_t apPageIdx = this->getAPPageIdxNoLock(apIdx, TransactionType::WRITE); - if (isCheckpoint) { - this->addInMemoryArrayPageAndReadFromFile(apPageIdx); - } - this->clearWALPageVersionAndRemovePageFromFrameIfNecessary(apPageIdx); - if (!isCheckpoint) { - minNewAPPageIdxToTruncateTo = std::min(minNewAPPageIdxToTruncateTo, apPageIdx); - } - } - - // TODO(Semih): Currently we do not support truncating DiskArrays. When we support that, we - // need to implement the logic to truncate InMemArrayPages as well. - // Note that the base class call sets hasTransactionalUpdates to false. - if (isCheckpoint) { - BaseDiskArrayInternal::checkpointOrRollbackInMemoryIfNecessaryNoLock( - true /* is checkpoint */); - } else { - BaseDiskArrayInternal::checkpointOrRollbackInMemoryIfNecessaryNoLock( - false /* is rollback */); - ((BMFileHandle&)this->fileHandle) - .removePageIdxAndTruncateIfNecessary(minNewAPPageIdxToTruncateTo); - } + this->fileHandle.readPage(reinterpret_cast(this->inMemArrayPages[apIdx].get()), + apPageIdx); } InMemDiskArrayBuilderInternal::InMemDiskArrayBuilderInternal(FileHandle& fileHandle, @@ -455,8 +379,8 @@ void InMemDiskArrayBuilderInternal::saveToDisk() { // save the header and pips. this->header.saveToDisk(this->fileHandle, this->headerPageIdx); for (auto i = 0u; i < this->pips.size(); ++i) { - this->fileHandle.writePage( - reinterpret_cast(&this->pips[i].pipContents), this->pips[i].pipPageIdx); + this->fileHandle.writePage(reinterpret_cast(&this->pips[i].pipContents), + this->pips[i].pipPageIdx); } // Save array pages for (page_idx_t apIdx = 0; apIdx < this->header.numAPs; ++apIdx) { diff --git a/src/storage/storage_structure/disk_overflow_file.cpp b/src/storage/storage_structure/disk_overflow_file.cpp deleted file mode 100644 index 37a0091a1cb..00000000000 --- a/src/storage/storage_structure/disk_overflow_file.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "storage/storage_structure/disk_overflow_file.h" - -#include - -#include "common/constants.h" -#include "common/exception/message.h" -#include "common/type_utils.h" -#include "common/types/types.h" -#include "storage/storage_structure/db_file_utils.h" -#include "storage/storage_utils.h" - -using lock_t = std::unique_lock; - -using namespace kuzu::transaction; -using namespace kuzu::common; - -namespace kuzu { -namespace storage { - -std::string DiskOverflowFile::readString(TransactionType trxType, const ku_string_t& str) { - if (ku_string_t::isShortString(str.len)) { - return str.getAsShortString(); - } else { - PageCursor cursor; - TypeUtils::decodeOverflowPtr(str.overflowPtr, cursor.pageIdx, cursor.elemPosInPage); - std::string retVal; - retVal.reserve(str.len); - int32_t remainingLength = str.len; - while (remainingLength > 0) { - auto [fileHandleToPin, pageIdxToPin] = - DBFileUtils::getFileHandleAndPhysicalPageIdxToPin( - *fileHandle, cursor.pageIdx, *wal, trxType); - auto numBytesToReadInPage = std::min( - static_cast(remainingLength), END_OF_PAGE - cursor.elemPosInPage); - page_idx_t nextPage; - auto startPosInSrc = retVal.size(); - bufferManager->optimisticRead(*fileHandleToPin, pageIdxToPin, [&](uint8_t* frame) { - // Replace rather than append, since optimistic read may call the function multiple - // times - retVal.replace(startPosInSrc, numBytesToReadInPage, - std::string_view(reinterpret_cast(frame) + cursor.elemPosInPage, - numBytesToReadInPage)); - nextPage = *(page_idx_t*)(frame + END_OF_PAGE); - }); - remainingLength -= numBytesToReadInPage; - // After the first page we always start reading from the beginning of the page. - cursor.elemPosInPage = 0; - KU_ASSERT(nextPage < fileHandle->getNumPages()); - cursor.pageIdx = nextPage; - } - return retVal; - } -} - -bool DiskOverflowFile::addNewPageIfNecessaryWithoutLock(uint32_t numBytesToAppend) { - if ((nextPosToWriteTo.elemPosInPage == 0) || - ((nextPosToWriteTo.elemPosInPage + numBytesToAppend - 1) > END_OF_PAGE)) { - page_idx_t newPageIdx = - DBFileUtils::insertNewPage(*fileHandle, dbFileID, *bufferManager, *wal); - // Write new page index to end of previous page - if (nextPosToWriteTo.pageIdx > 0) { - DBFileUtils::updatePage(*fileHandle, dbFileID, nextPosToWriteTo.pageIdx - 1, - false /* existing page */, *bufferManager, *wal, - [&](auto frame) { memcpy(frame + END_OF_PAGE, &newPageIdx, sizeof(page_idx_t)); }); - } - return true; - } - return false; -} - -void DiskOverflowFile::setStringOverflowWithoutLock( - const char* srcRawString, uint64_t len, ku_string_t& diskDstString) { - if (len <= ku_string_t::SHORT_STR_LENGTH) { - return; - } else if (len > BufferPoolConstants::PAGE_256KB_SIZE) { - if constexpr (StorageConstants::TRUNCATE_OVER_LARGE_STRINGS) { - len = BufferPoolConstants::PAGE_256KB_SIZE; - diskDstString.len = len; - } else { - throw RuntimeException(ExceptionMessage::overLargeStringPKValueException(len)); - } - } - int32_t remainingLength = len; - TypeUtils::encodeOverflowPtr( - diskDstString.overflowPtr, nextPosToWriteTo.pageIdx, nextPosToWriteTo.elemPosInPage); - while (remainingLength > 0) { - auto bytesWritten = len - remainingLength; - auto numBytesToWriteInPage = std::min( - static_cast(remainingLength), END_OF_PAGE - nextPosToWriteTo.elemPosInPage); - bool insertingNewPage = addNewPageIfNecessaryWithoutLock(remainingLength); - DBFileUtils::updatePage(*fileHandle, dbFileID, nextPosToWriteTo.pageIdx, insertingNewPage, - *bufferManager, *wal, [&](auto frame) { - memcpy(frame + nextPosToWriteTo.elemPosInPage, srcRawString + bytesWritten, - numBytesToWriteInPage); - }); - remainingLength -= numBytesToWriteInPage; - nextPosToWriteTo.elemPosInPage += numBytesToWriteInPage; - if (nextPosToWriteTo.elemPosInPage >= END_OF_PAGE) { - nextPosToWriteTo.nextPage(); - } - } -} - -ku_string_t DiskOverflowFile::writeString(std::string_view rawString) { - lock_t lck{mtx}; - ku_string_t result; - result.len = rawString.length(); - auto shortStrLen = ku_string_t::SHORT_STR_LENGTH; - auto inlineLen = std::min(shortStrLen, (uint64_t)result.len); - memcpy(result.prefix, rawString.data(), inlineLen); - logNewOverflowFileNextBytePosRecordIfNecessaryWithoutLock(); - setStringOverflowWithoutLock(rawString.data(), result.len, result); - return result; -} - -void DiskOverflowFile::logNewOverflowFileNextBytePosRecordIfNecessaryWithoutLock() { - if (!loggedNewOverflowFileNextBytePosRecord) { - loggedNewOverflowFileNextBytePosRecord = true; - wal->logOverflowFileNextBytePosRecord( - dbFileID, nextPosToWriteTo.pageIdx * BufferPoolConstants::PAGE_4KB_SIZE + - nextPosToWriteTo.elemPosInPage); - } -} - -} // namespace storage -} // namespace kuzu diff --git a/src/storage/storage_structure/in_mem_file.cpp b/src/storage/storage_structure/in_mem_file.cpp deleted file mode 100644 index 9d4c1d21075..00000000000 --- a/src/storage/storage_structure/in_mem_file.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "storage/storage_structure/in_mem_file.h" - -#include "common/constants.h" -#include "common/exception/copy.h" -#include "common/exception/message.h" -#include "common/type_utils.h" -#include "common/types/ku_string.h" -#include "common/types/types.h" - -using namespace kuzu::common; - -namespace kuzu { -namespace storage { - -InMemFile::InMemFile(std::shared_ptr fileInfo, std::atomic& pageCounter) - : fileInfo{fileInfo}, nextPosToAppend(0, 0), pageCounter(pageCounter) {} - -void InMemFile::addANewPage() { - page_idx_t newPageIdx = pageCounter.fetch_add(1); - // Write the index of the next page to the end of the current page, in case a string overflows - // from one page to another This is always done, as strings are unlikely to end exactly at the - // end of a page and it's probably not worth the additional complexity to save a few bytes on - // the occasions that a string does - if (pages.size() > 0) { - pages[nextPosToAppend.pageIdx]->write( - END_OF_PAGE, reinterpret_cast(&newPageIdx), sizeof(page_idx_t)); - } - pages.emplace(newPageIdx, std::make_unique()); - nextPosToAppend.elemPosInPage = 0; - nextPosToAppend.pageIdx = newPageIdx; -} - -void InMemFile::appendString(std::string_view rawString, ku_string_t& result) { - auto length = rawString.length(); - result.len = length; - std::memcpy(result.prefix, rawString.data(), - length <= ku_string_t::SHORT_STR_LENGTH ? length : ku_string_t::PREFIX_LENGTH); - if (length > ku_string_t::SHORT_STR_LENGTH) { - if (length > BufferPoolConstants::PAGE_256KB_SIZE) { - if constexpr (StorageConstants::TRUNCATE_OVER_LARGE_STRINGS) { - length = BufferPoolConstants::PAGE_256KB_SIZE; - result.len = length; - } else { - throw CopyException(ExceptionMessage::overLargeStringPKValueException(length)); - } - } - if (pages.size() == 0) { - addANewPage(); - } - - int32_t remainingLength = length; - // There should always be some space to write. The constructor adds an empty page, and - // we always add new pages if we run out of space at the end of the following loop - KU_ASSERT(nextPosToAppend.elemPosInPage < END_OF_PAGE); - - TypeUtils::encodeOverflowPtr( - result.overflowPtr, nextPosToAppend.pageIdx, nextPosToAppend.elemPosInPage); - while (remainingLength > 0) { - auto numBytesToWriteInPage = std::min(static_cast(remainingLength), - END_OF_PAGE - nextPosToAppend.elemPosInPage); - pages[nextPosToAppend.pageIdx]->write(nextPosToAppend.elemPosInPage, - reinterpret_cast(rawString.data()) + (length - remainingLength), - numBytesToWriteInPage); - remainingLength -= numBytesToWriteInPage; - // Allocate a new page if necessary. - nextPosToAppend.elemPosInPage += numBytesToWriteInPage; - if (nextPosToAppend.elemPosInPage >= END_OF_PAGE) { - addANewPage(); - } - } - } -} - -std::string InMemFile::readString(ku_string_t* strInInMemOvfFile) const { - auto length = strInInMemOvfFile->len; - if (ku_string_t::isShortString(length)) { - return strInInMemOvfFile->getAsShortString(); - } else { - PageCursor cursor; - TypeUtils::decodeOverflowPtr( - strInInMemOvfFile->overflowPtr, cursor.pageIdx, cursor.elemPosInPage); - std::string result; - result.reserve(length); - auto remainingLength = length; - while (remainingLength > 0) { - auto numBytesToReadInPage = std::min( - static_cast(remainingLength), END_OF_PAGE - cursor.elemPosInPage); - result += - std::string_view(reinterpret_cast(pages.at(cursor.pageIdx)->data) + - cursor.elemPosInPage, - numBytesToReadInPage); - cursor.elemPosInPage = 0; - cursor.pageIdx = getNextPageIndex(cursor.pageIdx); - remainingLength -= numBytesToReadInPage; - } - return result; - } -} - -bool InMemFile::equals(std::string_view keyToLookup, const ku_string_t& keyInEntry) const { - PageCursor cursor; - TypeUtils::decodeOverflowPtr(keyInEntry.overflowPtr, cursor.pageIdx, cursor.elemPosInPage); - auto lengthRead = 0u; - while (lengthRead < keyInEntry.len) { - auto numBytesToCheckInPage = std::min( - static_cast(keyInEntry.len) - lengthRead, END_OF_PAGE - cursor.elemPosInPage); - if (memcmp(keyToLookup.data() + lengthRead, - getPage(cursor.pageIdx)->data + cursor.elemPosInPage, numBytesToCheckInPage) != 0) { - return false; - } - cursor.elemPosInPage = 0; - cursor.pageIdx = getNextPageIndex(cursor.pageIdx); - lengthRead += numBytesToCheckInPage; - } - return true; -} - -void InMemFile::flush() { - for (auto& [pageIndex, page] : pages) { - // actual page index is stored inside of the InMemPage and does not correspond to the index - // in the vector - fileInfo->writeFile(page->data, BufferPoolConstants::PAGE_4KB_SIZE, - pageIndex * BufferPoolConstants::PAGE_4KB_SIZE); - } -} - -} // namespace storage -} // namespace kuzu diff --git a/src/storage/storage_structure/in_mem_page.cpp b/src/storage/storage_structure/in_mem_page.cpp index 777307fd20c..694cd4f0974 100644 --- a/src/storage/storage_structure/in_mem_page.cpp +++ b/src/storage/storage_structure/in_mem_page.cpp @@ -14,8 +14,8 @@ InMemPage::InMemPage() { data = buffer.get(); } -uint8_t* InMemPage::write( - uint32_t byteOffsetInPage, const uint8_t* elem, uint32_t numBytesForElem) const { +uint8_t* InMemPage::write(uint32_t byteOffsetInPage, const uint8_t* elem, + uint32_t numBytesForElem) const { memcpy(data + byteOffsetInPage, elem, numBytesForElem); return data + byteOffsetInPage; } diff --git a/src/storage/storage_structure/overflow_file.cpp b/src/storage/storage_structure/overflow_file.cpp new file mode 100644 index 00000000000..4ce27b5a6db --- /dev/null +++ b/src/storage/storage_structure/overflow_file.cpp @@ -0,0 +1,240 @@ +#include "storage/storage_structure/overflow_file.h" + +#include + +#include "common/constants.h" +#include "common/exception/message.h" +#include "common/type_utils.h" +#include "common/types/types.h" +#include "storage/buffer_manager/bm_file_handle.h" +#include "storage/file_handle.h" +#include "storage/storage_structure/db_file_utils.h" +#include "storage/storage_structure/in_mem_page.h" +#include "storage/storage_utils.h" +#include "transaction/transaction.h" + +using namespace kuzu::transaction; +using namespace kuzu::common; + +namespace kuzu { +namespace storage { + +std::string OverflowFileHandle::readString(TransactionType trxType, const ku_string_t& str) { + if (ku_string_t::isShortString(str.len)) { + return str.getAsShortString(); + } else { + PageCursor cursor; + TypeUtils::decodeOverflowPtr(str.overflowPtr, cursor.pageIdx, cursor.elemPosInPage); + std::string retVal; + retVal.reserve(str.len); + int32_t remainingLength = str.len; + while (remainingLength > 0) { + auto numBytesToReadInPage = std::min(static_cast(remainingLength), + END_OF_PAGE - cursor.elemPosInPage); + auto startPosInSrc = retVal.size(); + read(trxType, cursor.pageIdx, [&](uint8_t* frame) { + // Replace rather than append, since optimistic read may call the function multiple + // times + retVal.replace(startPosInSrc, numBytesToReadInPage, + std::string_view(reinterpret_cast(frame) + cursor.elemPosInPage, + numBytesToReadInPage)); + cursor.pageIdx = *(page_idx_t*)(frame + END_OF_PAGE); + }); + remainingLength -= numBytesToReadInPage; + // After the first page we always start reading from the beginning of the page. + cursor.elemPosInPage = 0; + } + return retVal; + } +} + +bool OverflowFileHandle::equals(TransactionType trxType, std::string_view keyToLookup, + const common::ku_string_t& keyInEntry) const { + PageCursor cursor; + TypeUtils::decodeOverflowPtr(keyInEntry.overflowPtr, cursor.pageIdx, cursor.elemPosInPage); + auto lengthRead = 0u; + while (lengthRead < keyInEntry.len) { + auto numBytesToCheckInPage = std::min(static_cast(keyInEntry.len) - lengthRead, + END_OF_PAGE - cursor.elemPosInPage); + bool equal = true; + read(trxType, cursor.pageIdx, [&](auto* frame) { + equal = memcmp(keyToLookup.data() + lengthRead, frame + cursor.elemPosInPage, + numBytesToCheckInPage) == 0; + // Update the next page index + cursor.pageIdx = *(page_idx_t*)(frame + END_OF_PAGE); + }); + if (!equal) { + return false; + } + cursor.elemPosInPage = 0; + lengthRead += numBytesToCheckInPage; + } + return true; +} + +uint8_t* OverflowFileHandle::addANewPage() { + page_idx_t newPageIdx = overflowFile.getNewPageIdx(); + if (pageWriteCache.size() > 0) { + pageWriteCache[nextPosToWriteTo.pageIdx]->write(END_OF_PAGE, + reinterpret_cast(&newPageIdx), sizeof(page_idx_t)); + } + pageWriteCache.emplace(newPageIdx, std::make_unique()); + nextPosToWriteTo.elemPosInPage = 0; + nextPosToWriteTo.pageIdx = newPageIdx; + return pageWriteCache[newPageIdx]->data; +} + +void OverflowFileHandle::setStringOverflow(const char* srcRawString, uint64_t len, + ku_string_t& diskDstString) { + if (len <= ku_string_t::SHORT_STR_LENGTH) { + return; + } else if (len > BufferPoolConstants::PAGE_256KB_SIZE) { + if constexpr (StorageConstants::TRUNCATE_OVER_LARGE_STRINGS) { + len = BufferPoolConstants::PAGE_256KB_SIZE; + diskDstString.len = len; + } else { + throw RuntimeException(ExceptionMessage::overLargeStringPKValueException(len)); + } + } + overflowFile.headerChanged = true; + uint8_t* pageToWrite = nullptr; + if (nextPosToWriteTo.pageIdx == INVALID_PAGE_IDX) { + pageToWrite = addANewPage(); + } else { + auto cached = pageWriteCache.find(nextPosToWriteTo.pageIdx); + if (cached != pageWriteCache.end()) { + pageToWrite = cached->second->data; + } else { + overflowFile.readFromDisk(TransactionType::WRITE, nextPosToWriteTo.pageIdx, + [&](auto* frame) { + auto page = std::make_unique(); + memcpy(page->data, frame, BufferPoolConstants::PAGE_4KB_SIZE); + pageToWrite = page->data; + pageWriteCache.emplace(nextPosToWriteTo.pageIdx, std::move(page)); + }); + } + } + int32_t remainingLength = len; + TypeUtils::encodeOverflowPtr(diskDstString.overflowPtr, nextPosToWriteTo.pageIdx, + nextPosToWriteTo.elemPosInPage); + while (remainingLength > 0) { + auto bytesWritten = len - remainingLength; + auto numBytesToWriteInPage = std::min(static_cast(remainingLength), + END_OF_PAGE - nextPosToWriteTo.elemPosInPage); + memcpy(pageToWrite + nextPosToWriteTo.elemPosInPage, srcRawString + bytesWritten, + numBytesToWriteInPage); + remainingLength -= numBytesToWriteInPage; + nextPosToWriteTo.elemPosInPage += numBytesToWriteInPage; + if (nextPosToWriteTo.elemPosInPage >= END_OF_PAGE) { + pageToWrite = addANewPage(); + } + } +} + +ku_string_t OverflowFileHandle::writeString(std::string_view rawString) { + ku_string_t result; + result.len = rawString.length(); + auto shortStrLen = ku_string_t::SHORT_STR_LENGTH; + auto inlineLen = std::min(shortStrLen, (uint64_t)result.len); + memcpy(result.prefix, rawString.data(), inlineLen); + setStringOverflow(rawString.data(), result.len, result); + return result; +} + +void OverflowFileHandle::prepareCommit() { + for (auto& [pageIndex, page] : pageWriteCache) { + overflowFile.writePageToDisk(pageIndex, page->data); + } +} + +void OverflowFileHandle::read(transaction::TransactionType trxType, common::page_idx_t pageIdx, + const std::function& func) const { + if (trxType == TransactionType::WRITE) { + auto cachedPage = pageWriteCache.find(pageIdx); + if (cachedPage != pageWriteCache.end()) { + return func(cachedPage->second->data); + } + } + overflowFile.readFromDisk(trxType, pageIdx, func); +} + +static inline DBFileIDAndName constructDBFileIDAndName( + const DBFileIDAndName& dbFileIdAndNameForMainDBFile) { + DBFileIDAndName copy = dbFileIdAndNameForMainDBFile; + copy.dbFileID.isOverflow = true; + copy.fName = StorageUtils::getOverflowFileName(dbFileIdAndNameForMainDBFile.fName); + return copy; +} + +OverflowFile::OverflowFile(const DBFileIDAndName& dbFileIdAndName, BufferManager* bufferManager, + WAL* wal, bool readOnly, common::VirtualFileSystem* vfs) + : bufferManager{bufferManager}, wal{wal}, headerChanged{false} { + auto overflowFileIDAndName = constructDBFileIDAndName(dbFileIdAndName); + dbFileID = overflowFileIDAndName.dbFileID; + fileHandle = bufferManager->getBMFileHandle(overflowFileIDAndName.fName, + readOnly ? FileHandle::O_PERSISTENT_FILE_READ_ONLY : + FileHandle::O_PERSISTENT_FILE_NO_CREATE, + BMFileHandle::FileVersionedType::VERSIONED_FILE, vfs); + if (vfs->fileOrPathExists(overflowFileIDAndName.fName)) { + readFromDisk(transaction::TransactionType::READ_ONLY, HEADER_PAGE_IDX, + [&](auto* frame) { memcpy(&header, frame, sizeof(header)); }); + pageCounter = numPagesOnDisk = header.pages; + } else { + // Reserve a page for the header + getNewPageIdx(); + } +} + +void OverflowFile::readFromDisk(transaction::TransactionType trxType, common::page_idx_t pageIdx, + const std::function& func) const { + auto [fileHandleToPin, pageIdxToPin] = + storage::DBFileUtils::getFileHandleAndPhysicalPageIdxToPin(*getBMFileHandle(), pageIdx, + *wal, trxType); + bufferManager->optimisticRead(*fileHandleToPin, pageIdxToPin, func); +} + +void OverflowFile::writePageToDisk(common::page_idx_t pageIdx, uint8_t* data) const { + if (pageIdx < numPagesOnDisk) { + // TODO: updatePage does an unnecessary read + copy. We just want to overwrite + DBFileUtils::updatePage(*getBMFileHandle(), dbFileID, pageIdx, false, *bufferManager, *wal, + [&](auto* frame) { memcpy(frame, data, BufferPoolConstants::PAGE_4KB_SIZE); }); + } else { + fileHandle->writePage(data, pageIdx); + } +} + +void OverflowFile::prepareCommit() { + if (fileHandle->getNumPages() < pageCounter) { + fileHandle->addNewPages(pageCounter - fileHandle->getNumPages()); + } + // TODO(bmwinger): Ideally this could be done separately and in parallel by each HashIndex + // However fileHandle->addNewPages needs to be called beforehand, + // but after each HashIndex::prepareCommit has written to the in-memory pages + for (auto& handle : handles) { + handle->prepareCommit(); + } + if (headerChanged) { + uint8_t page[BufferPoolConstants::PAGE_4KB_SIZE]; + header.pages = pageCounter; + memcpy(page, &header, sizeof(header)); + writePageToDisk(HEADER_PAGE_IDX, page); + } +} + +void OverflowFile::checkpointInMemory() { + headerChanged = false; + numPagesOnDisk = pageCounter; +} + +void OverflowFile::rollbackInMemory() { + readFromDisk(transaction::TransactionType::READ_ONLY, HEADER_PAGE_IDX, + [&](auto* frame) { memcpy(&header, frame, sizeof(header)); }); + numPagesOnDisk = pageCounter = header.pages; + for (auto i = 0u; i < handles.size(); i++) { + auto& handle = handles[i]; + handle->rollbackInMemory(header.cursors[i]); + } +} + +} // namespace storage +} // namespace kuzu diff --git a/src/storage/storage_utils.cpp b/src/storage/storage_utils.cpp index b29197608ba..b918f1e640d 100644 --- a/src/storage/storage_utils.cpp +++ b/src/storage/storage_utils.cpp @@ -16,8 +16,8 @@ using namespace kuzu::common; namespace kuzu { namespace storage { -std::string StorageUtils::getColumnName( - const std::string& propertyName, StorageUtils::ColumnType type, const std::string& prefix) { +std::string StorageUtils::getColumnName(const std::string& propertyName, + StorageUtils::ColumnType type, const std::string& prefix) { switch (type) { case StorageUtils::ColumnType::DATA: { return stringFormat("{}_data", propertyName); @@ -37,9 +37,6 @@ std::string StorageUtils::getColumnName( case StorageUtils::ColumnType::CSR_LENGTH: { return stringFormat("{}_csr_length", prefix); } - case StorageUtils::ColumnType::ADJ: { - return stringFormat("{}_adj", prefix); - } case StorageUtils::ColumnType::STRUCT_CHILD: { return stringFormat("{}_{}_child", propertyName, prefix); } @@ -60,8 +57,8 @@ std::string StorageUtils::getNodeIndexFName(const VirtualFileSystem* vfs, vfs->joinPath(directory, fName + StorageConstants::INDEX_FILE_SUFFIX), fileVersionType); } -std::unique_ptr StorageUtils::getFileInfoForReadWrite( - const std::string& directory, DBFileID dbFileID, VirtualFileSystem* vfs) { +std::unique_ptr StorageUtils::getFileInfoForReadWrite(const std::string& directory, + DBFileID dbFileID, VirtualFileSystem* vfs) { std::string fName; switch (dbFileID.dbFileType) { case DBFileType::METADATA: { @@ -71,8 +68,8 @@ std::unique_ptr StorageUtils::getFileInfoForReadWrite( fName = getDataFName(vfs, directory); } break; case DBFileType::NODE_INDEX: { - fName = getNodeIndexFName( - vfs, directory, dbFileID.nodeIndexID.tableID, FileVersionType::ORIGINAL); + fName = getNodeIndexFName(vfs, directory, dbFileID.nodeIndexID.tableID, + FileVersionType::ORIGINAL); if (dbFileID.isOverflow) { fName = getOverflowFileName(fName); } @@ -89,10 +86,9 @@ uint32_t StorageUtils::getDataTypeSize(PhysicalTypeID type) { case PhysicalTypeID::STRING: { return sizeof(ku_string_t); } - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { return sizeof(ku_list_t); } - case PhysicalTypeID::FIXED_LIST: case PhysicalTypeID::STRUCT: { // Not calculable using this interface! KU_UNREACHABLE; @@ -108,11 +104,7 @@ uint32_t StorageUtils::getDataTypeSize(const LogicalType& type) { case PhysicalTypeID::STRING: { return sizeof(ku_string_t); } - case PhysicalTypeID::FIXED_LIST: { - return getDataTypeSize(*FixedListType::getChildType(&type)) * - FixedListType::getNumValuesInList(&type); - } - case PhysicalTypeID::VAR_LIST: { + case PhysicalTypeID::LIST: { return sizeof(ku_list_t); } case PhysicalTypeID::STRUCT: { @@ -130,8 +122,8 @@ uint32_t StorageUtils::getDataTypeSize(const LogicalType& type) { } } -std::string StorageUtils::appendSuffixOrInsertBeforeWALSuffix( - const std::string& fileName, const std::string& suffix) { +std::string StorageUtils::appendSuffixOrInsertBeforeWALSuffix(const std::string& fileName, + const std::string& suffix) { auto pos = fileName.find(StorageConstants::WAL_FILE_SUFFIX); if (pos == std::string::npos) { return fileName + suffix; diff --git a/src/storage/storage_info.cpp b/src/storage/storage_version_info.cpp similarity index 94% rename from src/storage/storage_info.cpp rename to src/storage/storage_version_info.cpp index c033027d6a2..34d54be3b76 100644 --- a/src/storage/storage_info.cpp +++ b/src/storage/storage_version_info.cpp @@ -1,4 +1,4 @@ -#include "storage/storage_info.h" +#include "storage/storage_version_info.h" namespace kuzu { namespace storage { diff --git a/src/storage/store/CMakeLists.txt b/src/storage/store/CMakeLists.txt index 2c579e8276e..4a03cc5dccc 100644 --- a/src/storage/store/CMakeLists.txt +++ b/src/storage/store/CMakeLists.txt @@ -1,10 +1,11 @@ add_library(kuzu_storage_store OBJECT + chunked_node_group.cpp + chunked_node_group_collection.cpp column.cpp column_chunk.cpp dictionary_chunk.cpp dictionary_column.cpp - node_group.cpp node_table.cpp node_table_data.cpp null_column.cpp @@ -15,8 +16,8 @@ add_library(kuzu_storage_store struct_column_chunk.cpp struct_column.cpp table_data.cpp - var_list_column_chunk.cpp - var_list_column.cpp) + list_column_chunk.cpp + list_column.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/storage/store/node_group.cpp b/src/storage/store/chunked_node_group.cpp similarity index 60% rename from src/storage/store/node_group.cpp rename to src/storage/store/chunked_node_group.cpp index d50c64a0d53..f3291c90fb5 100644 --- a/src/storage/store/node_group.cpp +++ b/src/storage/store/chunked_node_group.cpp @@ -1,4 +1,4 @@ -#include "storage/store/node_group.h" +#include "storage/store/chunked_node_group.h" #include "common/assert.h" #include "common/constants.h" @@ -9,7 +9,7 @@ using namespace kuzu::common; namespace kuzu { namespace storage { -bool CSRHeaderChunks::sanityCheck() const { +bool ChunkedCSRHeader::sanityCheck() const { if (offset->getNumValues() != length->getNumValues()) { return false; } @@ -28,8 +28,7 @@ bool CSRHeaderChunks::sanityCheck() const { return true; } -// TODO(Guodong): Should be refactored to use copy of ColumnChunk. -void CSRHeaderChunks::copyFrom(const CSRHeaderChunks& other) const { +void ChunkedCSRHeader::copyFrom(const ChunkedCSRHeader& other) const { auto numValues = other.offset->getNumValues(); memcpy(offset->getData(), other.offset->getData(), numValues * sizeof(offset_t)); memcpy(length->getData(), other.length->getData(), numValues * sizeof(length_t)); @@ -37,7 +36,7 @@ void CSRHeaderChunks::copyFrom(const CSRHeaderChunks& other) const { offset->setNumValues(numValues); } -void CSRHeaderChunks::fillDefaultValues(offset_t newNumValues) const { +void ChunkedCSRHeader::fillDefaultValues(offset_t newNumValues) const { auto lastCSROffset = getEndCSROffset(length->getNumValues() - 1); for (auto i = length->getNumValues(); i < newNumValues; i++) { offset->setValue(lastCSROffset, i); @@ -47,17 +46,18 @@ void CSRHeaderChunks::fillDefaultValues(offset_t newNumValues) const { offset->getNumValues() >= newNumValues && length->getNumValues() == offset->getNumValues()); } -NodeGroup::NodeGroup(const std::vector>& columnTypes, +ChunkedNodeGroup::ChunkedNodeGroup(const std::vector& columnTypes, bool enableCompression, uint64_t capacity) : nodeGroupIdx{UINT64_MAX}, numRows{0} { chunks.reserve(columnTypes.size()); for (auto& type : columnTypes) { chunks.push_back( - ColumnChunkFactory::createColumnChunk(*type->copy(), enableCompression, capacity)); + ColumnChunkFactory::createColumnChunk(*type.copy(), enableCompression, capacity)); } } -NodeGroup::NodeGroup(const std::vector>& columns, bool enableCompression) +ChunkedNodeGroup::ChunkedNodeGroup(const std::vector>& columns, + bool enableCompression) : nodeGroupIdx{UINT64_MAX}, numRows{0} { chunks.reserve(columns.size()); for (auto columnID = 0u; columnID < columns.size(); columnID++) { @@ -66,7 +66,7 @@ NodeGroup::NodeGroup(const std::vector>& columns, bool e } } -void NodeGroup::resetToEmpty() { +void ChunkedNodeGroup::resetToEmpty() { numRows = 0; nodeGroupIdx = UINT64_MAX; for (auto& chunk : chunks) { @@ -74,31 +74,32 @@ void NodeGroup::resetToEmpty() { } } -void NodeGroup::setAllNull() { +void ChunkedNodeGroup::setAllNull() { for (auto& chunk : chunks) { chunk->getNullChunk()->resetToAllNull(); } } -void NodeGroup::setNumValues(common::offset_t numValues) { +void ChunkedNodeGroup::setNumRows(common::offset_t numRows_) { for (auto& chunk : chunks) { - chunk->setNumValues(numValues); + chunk->setNumValues(numRows_); } + numRows = numRows_; } -void NodeGroup::resizeChunks(uint64_t newSize) { +void ChunkedNodeGroup::resizeChunks(uint64_t newSize) { for (auto& chunk : chunks) { chunk->resize(newSize); } } -uint64_t NodeGroup::append(const std::vector& columnVectors, - DataChunkState* columnState, uint64_t numValuesToAppend) { +uint64_t ChunkedNodeGroup::append(const std::vector& columnVectors, + SelectionVector& selVector, uint64_t numValuesToAppend) { auto numValuesToAppendInChunk = std::min(numValuesToAppend, StorageConstants::NODE_GROUP_SIZE - numRows); auto serialSkip = 0u; - auto originalSize = columnState->selVector->selectedSize; - columnState->selVector->selectedSize = numValuesToAppendInChunk; + auto originalSize = selVector.selectedSize; + selVector.selectedSize = numValuesToAppendInChunk; for (auto i = 0u; i < chunks.size(); i++) { auto chunk = chunks[i].get(); if (chunk->getDataType().getLogicalTypeID() == common::LogicalTypeID::SERIAL) { @@ -106,18 +107,19 @@ uint64_t NodeGroup::append(const std::vector& columnVectors, serialSkip++; continue; } - KU_ASSERT(chunk->getDataType() == columnVectors[i - serialSkip]->dataType); - chunk->append(columnVectors[i - serialSkip]); + KU_ASSERT((i - serialSkip) < columnVectors.size()); + auto columnVector = columnVectors[i - serialSkip]; + chunk->append(columnVector, selVector); } - columnState->selVector->selectedSize = originalSize; + selVector.selectedSize = originalSize; numRows += numValuesToAppendInChunk; return numValuesToAppendInChunk; } -offset_t NodeGroup::append(NodeGroup* other, offset_t offsetInOtherNodeGroup) { +offset_t ChunkedNodeGroup::append(ChunkedNodeGroup* other, offset_t offsetInOtherNodeGroup) { KU_ASSERT(other->chunks.size() == chunks.size()); - auto numNodesToAppend = std::min( - other->numRows - offsetInOtherNodeGroup, StorageConstants::NODE_GROUP_SIZE - numRows); + auto numNodesToAppend = std::min(other->numRows - offsetInOtherNodeGroup, + StorageConstants::NODE_GROUP_SIZE - numRows); for (auto i = 0u; i < chunks.size(); i++) { chunks[i]->append(other->chunks[i].get(), offsetInOtherNodeGroup, numNodesToAppend); } @@ -125,38 +127,43 @@ offset_t NodeGroup::append(NodeGroup* other, offset_t offsetInOtherNodeGroup) { return numNodesToAppend; } -void NodeGroup::write(DataChunk* dataChunk, vector_idx_t offsetVectorIdx) { - KU_ASSERT(dataChunk->getNumValueVectors() == chunks.size() + 1); - auto offsetVector = dataChunk->getValueVector(offsetVectorIdx).get(); - vector_idx_t vectorIdx = 0, chunkIdx = 0; - for (auto i = 0u; i < dataChunk->getNumValueVectors(); i++) { - if (i == offsetVectorIdx) { - vectorIdx++; +void ChunkedNodeGroup::write(const std::vector>& data, + column_id_t offsetColumnID) { + KU_ASSERT(data.size() == chunks.size() + 1); + auto& offsetChunk = data[offsetColumnID]; + column_id_t columnID = 0, chunkIdx = 0; + for (auto i = 0u; i < data.size(); i++) { + if (i == offsetColumnID) { + columnID++; continue; } - KU_ASSERT(vectorIdx < dataChunk->getNumValueVectors()); - writeToColumnChunk(chunkIdx, vectorIdx, dataChunk, offsetVector); + KU_ASSERT(columnID < data.size()); + writeToColumnChunk(chunkIdx, columnID, data, *offsetChunk); chunkIdx++; - vectorIdx++; + columnID++; } - numRows += offsetVector->state->selVector->selectedSize; + numRows += offsetChunk->getNumValues(); } -void NodeGroup::finalize(uint64_t nodeGroupIdx_) { +void ChunkedNodeGroup::write(const ChunkedNodeGroup& data, column_id_t offsetColumnID) { + write(data.chunks, offsetColumnID); +} + +void ChunkedNodeGroup::finalize(uint64_t nodeGroupIdx_) { nodeGroupIdx = nodeGroupIdx_; for (auto i = 0u; i < chunks.size(); i++) { chunks[i]->finalize(); } } -CSRHeaderChunks::CSRHeaderChunks(bool enableCompression, uint64_t capacity) { +ChunkedCSRHeader::ChunkedCSRHeader(bool enableCompression, uint64_t capacity) { offset = ColumnChunkFactory::createColumnChunk(*LogicalType::UINT64(), enableCompression, capacity); length = ColumnChunkFactory::createColumnChunk(*LogicalType::UINT64(), enableCompression, capacity); } -offset_t CSRHeaderChunks::getStartCSROffset(offset_t nodeOffset) const { +offset_t ChunkedCSRHeader::getStartCSROffset(offset_t nodeOffset) const { if (nodeOffset == 0 || offset->getNumValues() == 0) { return 0; } @@ -164,7 +171,7 @@ offset_t CSRHeaderChunks::getStartCSROffset(offset_t nodeOffset) const { nodeOffset >= offset->getNumValues() ? (offset->getNumValues() - 1) : (nodeOffset - 1)); } -offset_t CSRHeaderChunks::getEndCSROffset(offset_t nodeOffset) const { +offset_t ChunkedCSRHeader::getEndCSROffset(offset_t nodeOffset) const { if (offset->getNumValues() == 0) { return 0; } @@ -172,16 +179,16 @@ offset_t CSRHeaderChunks::getEndCSROffset(offset_t nodeOffset) const { nodeOffset >= offset->getNumValues() ? (offset->getNumValues() - 1) : nodeOffset); } -length_t CSRHeaderChunks::getCSRLength(offset_t nodeOffset) const { +length_t ChunkedCSRHeader::getCSRLength(offset_t nodeOffset) const { return nodeOffset >= length->getNumValues() ? 0 : length->getValue(nodeOffset); } -CSRNodeGroup::CSRNodeGroup( - const std::vector>& columnTypes, bool enableCompression) +ChunkedCSRNodeGroup::ChunkedCSRNodeGroup(const std::vector& columnTypes, + bool enableCompression) // By default, initialize all column chunks except for the csrOffsetChunk to empty, as they // should be resized after csr offset calculation (e.g., during RelBatchInsert). - : NodeGroup{columnTypes, enableCompression, 0 /* capacity */} { - csrHeaderChunks = CSRHeaderChunks(enableCompression); + : ChunkedNodeGroup{columnTypes, enableCompression, 0 /* capacity */} { + csrHeader = ChunkedCSRHeader(enableCompression); } } // namespace storage diff --git a/src/storage/store/chunked_node_group_collection.cpp b/src/storage/store/chunked_node_group_collection.cpp new file mode 100644 index 00000000000..e21facf5a3f --- /dev/null +++ b/src/storage/store/chunked_node_group_collection.cpp @@ -0,0 +1,51 @@ +#include "storage/store/chunked_node_group_collection.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace storage { + +void ChunkedNodeGroupCollection::append(const std::vector& vectors, + const SelectionVector& selVector) { + if (chunkedGroups.empty()) { + chunkedGroups.push_back( + std::make_unique(types, false /*enableCompression*/, CHUNK_CAPACITY)); + } + auto numRowsToAppend = selVector.selectedSize; + row_idx_t numRowsAppended = 0; + SelectionVector tmpSelVector(numRowsToAppend); + while (numRowsAppended < numRowsToAppend) { + auto& lastChunkedGroup = chunkedGroups.back(); + auto numRowsToAppendInGroup = std::min(numRowsToAppend - numRowsAppended, + static_cast(CHUNK_CAPACITY - lastChunkedGroup->getNumRows())); + auto tmpSelVectorBuffer = tmpSelVector.getMultableBuffer(); + for (auto i = 0u; i < numRowsToAppendInGroup; i++) { + tmpSelVectorBuffer[i] = selVector.selectedPositions[numRowsAppended + i]; + } + tmpSelVector.setToFiltered(numRowsToAppendInGroup); + lastChunkedGroup->append(vectors, tmpSelVector, numRowsToAppendInGroup); + if (lastChunkedGroup->getNumRows() == CHUNK_CAPACITY) { + chunkedGroups.push_back(std::make_unique(types, + false /*enableCompression*/, CHUNK_CAPACITY)); + } + numRowsAppended += numRowsToAppendInGroup; + } +} + +void ChunkedNodeGroupCollection::merge(std::unique_ptr chunkedGroup) { + KU_ASSERT(chunkedGroup->getNumColumns() == types.size()); + for (auto i = 0u; i < chunkedGroup->getNumColumns(); i++) { + KU_ASSERT(chunkedGroup->getColumnChunk(i).getDataType() == types[i]); + } + chunkedGroups.push_back(std::move(chunkedGroup)); +} + +void ChunkedNodeGroupCollection::merge(ChunkedNodeGroupCollection& other) { + chunkedGroups.reserve(chunkedGroups.size() + other.chunkedGroups.size()); + for (auto& chunkedGroup : other.chunkedGroups) { + merge(std::move(chunkedGroup)); + } +} + +} // namespace storage +} // namespace kuzu diff --git a/src/storage/store/column.cpp b/src/storage/store/column.cpp index e9e78bfa7f6..776f6032e58 100644 --- a/src/storage/store/column.cpp +++ b/src/storage/store/column.cpp @@ -8,10 +8,10 @@ #include "storage/stats/property_statistics.h" #include "storage/storage_utils.h" #include "storage/store/column_chunk.h" +#include "storage/store/list_column.h" #include "storage/store/null_column.h" #include "storage/store/string_column.h" #include "storage/store/struct_column.h" -#include "storage/store/var_list_column.h" #include "transaction/transaction.h" #include @@ -122,9 +122,10 @@ class SerialColumn final : public Column { } } - bool canCommitInPlace(Transaction* /*transaction*/, node_group_idx_t /*nodeGroupIdx*/, - LocalVectorCollection* /*localChunk*/, const offset_to_row_idx_t& /*insertInfo*/, + bool canCommitInPlace(Transaction*, node_group_idx_t, const ChunkCollection&, + const offset_to_row_idx_t&, const ChunkCollection&, const offset_to_row_idx_t& updateInfo) override { + (void)updateInfo; // Avoid unused parameter warnings during release build. KU_ASSERT(updateInfo.empty()); return true; } @@ -139,8 +140,11 @@ class SerialColumn final : public Column { } void commitLocalChunkInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* /*localChunk*/, const offset_to_row_idx_t& insertInfo, + const ChunkCollection&, const offset_to_row_idx_t& insertInfo, const ChunkCollection&, const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) override { + // Avoid unused parameter warnings during release build. + (void)updateInfo; + (void)deleteInfo; KU_ASSERT(updateInfo.empty() && deleteInfo.empty()); auto chunkMeta = metadataDA->get(nodeGroupIdx, transaction->getType()); auto numValues = chunkMeta.numValues; @@ -156,9 +160,13 @@ class SerialColumn final : public Column { } void commitLocalChunkOutOfPlace(Transaction* /*transaction*/, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* /*localChunk*/, bool isNewNodeGroup, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo, + bool isNewNodeGroup, const ChunkCollection&, const offset_to_row_idx_t& insertInfo, + const ChunkCollection&, const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) override { + // Avoid unused parameter warnings during release build. + (void)isNewNodeGroup; + (void)updateInfo; + (void)deleteInfo; KU_ASSERT(isNewNodeGroup && updateInfo.empty() && deleteInfo.empty()); // Only when a new node group is created, we need to commit out of place. auto numValues = 0u; @@ -198,9 +206,9 @@ class SerialColumn final : public Column { InternalIDColumn::InternalIDColumn(std::string name, const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, - transaction::Transaction* transaction, RWPropertyStats stats) + transaction::Transaction* transaction, RWPropertyStats stats, bool enableCompression) : Column{name, *LogicalType::INTERNAL_ID(), metaDAHeaderInfo, dataFH, metadataFH, bufferManager, - wal, transaction, stats, false /* enableCompression */}, + wal, transaction, stats, enableCompression, false /*requireNullColumn*/}, commonTableID{INVALID_TABLE_ID} {} void InternalIDColumn::populateCommonTableID(ValueVector* resultVector) const { @@ -244,8 +252,8 @@ Column* Column::getNullColumn() { } // NOTE: This function should only be called on node tables. -void Column::batchLookup( - Transaction* transaction, const offset_t* nodeOffsets, size_t size, uint8_t* result) { +void Column::batchLookup(Transaction* transaction, const offset_t* nodeOffsets, size_t size, + uint8_t* result) { for (auto i = 0u; i < size; ++i) { auto nodeOffset = nodeOffsets[i]; auto [nodeGroupIdx, offsetInChunk] = @@ -276,15 +284,15 @@ void Column::scan(transaction::Transaction* transaction, node_group_idx_t nodeGr auto state = getReadState(transaction->getType(), nodeGroupIdx); auto pageCursor = getPageCursorForOffsetInGroup(startOffsetInGroup, state); auto numValuesToScan = endOffsetInGroup - startOffsetInGroup; - scanUnfiltered( - transaction, pageCursor, numValuesToScan, resultVector, state.metadata, offsetInVector); + scanUnfiltered(transaction, pageCursor, numValuesToScan, resultVector, state.metadata, + offsetInVector); } void Column::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, ColumnChunk* columnChunk, offset_t startOffset, offset_t endOffset) { if (nullColumn) { - nullColumn->scan( - transaction, nodeGroupIdx, columnChunk->getNullChunk(), startOffset, endOffset); + nullColumn->scan(transaction, nodeGroupIdx, columnChunk->getNullChunk(), startOffset, + endOffset); } if (nodeGroupIdx >= metadataDA->getNumElements(transaction->getType())) { columnChunk->setNumValues(0); @@ -307,8 +315,8 @@ void Column::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, Colum } KU_ASSERT((numValuesToScan + startOffset) <= chunkMetadata.numValues); while (numValuesScanned < numValuesToScan) { - auto numValuesToReadInPage = std::min( - numValuesPerPage - cursor.elemPosInPage, numValuesToScan - numValuesScanned); + auto numValuesToReadInPage = std::min(numValuesPerPage - cursor.elemPosInPage, + numValuesToScan - numValuesScanned); KU_ASSERT(isPageIdxValid(cursor.pageIdx, chunkMetadata)); readFromPage(transaction, cursor.pageIdx, [&](uint8_t* frame) -> void { readToPageFunc(frame, cursor, columnChunk->getData(), numValuesScanned, @@ -340,8 +348,8 @@ void Column::scan(Transaction* transaction, const ReadState& state, offset_t sta } } -void Column::scanInternal( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void Column::scanInternal(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { auto startNodeOffset = nodeIDVector->readNodeOffset(0); KU_ASSERT(startNodeOffset % DEFAULT_VECTOR_CAPACITY == 0); // TODO: replace with state @@ -406,16 +414,16 @@ void Column::scanFiltered(Transaction* transaction, PageCursor& pageCursor, } } -void Column::lookup( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void Column::lookup(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { if (nullColumn) { nullColumn->lookup(transaction, nodeIDVector, resultVector); } lookupInternal(transaction, nodeIDVector, resultVector); } -void Column::lookupInternal( - transaction::Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void Column::lookupInternal(transaction::Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { for (auto i = 0ul; i < nodeIDVector->state->selVector->selectedSize; i++) { auto pos = nodeIDVector->state->selVector->selectedPositions[i]; if (nodeIDVector->isNull(pos)) { @@ -433,13 +441,13 @@ void Column::lookupValue(transaction::Transaction* transaction, offset_t nodeOff auto chunkMeta = metadataDA->get(nodeGroupIdx, transaction->getType()); KU_ASSERT(isPageIdxValid(cursor.pageIdx, chunkMeta)); readFromPage(transaction, cursor.pageIdx, [&](uint8_t* frame) -> void { - readToVectorFunc( - frame, cursor, resultVector, posInVector, 1 /* numValuesToRead */, chunkMeta.compMeta); + readToVectorFunc(frame, cursor, resultVector, posInVector, 1 /* numValuesToRead */, + chunkMeta.compMeta); }); } -void Column::readFromPage( - Transaction* transaction, page_idx_t pageIdx, const std::function& func) { +void Column::readFromPage(Transaction* transaction, page_idx_t pageIdx, + const std::function& func) { // For constant compression, call read on a nullptr since there is no data on disk and // decompression only requires metadata if (pageIdx == INVALID_PAGE_IDX) { @@ -467,6 +475,7 @@ static bool sanityCheckForWrites(const ColumnChunkMetadata& metadata, const Logi void Column::append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) { KU_ASSERT(enableCompression == columnChunk->isCompressionEnabled()); + KU_ASSERT(columnChunk->sanityCheck()); // Main column chunk. auto preScanMetadata = columnChunk->getMetadataToFlush(); auto startPageIdx = dataFH->addNewPages(preScanMetadata.numPages); @@ -485,8 +494,8 @@ void Column::write(node_group_idx_t nodeGroupIdx, offset_t offsetInChunk, bool isNull = vectorToWriteFrom->isNull(posInVectorToWriteFrom); auto chunkMeta = metadataDA->get(nodeGroupIdx, TransactionType::WRITE); if (!isNull) { - writeValue( - chunkMeta, nodeGroupIdx, offsetInChunk, vectorToWriteFrom, posInVectorToWriteFrom); + writeValue(chunkMeta, nodeGroupIdx, offsetInChunk, vectorToWriteFrom, + posInVectorToWriteFrom); } if (offsetInChunk >= chunkMeta.numValues) { chunkMeta.numValues = offsetInChunk + 1; @@ -500,8 +509,8 @@ void Column::writeValue(const ColumnChunkMetadata& chunkMeta, node_group_idx_t n updatePageWithCursor( getPageCursorForOffset(TransactionType::WRITE, nodeGroupIdx, offsetInChunk), [&](auto frame, auto posInPage) { - writeFromVectorFunc( - frame, posInPage, vectorToWriteFrom, posInVectorToWriteFrom, chunkMeta.compMeta); + writeFromVectorFunc(frame, posInPage, vectorToWriteFrom, posInVectorToWriteFrom, + chunkMeta.compMeta); }); } @@ -533,8 +542,8 @@ void Column::writeValues(ReadState& state, common::offset_t dstOffset, const uin } } -offset_t Column::appendValues( - node_group_idx_t nodeGroupIdx, const uint8_t* data, offset_t numValues) { +offset_t Column::appendValues(node_group_idx_t nodeGroupIdx, const uint8_t* data, + offset_t numValues) { auto state = getReadState(TransactionType::WRITE, nodeGroupIdx); auto startOffset = state.metadata.numValues; auto numPages = dataFH->getNumPages(); @@ -552,8 +561,8 @@ PageCursor Column::getPageCursorForOffsetInGroup(offset_t offsetInChunk, const R return pageCursor; } -void Column::updatePageWithCursor( - PageCursor cursor, const std::function& writeOp) { +void Column::updatePageWithCursor(PageCursor cursor, + const std::function& writeOp) { bool insertingNewPage = false; if (cursor.pageIdx == INVALID_PAGE_IDX) { return writeOp(nullptr, cursor.elemPosInPage); @@ -566,48 +575,60 @@ void Column::updatePageWithCursor( *wal, [&](auto frame) { writeOp(frame, cursor.elemPosInPage); }); } -Column::ReadState Column::getReadState( - TransactionType transactionType, node_group_idx_t nodeGroupIdx) const { +Column::ReadState Column::getReadState(TransactionType transactionType, + node_group_idx_t nodeGroupIdx) const { auto metadata = metadataDA->get(nodeGroupIdx, transactionType); return {metadata, metadata.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)}; } +void Column::prepareCommit() { + metadataDA->prepareCommit(); + if (nullColumn) { + nullColumn->prepareCommit(); + } +} + void Column::prepareCommitForChunk(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localColumnChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) { + const ChunkCollection& localInsertChunks, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo, + const offset_set_t& deleteInfo) { auto currentNumNodeGroups = metadataDA->getNumElements(transaction->getType()); auto isNewNodeGroup = nodeGroupIdx >= currentNumNodeGroups; if (isNewNodeGroup) { // If this is a new node group, updateInfo should be empty. We should perform out-of-place // commit with a new column chunk. - commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, localColumnChunk, isNewNodeGroup, - insertInfo, updateInfo, deleteInfo); + commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, localInsertChunks, + insertInfo, localUpdateChunks, updateInfo, deleteInfo); } else { bool didInPlaceCommit = false; // If this is not a new node group, we should first check if we can perform in-place commit. - if (canCommitInPlace(transaction, nodeGroupIdx, localColumnChunk, insertInfo, updateInfo)) { - commitLocalChunkInPlace( - transaction, nodeGroupIdx, localColumnChunk, insertInfo, updateInfo, deleteInfo); + if (canCommitInPlace(transaction, nodeGroupIdx, localInsertChunks, insertInfo, + localUpdateChunks, updateInfo)) { + commitLocalChunkInPlace(transaction, nodeGroupIdx, localInsertChunks, insertInfo, + localUpdateChunks, updateInfo, deleteInfo); didInPlaceCommit = true; } else { - commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, localColumnChunk, isNewNodeGroup, - insertInfo, updateInfo, deleteInfo); + commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, localInsertChunks, + insertInfo, localUpdateChunks, updateInfo, deleteInfo); } // TODO(Guodong/Ben): The logic here on NullColumn is confusing as out-of-place commits and // in-place commits handle it differently. See if we can unify them. if (nullColumn) { // Uses functions written for the null chunk which only access the localColumnChunk's // null information - if (nullColumn->canCommitInPlace( - transaction, nodeGroupIdx, localColumnChunk, insertInfo, updateInfo)) { - nullColumn->commitLocalChunkInPlace(transaction, nodeGroupIdx, localColumnChunk, - insertInfo, updateInfo, deleteInfo); + if (nullColumn->canCommitInPlace(transaction, nodeGroupIdx, + getNullChunkCollection(localInsertChunks), insertInfo, + getNullChunkCollection(localUpdateChunks), updateInfo)) { + nullColumn->commitLocalChunkInPlace(transaction, nodeGroupIdx, + getNullChunkCollection(localInsertChunks), insertInfo, + getNullChunkCollection(localUpdateChunks), updateInfo, deleteInfo); } else if (didInPlaceCommit) { // Out-of-place commits also commit the null chunk out of place, // so we only need to do a separate out of place commit for the null chunk if the // main chunk did an in-place commit. - nullColumn->commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, localColumnChunk, - isNewNodeGroup, insertInfo, updateInfo, deleteInfo); + nullColumn->commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, + getNullChunkCollection(localInsertChunks), insertInfo, + getNullChunkCollection(localUpdateChunks), updateInfo, deleteInfo); } } } @@ -615,11 +636,12 @@ void Column::prepareCommitForChunk(Transaction* transaction, node_group_idx_t no void Column::prepareCommitForChunk(Transaction* transaction, node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, offset_t startSrcOffset) { + metadataDA->prepareCommit(); auto currentNumNodeGroups = metadataDA->getNumElements(transaction->getType()); auto isNewNodeGroup = nodeGroupIdx >= currentNumNodeGroups; if (isNewNodeGroup) { - commitColumnChunkOutOfPlace( - transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk, startSrcOffset); + commitColumnChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk, + startSrcOffset); } else { bool didInPlaceCommit = false; // If this is not a new node group, we should first check if we can perform in-place commit. @@ -627,14 +649,14 @@ void Column::prepareCommitForChunk(Transaction* transaction, node_group_idx_t no commitColumnChunkInPlace(nodeGroupIdx, dstOffsets, chunk, startSrcOffset); didInPlaceCommit = true; } else { - commitColumnChunkOutOfPlace( - transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk, startSrcOffset); + commitColumnChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, + chunk, startSrcOffset); } if (nullColumn) { - if (nullColumn->canCommitInPlace( - transaction, nodeGroupIdx, dstOffsets, chunk->getNullChunk(), startSrcOffset)) { - nullColumn->commitColumnChunkInPlace( - nodeGroupIdx, dstOffsets, chunk->getNullChunk(), startSrcOffset); + if (nullColumn->canCommitInPlace(transaction, nodeGroupIdx, dstOffsets, + chunk->getNullChunk(), startSrcOffset)) { + nullColumn->commitColumnChunkInPlace(nodeGroupIdx, dstOffsets, + chunk->getNullChunk(), startSrcOffset); } else if (didInPlaceCommit) { nullColumn->commitColumnChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk->getNullChunk(), startSrcOffset); @@ -643,8 +665,8 @@ void Column::prepareCommitForChunk(Transaction* transaction, node_group_idx_t no } } -bool Column::isInsertionsOutOfPagesCapacity( - const ColumnChunkMetadata& metadata, const offset_to_row_idx_t& insertInfo) { +bool Column::isInsertionsOutOfPagesCapacity(const ColumnChunkMetadata& metadata, + const offset_to_row_idx_t& insertInfo) { auto maxOffset = 0u; for (auto& [offset, rowIdx] : insertInfo) { if (offset > maxOffset) { @@ -654,8 +676,8 @@ bool Column::isInsertionsOutOfPagesCapacity( return isMaxOffsetOutOfPagesCapacity(metadata, maxOffset); } -bool Column::isMaxOffsetOutOfPagesCapacity( - const ColumnChunkMetadata& metadata, offset_t maxOffset) { +bool Column::isMaxOffsetOutOfPagesCapacity(const ColumnChunkMetadata& metadata, + offset_t maxOffset) { if (metadata.compMeta.compression != CompressionType::CONSTANT && (metadata.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType) * metadata.numPages) <= (maxOffset + 1)) { @@ -667,24 +689,21 @@ bool Column::isMaxOffsetOutOfPagesCapacity( } bool Column::checkUpdateInPlace(const ColumnChunkMetadata& metadata, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo) { + const ChunkCollection& localChunks, const offset_to_row_idx_t& writeInfo) { std::vector rowIdxesToRead; - for (auto& [_, rowIdx] : updateInfo) { - rowIdxesToRead.push_back(rowIdx); - } - for (auto& [_, rowIdx] : insertInfo) { + for (auto& [_, rowIdx] : writeInfo) { rowIdxesToRead.push_back(rowIdx); } std::sort(rowIdxesToRead.begin(), rowIdxesToRead.end()); for (auto rowIdx : rowIdxesToRead) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - if (localVector->getVector()->isNull(offsetInVector)) { + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + if (localChunks[chunkIdx]->getNullChunk() != nullptr && + localChunks[chunkIdx]->getNullChunk()->isNull(offsetInLocalChunk)) { continue; } - if (!metadata.compMeta.canUpdateInPlace( - localVector->getVector()->getData(), offsetInVector, dataType.getPhysicalType())) { + if (!metadata.compMeta.canUpdateInPlace(localChunks[chunkIdx]->getData(), + offsetInLocalChunk, dataType.getPhysicalType())) { return false; } } @@ -692,8 +711,8 @@ bool Column::checkUpdateInPlace(const ColumnChunkMetadata& metadata, } bool Column::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo) { + const ChunkCollection& localInsertChunks, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo) { auto metadata = getMetadata(nodeGroupIdx, transaction->getType()); if (isInsertionsOutOfPagesCapacity(metadata, insertInfo)) { return false; @@ -701,7 +720,8 @@ bool Column::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGro if (metadata.compMeta.canAlwaysUpdateInPlace()) { return true; } - return checkUpdateInPlace(metadata, localChunk, insertInfo, updateInfo); + return checkUpdateInPlace(metadata, localInsertChunks, insertInfo) && + checkUpdateInPlace(metadata, localUpdateChunks, updateInfo); } bool Column::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, @@ -716,8 +736,8 @@ bool Column::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGro return true; } for (auto i = 0u; i < dstOffsets.size(); i++) { - if (!metadata.compMeta.canUpdateInPlace( - chunk->getData(), srcOffset + i, dataType.getPhysicalType())) { + if (!metadata.compMeta.canUpdateInPlace(chunk->getData(), srcOffset + i, + dataType.getPhysicalType())) { return false; } } @@ -725,10 +745,11 @@ bool Column::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGro } void Column::commitLocalChunkInPlace(Transaction* /*transaction*/, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo, const offset_set_t& /*deleteInfo*/) { - applyLocalChunkToColumn(nodeGroupIdx, localChunk, updateInfo); - applyLocalChunkToColumn(nodeGroupIdx, localChunk, insertInfo); + const ChunkCollection& localInsertChunks, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo, + const offset_set_t& /*deleteInfo*/) { + applyLocalChunkToColumn(nodeGroupIdx, localUpdateChunks, updateInfo); + applyLocalChunkToColumn(nodeGroupIdx, localInsertChunks, insertInfo); } std::unique_ptr Column::getEmptyChunkForCommit(uint64_t capacity) { @@ -736,20 +757,21 @@ std::unique_ptr Column::getEmptyChunkForCommit(uint64_t capacity) { } void Column::commitLocalChunkOutOfPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, bool isNewNodeGroup, const offset_to_row_idx_t& insertInfo, + bool isNewNodeGroup, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) { auto columnChunk = getEmptyChunkForCommit(common::StorageConstants::NODE_GROUP_SIZE); if (isNewNodeGroup) { KU_ASSERT(updateInfo.empty() && deleteInfo.empty()); // Apply inserts from the local chunk. - applyLocalChunkToColumnChunk(localChunk, columnChunk.get(), insertInfo); + applyLocalChunkToColumnChunk(localInsertChunks, columnChunk.get(), insertInfo); } else { // First, scan the whole column chunk from persistent storage. scan(transaction, nodeGroupIdx, columnChunk.get()); // Then, apply updates from the local chunk. - applyLocalChunkToColumnChunk(localChunk, columnChunk.get(), updateInfo); + applyLocalChunkToColumnChunk(localUpdateChunks, columnChunk.get(), updateInfo); // Lastly, apply inserts from the local chunk. - applyLocalChunkToColumnChunk(localChunk, columnChunk.get(), insertInfo); + applyLocalChunkToColumnChunk(localInsertChunks, columnChunk.get(), insertInfo); if (columnChunk->getNullChunk()) { // Set nulls based on deleteInfo. for (auto offsetInChunk : deleteInfo) { @@ -758,6 +780,7 @@ void Column::commitLocalChunkOutOfPlace(Transaction* transaction, node_group_idx } } columnChunk->finalize(); + KU_ASSERT(columnChunk->sanityCheck()); append(columnChunk.get(), nodeGroupIdx); } @@ -776,41 +799,44 @@ void Column::commitColumnChunkOutOfPlace(Transaction* transaction, node_group_id append(chunk, nodeGroupIdx); } else { auto chunkMeta = getMetadata(nodeGroupIdx, transaction->getType()); - auto maxDstOffset = getMaxOffset(dstOffsets); - if (maxDstOffset < chunkMeta.numValues) { - // TODO(Guodong): Should consider caching the scanned column chunk to avoid redundant - // scans in the same transaction. - auto columnChunk = getEmptyChunkForCommit(chunkMeta.numValues + dstOffsets.size()); - scan(transaction, nodeGroupIdx, columnChunk.get()); - for (auto i = 0u; i < dstOffsets.size(); i++) { - columnChunk->write(chunk, srcOffset + i, dstOffsets[i], 1 /* numValues */); - } - columnChunk->finalize(); - append(columnChunk.get(), nodeGroupIdx); - } else { - chunk->finalize(); - append(chunk, nodeGroupIdx); + // TODO(Guodong): Should consider caching the scanned column chunk to avoid redundant + // scans in the same transaction. + auto columnChunk = + getEmptyChunkForCommit(1.5 * std::bit_ceil(chunkMeta.numValues + dstOffsets.size())); + scan(transaction, nodeGroupIdx, columnChunk.get()); + for (auto i = 0u; i < dstOffsets.size(); i++) { + columnChunk->write(chunk, srcOffset + i, dstOffsets[i], 1 /* numValues */); } + columnChunk->finalize(); + append(columnChunk.get(), nodeGroupIdx); } } -void Column::applyLocalChunkToColumnChunk(LocalVectorCollection* localChunk, - ColumnChunk* columnChunk, const std::map& updateInfo) { - for (auto& [offsetInChunk, rowIdx] : updateInfo) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - localVector->getVector()->state->selVector->selectedPositions[0] = offsetInVector; - columnChunk->write(localVector->getVector(), offsetInVector, offsetInChunk); +void Column::applyLocalChunkToColumnChunk(const ChunkCollection& localChunks, + ColumnChunk* columnChunk, const offset_to_row_idx_t& updateInfo) { + for (auto& [offsetInDstChunk, rowIdx] : updateInfo) { + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + columnChunk->write(localChunks[chunkIdx], offsetInLocalChunk, offsetInDstChunk, + 1 /* numValues */); } } void Column::applyLocalChunkToColumn(node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& updateInfo) { - for (auto& [offsetInChunk, rowIdx] : updateInfo) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - if (!localVector->getVector()->isNull(offsetInVector)) { - write(nodeGroupIdx, offsetInChunk, localVector->getVector(), offsetInVector); + const ChunkCollection& localChunks, const offset_to_row_idx_t& updateInfo) { + for (auto& [offsetInDstChunk, rowIdx] : updateInfo) { + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + if (!localChunks[chunkIdx]->getNullChunk()->isNull(offsetInLocalChunk)) { + write(nodeGroupIdx, offsetInDstChunk, localChunks[chunkIdx], offsetInLocalChunk, + 1 /*numValues*/); + } else { + auto chunkMeta = metadataDA->get(nodeGroupIdx, TransactionType::WRITE); + if (offsetInDstChunk >= chunkMeta.numValues) { + chunkMeta.numValues = offsetInDstChunk + 1; + KU_ASSERT(sanityCheckForWrites(chunkMeta, dataType)); + metadataDA->update(nodeGroupIdx, chunkMeta); + } } } } @@ -842,8 +868,8 @@ void Column::populateWithDefaultVal(Transaction* transaction, capacity *= CHUNK_RESIZE_RATIO; } if (capacity > columnChunk->getCapacity()) { - auto newColumnChunk = ColumnChunkFactory::createColumnChunk( - *dataType.copy(), enableCompression, capacity); + auto newColumnChunk = ColumnChunkFactory::createColumnChunk(*dataType.copy(), + enableCompression, capacity); newColumnChunk->populateWithDefaultVal(defaultValueVector); newColumnChunk->setNumValues(chunkMeta.numValues); append(newColumnChunk.get(), i); @@ -854,12 +880,20 @@ void Column::populateWithDefaultVal(Transaction* transaction, } } -PageCursor Column::getPageCursorForOffset( - TransactionType transactionType, node_group_idx_t nodeGroupIdx, offset_t offsetInChunk) { +PageCursor Column::getPageCursorForOffset(TransactionType transactionType, + node_group_idx_t nodeGroupIdx, offset_t offsetInChunk) { auto state = getReadState(transactionType, nodeGroupIdx); return getPageCursorForOffsetInGroup(offsetInChunk, state); } +ChunkCollection Column::getNullChunkCollection(const ChunkCollection& chunkCollection) { + ChunkCollection nullChunkCollection; + for (const auto& chunk : chunkCollection) { + nullChunkCollection.push_back(chunk->getNullChunk()); + } + return nullChunkCollection; +} + std::unique_ptr ColumnFactory::createColumn(std::string name, LogicalType dataType, const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, BufferManager* bufferManager, WAL* wal, transaction::Transaction* transaction, @@ -884,23 +918,23 @@ std::unique_ptr ColumnFactory::createColumn(std::string name, LogicalTyp case LogicalTypeID::TIMESTAMP_NS: case LogicalTypeID::TIMESTAMP_SEC: case LogicalTypeID::TIMESTAMP_TZ: - case LogicalTypeID::INTERVAL: - case LogicalTypeID::FIXED_LIST: { + case LogicalTypeID::INTERVAL: { return std::make_unique(name, std::move(dataType), metaDAHeaderInfo, dataFH, metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); } case LogicalTypeID::INTERNAL_ID: { return std::make_unique(name, metaDAHeaderInfo, dataFH, metadataFH, - bufferManager, wal, transaction, propertyStatistics); + bufferManager, wal, transaction, propertyStatistics, enableCompression); } case LogicalTypeID::BLOB: case LogicalTypeID::STRING: { return std::make_unique(name, std::move(dataType), metaDAHeaderInfo, dataFH, metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); } + case LogicalTypeID::ARRAY: case LogicalTypeID::MAP: - case LogicalTypeID::VAR_LIST: { - return std::make_unique(name, std::move(dataType), metaDAHeaderInfo, dataFH, + case LogicalTypeID::LIST: { + return std::make_unique(name, std::move(dataType), metaDAHeaderInfo, dataFH, metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); } case LogicalTypeID::UNION: @@ -910,8 +944,8 @@ std::unique_ptr ColumnFactory::createColumn(std::string name, LogicalTyp metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); } case LogicalTypeID::SERIAL: { - return std::make_unique( - name, metaDAHeaderInfo, dataFH, metadataFH, bufferManager, wal, transaction); + return std::make_unique(name, metaDAHeaderInfo, dataFH, metadataFH, + bufferManager, wal, transaction); } default: { KU_UNREACHABLE; diff --git a/src/storage/store/column_chunk.cpp b/src/storage/store/column_chunk.cpp index 9beb2460f7b..0f64270cc27 100644 --- a/src/storage/store/column_chunk.cpp +++ b/src/storage/store/column_chunk.cpp @@ -1,11 +1,14 @@ #include "storage/store/column_chunk.h" +#include "common/data_chunk/sel_vector.h" #include "common/exception/copy.h" +#include "common/types/internal_id_t.h" +#include "common/types/types.h" #include "storage/compression/compression.h" #include "storage/storage_utils.h" +#include "storage/store/list_column_chunk.h" #include "storage/store/string_column_chunk.h" #include "storage/store/struct_column_chunk.h" -#include "storage/store/var_list_column_chunk.h" using namespace kuzu::common; @@ -15,20 +18,20 @@ namespace storage { ColumnChunkMetadata fixedSizedFlushBuffer(const uint8_t* buffer, uint64_t bufferSize, BMFileHandle* dataFH, page_idx_t startPageIdx, const ColumnChunkMetadata& metadata) { KU_ASSERT(dataFH->getNumPages() >= startPageIdx + metadata.numPages); - dataFH->getFileInfo()->writeFile( - buffer, bufferSize, startPageIdx * BufferPoolConstants::PAGE_4KB_SIZE); - return ColumnChunkMetadata( - startPageIdx, metadata.numPages, metadata.numValues, metadata.compMeta); + dataFH->getFileInfo()->writeFile(buffer, bufferSize, + startPageIdx * BufferPoolConstants::PAGE_4KB_SIZE); + return ColumnChunkMetadata(startPageIdx, metadata.numPages, metadata.numValues, + metadata.compMeta); } -ColumnChunkMetadata fixedSizedGetMetadata( - const uint8_t* /*buffer*/, uint64_t bufferSize, uint64_t /*capacity*/, uint64_t numValues) { +ColumnChunkMetadata fixedSizedGetMetadata(const uint8_t* /*buffer*/, uint64_t bufferSize, + uint64_t /*capacity*/, uint64_t numValues) { return ColumnChunkMetadata(INVALID_PAGE_IDX, ColumnChunk::getNumPagesForBytes(bufferSize), numValues, CompressionMetadata()); } -ColumnChunkMetadata booleanGetMetadata( - const uint8_t* /*buffer*/, uint64_t bufferSize, uint64_t /*capacity*/, uint64_t numValues) { +ColumnChunkMetadata booleanGetMetadata(const uint8_t* /*buffer*/, uint64_t bufferSize, + uint64_t /*capacity*/, uint64_t numValues) { return ColumnChunkMetadata(INVALID_PAGE_IDX, ColumnChunk::getNumPagesForBytes(bufferSize), numValues, CompressionMetadata(CompressionType::BOOLEAN_BITPACKING)); } @@ -80,8 +83,8 @@ class CompressedFlushBuffer { BufferPoolConstants::PAGE_4KB_SIZE, (startPageIdx + metadata.numPages - 1) * BufferPoolConstants::PAGE_4KB_SIZE); } - return ColumnChunkMetadata( - startPageIdx, metadata.numPages, metadata.numValues, metadata.compMeta); + return ColumnChunkMetadata(startPageIdx, metadata.numPages, metadata.numValues, + metadata.compMeta); } }; @@ -95,8 +98,8 @@ class GetCompressionMetadata { GetCompressionMetadata(const GetCompressionMetadata& other) = default; - ColumnChunkMetadata operator()( - const uint8_t* buffer, uint64_t /*bufferSize*/, uint64_t capacity, uint64_t numValues) { + ColumnChunkMetadata operator()(const uint8_t* buffer, uint64_t /*bufferSize*/, + uint64_t capacity, uint64_t numValues) { auto metadata = alg->getCompressionMetadata(buffer, numValues); auto numValuesPerPage = metadata.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType); auto numPages = capacity / numValuesPerPage + (capacity % numValuesPerPage == 0 ? 0 : 1); @@ -104,8 +107,8 @@ class GetCompressionMetadata { } }; -static std::shared_ptr getCompression( - const LogicalType& dataType, bool enableCompression) { +static std::shared_ptr getCompression(const LogicalType& dataType, + bool enableCompression) { if (!enableCompression) { return std::make_shared(dataType); } @@ -122,7 +125,8 @@ static std::shared_ptr getCompression( case PhysicalTypeID::INT8: { return std::make_shared>(); } - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: { return std::make_shared>(); } @@ -142,11 +146,10 @@ static std::shared_ptr getCompression( } } -ColumnChunk::ColumnChunk( - LogicalType dataType, uint64_t capacity, bool enableCompression, bool hasNullChunk) - : dataType{std::move(dataType)}, - numBytesPerValue{getDataTypeSizeInChunk(this->dataType)}, numValues{0}, - enableCompression(enableCompression) { +ColumnChunk::ColumnChunk(LogicalType dataType, uint64_t capacity, bool enableCompression, + bool hasNullChunk) + : dataType{std::move(dataType)}, numBytesPerValue{getDataTypeSizeInChunk(this->dataType)}, + numValues{0}, enableCompression(enableCompression) { if (hasNullChunk) { nullChunk = std::make_unique(capacity, enableCompression); } @@ -157,7 +160,7 @@ ColumnChunk::ColumnChunk( void ColumnChunk::initializeBuffer(offset_t capacity_) { numBytesPerValue = getDataTypeSizeInChunk(dataType); capacity = capacity_; - bufferSize = getBufferSize(); + bufferSize = getBufferSize(capacity); buffer = std::make_unique(bufferSize); if (nullChunk) { nullChunk->initializeBuffer(capacity_); @@ -178,7 +181,8 @@ void ColumnChunk::initializeFunction() { case PhysicalTypeID::INT32: case PhysicalTypeID::INT16: case PhysicalTypeID::INT8: - case PhysicalTypeID::VAR_LIST: + case PhysicalTypeID::INTERNAL_ID: + case PhysicalTypeID::LIST: case PhysicalTypeID::UINT64: case PhysicalTypeID::UINT32: case PhysicalTypeID::UINT16: @@ -200,76 +204,85 @@ void ColumnChunk::resetToEmpty() { if (nullChunk) { nullChunk->resetToEmpty(); } - memset(buffer.get(), 0, bufferSize); + KU_ASSERT(bufferSize == getBufferSize(capacity)); + memset(buffer.get(), 0x00, bufferSize); numValues = 0; } -void ColumnChunk::append(ValueVector* vector) { +void ColumnChunk::append(ValueVector* vector, const SelectionVector& selVector) { KU_ASSERT(vector->dataType.getPhysicalType() == dataType.getPhysicalType()); - copyVectorToBuffer(vector, numValues); - numValues += vector->state->selVector->selectedSize; + copyVectorToBuffer(vector, numValues, selVector); + numValues += selVector.selectedSize; } -void ColumnChunk::append( - ColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { +void ColumnChunk::append(ColumnChunk* other, offset_t startPosInOtherChunk, + uint32_t numValuesToAppend) { KU_ASSERT(other->dataType.getPhysicalType() == dataType.getPhysicalType()); if (nullChunk) { KU_ASSERT(nullChunk->getNumValues() == getNumValues()); nullChunk->append(other->nullChunk.get(), startPosInOtherChunk, numValuesToAppend); } + KU_ASSERT(numValues + numValuesToAppend <= capacity); memcpy(buffer.get() + numValues * numBytesPerValue, other->buffer.get() + startPosInOtherChunk * numBytesPerValue, numValuesToAppend * numBytesPerValue); numValues += numValuesToAppend; } -void ColumnChunk::write(ValueVector* vector, ValueVector* offsetsInChunk, bool isCSR) { - KU_ASSERT( - vector->dataType.getPhysicalType() == dataType.getPhysicalType() && - offsetsInChunk->dataType.getPhysicalType() == PhysicalTypeID::INT64 && - vector->state->selVector->selectedSize == offsetsInChunk->state->selVector->selectedSize); - auto offsets = (offset_t*)offsetsInChunk->getData(); - for (auto i = 0u; i < offsetsInChunk->state->selVector->selectedSize; i++) { - auto offsetInChunk = offsets[offsetsInChunk->state->selVector->selectedPositions[i]]; - KU_ASSERT(offsetInChunk < capacity); - if (!isCSR && !nullChunk->isNull(offsetInChunk)) { +void ColumnChunk::lookup(offset_t offsetInChunk, ValueVector& output, + sel_t posInOutputVector) const { + KU_ASSERT(offsetInChunk < capacity); + output.setNull(posInOutputVector, nullChunk->isNull(offsetInChunk)); + if (!output.isNull(posInOutputVector)) { + memcpy(output.getData() + posInOutputVector * numBytesPerValue, + buffer.get() + offsetInChunk * numBytesPerValue, numBytesPerValue); + } +} + +void ColumnChunk::write(ColumnChunk* chunk, ColumnChunk* dstOffsets, RelMultiplicity multiplicity) { + KU_ASSERT(chunk->dataType.getPhysicalType() == dataType.getPhysicalType() && + dstOffsets->getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID && + chunk->getNumValues() == dstOffsets->getNumValues()); + for (auto i = 0u; i < dstOffsets->getNumValues(); i++) { + auto dstOffset = dstOffsets->getValue(i); + KU_ASSERT(dstOffset < capacity); + if (multiplicity == RelMultiplicity::ONE && !nullChunk->isNull(dstOffset)) { throw CopyException(stringFormat("Node with offset: {} can only have one neighbour due " "to the MANY-ONE/ONE-ONE relationship constraint.", - offsetInChunk)); + dstOffset)); } - auto offsetInVector = vector->state->selVector->selectedPositions[i]; - if (!vector->isNull(offsetInVector)) { - memcpy(buffer.get() + offsetInChunk * numBytesPerValue, - vector->getData() + offsetInVector * numBytesPerValue, numBytesPerValue); - } - nullChunk->setNull(offsetInChunk, vector->isNull(offsetInVector)); - if (offsetInChunk >= numValues) { - numValues = offsetInChunk + 1; + if (!chunk->getNullChunk()->isNull(i)) { + memcpy(buffer.get() + dstOffset * numBytesPerValue, + chunk->getData() + i * numBytesPerValue, numBytesPerValue); } + nullChunk->setNull(dstOffset, chunk->getNullChunk()->isNull(i)); + numValues = dstOffset >= numValues ? dstOffset + 1 : numValues; } } // NOTE: This function is only called in LocalTable right now when performing out-of-place -// committing. VAR_LIST has a different logic for handling out-of-place committing as it has to +// committing. LIST has a different logic for handling out-of-place committing as it has to // be slided. However, this is unsafe, as this function can also be used for other purposes later. // Thus, an assertion is added at the first line. void ColumnChunk::write(ValueVector* vector, offset_t offsetInVector, offset_t offsetInChunk) { KU_ASSERT(dataType.getPhysicalType() != PhysicalTypeID::BOOL && - dataType.getPhysicalType() != PhysicalTypeID::VAR_LIST); + dataType.getPhysicalType() != PhysicalTypeID::LIST); nullChunk->setNull(offsetInChunk, vector->isNull(offsetInVector)); + if (offsetInChunk >= numValues) { + numValues = offsetInChunk + 1; + } if (!vector->isNull(offsetInVector)) { memcpy(buffer.get() + offsetInChunk * numBytesPerValue, vector->getData() + offsetInVector * numBytesPerValue, numBytesPerValue); } - if (offsetInChunk >= numValues) { - numValues = offsetInChunk + 1; - } } void ColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, offset_t dstOffsetInChunk, offset_t numValuesToCopy) { - KU_ASSERT(numValues >= (dstOffsetInChunk + numValuesToCopy)); KU_ASSERT(srcChunk->dataType.getPhysicalType() == dataType.getPhysicalType()); + if ((dstOffsetInChunk + numValuesToCopy) >= numValues) { + numValues = dstOffsetInChunk + numValuesToCopy; + } memcpy(buffer.get() + dstOffsetInChunk * numBytesPerValue, srcChunk->buffer.get() + srcOffsetInChunk * numBytesPerValue, numValuesToCopy * numBytesPerValue); @@ -288,8 +301,10 @@ void ColumnChunk::copy(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, offset_ } void ColumnChunk::resize(uint64_t newCapacity) { - capacity = newCapacity; - auto numBytesAfterResize = getBufferSize(); + if (newCapacity > capacity) { + capacity = newCapacity; + } + auto numBytesAfterResize = getBufferSize(newCapacity); if (numBytesAfterResize > bufferSize) { auto resizedBuffer = std::make_unique(numBytesAfterResize); memcpy(resizedBuffer.get(), buffer.get(), bufferSize); @@ -302,20 +317,23 @@ void ColumnChunk::resize(uint64_t newCapacity) { } void ColumnChunk::populateWithDefaultVal(ValueVector* defaultValueVector) { + // TODO(Guodong): don't set vector state to a new one. Default vector is shared across all + // operators on the pipeline so setting its state will affect others. + // You can only set state for vectors that is local to this class. defaultValueVector->setState(std::make_shared()); auto valPos = defaultValueVector->state->selVector->selectedPositions[0]; - defaultValueVector->state->selVector->resetSelectorToValuePosBufferWithSize( - DEFAULT_VECTOR_CAPACITY); + auto positionBuffer = defaultValueVector->state->selVector->getMultableBuffer(); for (auto i = 0u; i < defaultValueVector->state->selVector->selectedSize; i++) { - defaultValueVector->state->selVector->selectedPositions[i] = valPos; + positionBuffer[i] = valPos; } + defaultValueVector->state->selVector->setToFiltered(DEFAULT_VECTOR_CAPACITY); auto numValuesAppended = 0u; auto numValuesToPopulate = capacity; while (numValuesAppended < numValuesToPopulate) { auto numValuesToAppend = std::min(DEFAULT_VECTOR_CAPACITY, numValuesToPopulate - numValuesAppended); defaultValueVector->state->selVector->selectedSize = numValuesToAppend; - append(defaultValueVector); + append(defaultValueVector, *defaultValueVector->state->selVector); numValuesAppended += numValuesToAppend; } } @@ -330,19 +348,20 @@ offset_t ColumnChunk::getOffsetInBuffer(offset_t pos) const { return offsetInBuffer; } -void ColumnChunk::copyVectorToBuffer(ValueVector* vector, offset_t startPosInChunk) { +void ColumnChunk::copyVectorToBuffer(ValueVector* vector, offset_t startPosInChunk, + const SelectionVector& selVector) { auto bufferToWrite = buffer.get() + startPosInChunk * numBytesPerValue; + KU_ASSERT(startPosInChunk + selVector.selectedSize <= capacity); auto vectorDataToWriteFrom = vector->getData(); - if (vector->state->selVector->isUnfiltered()) { - memcpy(bufferToWrite, vectorDataToWriteFrom, - vector->state->selVector->selectedSize * numBytesPerValue); + if (selVector.isUnfiltered()) { + memcpy(bufferToWrite, vectorDataToWriteFrom, selVector.selectedSize * numBytesPerValue); // TODO(Guodong): Should be wrapped into nullChunk->append(vector); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { + for (auto i = 0u; i < selVector.selectedSize; i++) { nullChunk->setNull(startPosInChunk + i, vector->isNull(i)); } } else { - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - auto pos = vector->state->selVector->selectedPositions[i]; + for (auto i = 0u; i < selVector.selectedSize; i++) { + auto pos = selVector.selectedPositions[i]; // TODO(Guodong): Should be wrapped into nullChunk->append(vector); nullChunk->setNull(startPosInChunk + i, vector->isNull(pos)); memcpy(bufferToWrite, vectorDataToWriteFrom + pos * numBytesPerValue, numBytesPerValue); @@ -365,6 +384,13 @@ bool ColumnChunk::numValuesSanityCheck() const { return numValues <= capacity; } +bool ColumnChunk::sanityCheck() { + if (nullChunk) { + return nullChunk->sanityCheck() && numValuesSanityCheck(); + } + return numValues <= capacity; +} + ColumnChunkMetadata ColumnChunk::getMetadataToFlush() const { KU_ASSERT(numValues <= capacity); if (enableCompression) { @@ -374,47 +400,43 @@ ColumnChunkMetadata ColumnChunk::getMetadataToFlush() const { return ColumnChunkMetadata(INVALID_PAGE_IDX, 0, numValues, *constantMetadata); } } + KU_ASSERT(bufferSize == getBufferSize(capacity)); return getMetadataFunction(buffer.get(), bufferSize, capacity, numValues); } -ColumnChunkMetadata ColumnChunk::flushBuffer( - BMFileHandle* dataFH, page_idx_t startPageIdx, const ColumnChunkMetadata& metadata) { +ColumnChunkMetadata ColumnChunk::flushBuffer(BMFileHandle* dataFH, page_idx_t startPageIdx, + const ColumnChunkMetadata& metadata) { if (!metadata.compMeta.isConstant()) { + KU_ASSERT(bufferSize == getBufferSize(capacity)); return flushBufferFunction(buffer.get(), bufferSize, dataFH, startPageIdx, metadata); } return metadata; } -uint64_t ColumnChunk::getBufferSize() const { +uint64_t ColumnChunk::getBufferSize(uint64_t capacity_) const { switch (dataType.getLogicalTypeID()) { case LogicalTypeID::BOOL: { // 8 values per byte, and we need a buffer size which is a multiple of 8 bytes. - return ceil(capacity / 8.0 / 8.0) * 8; - } - case LogicalTypeID::FIXED_LIST: { - auto numElementsInAPage = - PageUtils::getNumElementsInAPage(numBytesPerValue, false /* hasNull */); - auto numPages = capacity / numElementsInAPage + (capacity % numElementsInAPage ? 1 : 0); - return BufferPoolConstants::PAGE_4KB_SIZE * numPages; + return ceil(capacity_ / 8.0 / 8.0) * 8; } default: { - return numBytesPerValue * capacity; + return numBytesPerValue * capacity_; } } } -void BoolColumnChunk::append(ValueVector* vector) { +void BoolColumnChunk::append(ValueVector* vector, const SelectionVector& selVector) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::BOOL); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - auto pos = vector->state->selVector->selectedPositions[i]; + for (auto i = 0u; i < selVector.selectedSize; i++) { + auto pos = selVector.selectedPositions[i]; nullChunk->setNull(numValues + i, vector->isNull(pos)); NullMask::setNull((uint64_t*)buffer.get(), numValues + i, vector->getValue(pos)); } - numValues += vector->state->selVector->selectedSize; + numValues += selVector.selectedSize; } -void BoolColumnChunk::append( - ColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { +void BoolColumnChunk::append(ColumnChunk* other, offset_t startPosInOtherChunk, + uint32_t numValuesToAppend) { NullMask::copyNullMask((uint64_t*)static_cast(other)->buffer.get(), startPosInOtherChunk, (uint64_t*)buffer.get(), numValues, numValuesToAppend); if (nullChunk) { @@ -423,23 +445,29 @@ void BoolColumnChunk::append( numValues += numValuesToAppend; } -void BoolColumnChunk::write( - ValueVector* valueVector, ValueVector* offsetInChunkVector, bool /*isCSR*/) { - KU_ASSERT(valueVector->dataType.getPhysicalType() == PhysicalTypeID::BOOL && - offsetInChunkVector->dataType.getPhysicalType() == PhysicalTypeID::INT64 && - valueVector->state->selVector->selectedSize == - offsetInChunkVector->state->selVector->selectedSize); - auto offsets = (offset_t*)offsetInChunkVector->getData(); - for (auto i = 0u; i < offsetInChunkVector->state->selVector->selectedSize; i++) { - auto offsetInChunk = offsets[offsetInChunkVector->state->selVector->selectedPositions[i]]; - KU_ASSERT(offsetInChunk < capacity); - auto offsetInVector = valueVector->state->selVector->selectedPositions[i]; - NullMask::setNull( - (uint64_t*)buffer.get(), offsetInChunk, valueVector->getValue(offsetInVector)); +void BoolColumnChunk::lookup(offset_t offsetInChunk, ValueVector& output, + sel_t posInOutputVector) const { + KU_ASSERT(offsetInChunk < capacity); + output.setNull(posInOutputVector, nullChunk->isNull(offsetInChunk)); + if (!output.isNull(posInOutputVector)) { + output.setValue(posInOutputVector, + NullMask::isNull((uint64_t*)buffer.get(), offsetInChunk)); + } +} + +void BoolColumnChunk::write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + RelMultiplicity /*multiplicity*/) { + KU_ASSERT(chunk->getDataType().getPhysicalType() == PhysicalTypeID::BOOL && + dstOffsets->getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID && + chunk->getNumValues() == dstOffsets->getNumValues()); + for (auto i = 0u; i < dstOffsets->getNumValues(); i++) { + auto dstOffset = dstOffsets->getValue(i); + KU_ASSERT(dstOffset < capacity); + NullMask::setNull((uint64_t*)buffer.get(), dstOffset, chunk->getValue(i)); if (nullChunk) { - nullChunk->write(valueVector, offsetInVector, offsetInChunk); + nullChunk->setNull(dstOffset, chunk->getNullChunk()->isNull(i)); } - numValues = offsetInChunk >= numValues ? offsetInChunk + 1 : numValues; + numValues = dstOffset >= numValues ? dstOffset + 1 : numValues; } } @@ -455,7 +483,13 @@ void BoolColumnChunk::write(ValueVector* vector, offset_t offsetInVector, offset void BoolColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, offset_t dstOffsetInChunk, offset_t numValuesToCopy) { - KU_ASSERT(numValues >= (dstOffsetInChunk + numValuesToCopy)); + if (nullChunk) { + nullChunk->write(srcChunk->getNullChunk(), srcOffsetInChunk, dstOffsetInChunk, + numValuesToCopy); + } + if ((dstOffsetInChunk + numValuesToCopy) >= numValues) { + numValues = dstOffsetInChunk + numValuesToCopy; + } NullMask::copyNullMask((uint64_t*)static_cast(srcChunk)->buffer.get(), srcOffsetInChunk, (uint64_t*)buffer.get(), dstOffsetInChunk, numValuesToCopy); } @@ -468,6 +502,7 @@ void NullColumnChunk::setNull(offset_t pos, bool isNull) { // TODO(Guodong): Better let NullColumnChunk also support `append` a vector. if (pos >= numValues) { numValues = pos + 1; + KU_ASSERT(numValues <= capacity); } } @@ -478,99 +513,79 @@ void NullColumnChunk::write(ValueVector* vector, offset_t offsetInVector, offset void NullColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, offset_t dstOffsetInChunk, offset_t numValuesToCopy) { - KU_ASSERT(numValues >= (dstOffsetInChunk + numValuesToCopy)); + if ((dstOffsetInChunk + numValuesToCopy) >= numValues) { + numValues = dstOffsetInChunk + numValuesToCopy; + } copyFromBuffer((uint64_t*)static_cast(srcChunk)->buffer.get(), srcOffsetInChunk, dstOffsetInChunk, numValuesToCopy); } -void NullColumnChunk::append( - ColumnChunk* other, offset_t startOffsetInOtherChunk, uint32_t numValuesToAppend) { +void NullColumnChunk::append(ColumnChunk* other, offset_t startOffsetInOtherChunk, + uint32_t numValuesToAppend) { copyFromBuffer((uint64_t*)static_cast(other)->buffer.get(), startOffsetInOtherChunk, numValues, numValuesToAppend); numValues += numValuesToAppend; } -class FixedListColumnChunk : public ColumnChunk { +class InternalIDColumnChunk final : public ColumnChunk { public: - FixedListColumnChunk(LogicalType dataType, uint64_t capacity, bool enableCompression) - : ColumnChunk(std::move(dataType), capacity, enableCompression, true /* hasNullChunk */) {} - - void append( - ColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) final { - auto otherChunk = (FixedListColumnChunk*)other; - if (nullChunk) { - nullChunk->append(otherChunk->nullChunk.get(), startPosInOtherChunk, numValuesToAppend); + // Physically, we only materialize offset of INTERNAL_ID, which is same as UINT64, + explicit InternalIDColumnChunk(uint64_t capacity, bool enableCompression) + : ColumnChunk(*LogicalType::INTERNAL_ID(), capacity, enableCompression), + commonTableID{INVALID_TABLE_ID} {} + + void append(ValueVector* vector, const common::SelectionVector& selVector) override { + switch (vector->dataType.getPhysicalType()) { + case PhysicalTypeID::INTERNAL_ID: { + copyVectorToBuffer(vector, numValues, selVector); + } break; + case PhysicalTypeID::INT64: { + copyInt64VectorToBuffer(vector, numValues, selVector); + } break; + default: { + KU_UNREACHABLE; } - // TODO(Guodong): This can be optimized to not copy one by one. - for (auto i = 0u; i < numValuesToAppend; i++) { - memcpy(buffer.get() + getOffsetInBuffer(numValues + i), - otherChunk->buffer.get() + getOffsetInBuffer(startPosInOtherChunk + i), - numBytesPerValue); - } - numValues += numValuesToAppend; - } - - void write(ValueVector* valueVector, ValueVector* offsetInChunkVector, bool /*isCSR*/) final { - KU_ASSERT(valueVector->dataType.getPhysicalType() == PhysicalTypeID::FIXED_LIST && - offsetInChunkVector->dataType.getPhysicalType() == PhysicalTypeID::INT64); - auto offsets = (offset_t*)offsetInChunkVector->getData(); - KU_ASSERT(valueVector->state->selVector->selectedSize == - offsetInChunkVector->state->selVector->selectedSize); - for (auto i = 0u; i < offsetInChunkVector->state->selVector->selectedSize; i++) { - auto offsetInChunk = - offsets[offsetInChunkVector->state->selVector->selectedPositions[i]]; - KU_ASSERT(offsetInChunk < capacity); - auto offsetInVector = valueVector->state->selVector->selectedPositions[i]; - nullChunk->write(valueVector, offsetInVector, offsetInChunk); - if (!valueVector->isNull(offsetInVector)) { - memcpy(buffer.get() + getOffsetInBuffer(offsetInChunk), - valueVector->getData() + offsetInVector * numBytesPerValue, numBytesPerValue); - } - numValues = offsetInChunk >= numValues ? offsetInChunk + 1 : numValues; } + numValues += selVector.selectedSize; } - void write(ValueVector* vector, offset_t offsetInVector, offset_t offsetInChunk) final { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::FIXED_LIST); - KU_ASSERT(offsetInChunk < capacity); - nullChunk->write(vector, offsetInVector, offsetInChunk); - if (!vector->isNull(offsetInVector)) { - memcpy(buffer.get() + getOffsetInBuffer(offsetInChunk), - vector->getData() + offsetInVector * numBytesPerValue, numBytesPerValue); + void copyVectorToBuffer(ValueVector* vector, offset_t startPosInChunk, + const common::SelectionVector& selVector) override { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::INTERNAL_ID); + auto relIDsInVector = (internalID_t*)vector->getData(); + if (commonTableID == INVALID_TABLE_ID) { + commonTableID = relIDsInVector[selVector.selectedPositions[0]].tableID; } - numValues = offsetInChunk >= numValues ? offsetInChunk + 1 : numValues; - } - - void copyVectorToBuffer(ValueVector* vector, offset_t startPosInChunk) final { - auto vectorDataToWriteFrom = vector->getData(); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - auto pos = vector->state->selVector->selectedPositions[i]; + for (auto i = 0u; i < selVector.selectedSize; i++) { + KU_ASSERT(relIDsInVector[i].tableID == commonTableID); + auto pos = selVector.selectedPositions[i]; nullChunk->setNull(startPosInChunk + i, vector->isNull(pos)); - memcpy(buffer.get() + getOffsetInBuffer(startPosInChunk + i), - vectorDataToWriteFrom + pos * numBytesPerValue, numBytesPerValue); + memcpy(buffer.get() + (startPosInChunk + i) * numBytesPerValue, + &relIDsInVector[pos].offset, numBytesPerValue); } } -}; -class InternalIDColumnChunk final : public ColumnChunk { -public: - // Physically, we only materialize offset of INTERNAL_ID, which is same as UINT64, - explicit InternalIDColumnChunk(uint64_t capacity) - : ColumnChunk(*LogicalType::INT64(), capacity, false /*enableCompression*/) {} - - void append(ValueVector* vector) override { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::INTERNAL_ID); - copyVectorToBuffer(vector, numValues); - numValues += vector->state->selVector->selectedSize; - } - - void copyVectorToBuffer(ValueVector* vector, offset_t startPosInChunk) override { - auto relIDsInVector = (internalID_t*)vector->getData(); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - auto pos = vector->state->selVector->selectedPositions[i]; + void copyInt64VectorToBuffer(ValueVector* vector, offset_t startPosInChunk, + const common::SelectionVector& selVector) { + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::INT64); + for (auto i = 0u; i < selVector.selectedSize; i++) { + auto pos = selVector.selectedPositions[i]; nullChunk->setNull(startPosInChunk + i, vector->isNull(pos)); memcpy(buffer.get() + (startPosInChunk + i) * numBytesPerValue, - &relIDsInVector[pos].offset, numBytesPerValue); + &vector->getValue(pos), numBytesPerValue); + } + } + + void lookup(offset_t offsetInChunk, ValueVector& output, + sel_t posInOutputVector) const override { + KU_ASSERT(offsetInChunk < capacity); + output.setNull(posInOutputVector, nullChunk->isNull(offsetInChunk)); + if (!output.isNull(posInOutputVector)) { + auto relID = output.getValue(posInOutputVector); + relID.offset = getValue(offsetInChunk); + KU_ASSERT(commonTableID != INVALID_TABLE_ID); + relID.tableID = commonTableID; + output.setValue(posInOutputVector, relID); } } @@ -578,6 +593,10 @@ class InternalIDColumnChunk final : public ColumnChunk { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::INTERNAL_ID); nullChunk->setNull(offsetInChunk, vector->isNull(offsetInVector)); auto relIDsInVector = (internalID_t*)vector->getData(); + if (commonTableID == INVALID_TABLE_ID) { + commonTableID = relIDsInVector[offsetInVector].tableID; + } + KU_ASSERT(commonTableID == relIDsInVector[offsetInVector].tableID); if (!vector->isNull(offsetInVector)) { memcpy(buffer.get() + offsetInChunk * numBytesPerValue, &relIDsInVector[offsetInVector].offset, numBytesPerValue); @@ -586,10 +605,14 @@ class InternalIDColumnChunk final : public ColumnChunk { numValues = offsetInChunk + 1; } } + +private: + common::table_id_t commonTableID; }; -std::unique_ptr ColumnChunkFactory::createColumnChunk( - LogicalType dataType, bool enableCompression, uint64_t capacity) { +// TODO(Guodong): Change the input param `dataType` to PhysicalType. +std::unique_ptr ColumnChunkFactory::createColumnChunk(LogicalType dataType, + bool enableCompression, uint64_t capacity, bool inMemory) { switch (dataType.getPhysicalType()) { case PhysicalTypeID::BOOL: { return std::make_unique(capacity, enableCompression); @@ -606,32 +629,25 @@ std::unique_ptr ColumnChunkFactory::createColumnChunk( case PhysicalTypeID::DOUBLE: case PhysicalTypeID::FLOAT: case PhysicalTypeID::INTERVAL: { - if (dataType.getLogicalTypeID() == LogicalTypeID::SERIAL) { - return std::make_unique(std::move(dataType), capacity, - false /*enableCompression*/, false /* hasNullChunk */); - } else { - return std::make_unique(std::move(dataType), capacity, enableCompression); - } + // TODO: As we have constant compression, SERIAL column should always be compressed as + // constant non-null when flushed to disk. We should add a sanity check for this. + return std::make_unique(std::move(dataType), capacity, enableCompression); } // Physically, we only materialize offset of INTERNAL_ID, which is same as INT64, case PhysicalTypeID::INTERNAL_ID: { - return std::make_unique(capacity); - } - case PhysicalTypeID::FIXED_LIST: { - return std::make_unique( - std::move(dataType), capacity, enableCompression); + return std::make_unique(capacity, enableCompression); } case PhysicalTypeID::STRING: { - return std::make_unique( - std::move(dataType), capacity, enableCompression); + return std::make_unique(std::move(dataType), capacity, enableCompression, + inMemory); } - case PhysicalTypeID::VAR_LIST: { - return std::make_unique( - std::move(dataType), capacity, enableCompression); + case PhysicalTypeID::LIST: { + return std::make_unique(std::move(dataType), capacity, enableCompression, + inMemory); } case PhysicalTypeID::STRUCT: { - return std::make_unique( - std::move(dataType), capacity, enableCompression); + return std::make_unique(std::move(dataType), capacity, enableCompression, + inMemory); } default: KU_UNREACHABLE; diff --git a/src/storage/store/dictionary_chunk.cpp b/src/storage/store/dictionary_chunk.cpp index e4e9c0c35e4..1fdc3b1e4b1 100644 --- a/src/storage/store/dictionary_chunk.cpp +++ b/src/storage/store/dictionary_chunk.cpp @@ -1,5 +1,7 @@ #include "storage/store/dictionary_chunk.h" +#include + #include using namespace kuzu::common; @@ -14,15 +16,16 @@ namespace storage { // chunk to be greater than the node group size since they remove unused entries. // So the chunk is initialized with a size equal to 3/4 the node group size, making sure there // is always extra space for updates. -static const uint64_t OFFSET_CHUNK_INITIAL_CAPACITY = StorageConstants::NODE_GROUP_SIZE * 0.75; +static const double OFFSET_CHUNK_CAPACITY_FACTOR = 0.75; DictionaryChunk::DictionaryChunk(uint64_t capacity, bool enableCompression) - : enableCompression{enableCompression} { + : enableCompression{enableCompression}, + indexTable(0, StringOps(this) /*hash*/, StringOps(this) /*equals*/) { // Bitpacking might save 1 bit per value with regular ascii compared to UTF-8 - stringDataChunk = ColumnChunkFactory::createColumnChunk( - *LogicalType::UINT8(), false /*enableCompression*/, capacity); - offsetChunk = ColumnChunkFactory::createColumnChunk( - *LogicalType::UINT64(), enableCompression, OFFSET_CHUNK_INITIAL_CAPACITY); + stringDataChunk = ColumnChunkFactory::createColumnChunk(*LogicalType::UINT8(), + false /*enableCompression*/, capacity); + offsetChunk = ColumnChunkFactory::createColumnChunk(*LogicalType::UINT64(), enableCompression, + capacity * OFFSET_CHUNK_CAPACITY_FACTOR); } void DictionaryChunk::resetToEmpty() { @@ -32,7 +35,9 @@ void DictionaryChunk::resetToEmpty() { } uint64_t DictionaryChunk::getStringLength(string_index_t index) const { - if (index + 1 < offsetChunk->getNumValues()) { + if (stringDataChunk->getNumValues() == 0) { + return 0; + } else if (index + 1 < offsetChunk->getNumValues()) { KU_ASSERT(offsetChunk->getValue(index + 1) >= offsetChunk->getValue(index)); return offsetChunk->getValue(index + 1) - @@ -45,7 +50,7 @@ DictionaryChunk::string_index_t DictionaryChunk::appendString(std::string_view v auto found = indexTable.find(val); // If the string already exists in the dictionary, skip it and refer to the existing string if (enableCompression && found != indexTable.end()) { - return found->second; + return found->index; } auto leftSpace = stringDataChunk->getCapacity() - stringDataChunk->getNumValues(); if (leftSpace < val.size()) { @@ -56,12 +61,14 @@ DictionaryChunk::string_index_t DictionaryChunk::appendString(std::string_view v stringDataChunk->setNumValues(startOffset + val.size()); auto index = offsetChunk->getNumValues(); if (index >= offsetChunk->getCapacity()) { - offsetChunk->resize(std::bit_ceil(offsetChunk->getCapacity() * CHUNK_RESIZE_RATIO)); + offsetChunk->resize(offsetChunk->getCapacity() == 0 ? + 2 : + (offsetChunk->getCapacity() * CHUNK_RESIZE_RATIO)); } offsetChunk->setValue(startOffset, index); offsetChunk->setNumValues(index + 1); if (enableCompression) { - indexTable.insert({std::string{val}, index}); + indexTable.insert({static_cast(index)}); } return index; } diff --git a/src/storage/store/dictionary_column.cpp b/src/storage/store/dictionary_column.cpp index 108706bb4b3..38b4b79f514 100644 --- a/src/storage/store/dictionary_column.cpp +++ b/src/storage/store/dictionary_column.cpp @@ -30,8 +30,8 @@ void DictionaryColumn::append(node_group_idx_t nodeGroupIdx, const DictionaryChu offsetColumn->append(dictChunk.getOffsetChunk(), nodeGroupIdx); } -void DictionaryColumn::scan( - Transaction* transaction, node_group_idx_t nodeGroupIdx, DictionaryChunk& dictChunk) { +void DictionaryColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, + DictionaryChunk& dictChunk) { auto dataMetadata = dataColumn->getMetadata(nodeGroupIdx, transaction->getType()); // Make sure that the chunk is large enough auto stringDataChunk = dictChunk.getStringDataChunk(); @@ -100,10 +100,15 @@ void DictionaryColumn::scan(Transaction* transaction, node_group_idx_t nodeGroup } string_index_t DictionaryColumn::append(node_group_idx_t nodeGroupIdx, std::string_view val) { - auto startOffset = dataColumn->appendValues( - nodeGroupIdx, reinterpret_cast(val.data()), val.size()); - return offsetColumn->appendValues( - nodeGroupIdx, reinterpret_cast(&startOffset), 1 /*numValues*/); + auto startOffset = dataColumn->appendValues(nodeGroupIdx, + reinterpret_cast(val.data()), val.size()); + return offsetColumn->appendValues(nodeGroupIdx, reinterpret_cast(&startOffset), + 1 /*numValues*/); +} + +void DictionaryColumn::prepareCommit() { + dataColumn->prepareCommit(); + offsetColumn->prepareCommit(); } void DictionaryColumn::checkpointInMemory() { @@ -154,8 +159,8 @@ bool DictionaryColumn::canCommitInPlace(Transaction* transaction, node_group_idx return true; } -bool DictionaryColumn::canDataCommitInPlace( - Transaction* transaction, node_group_idx_t nodeGroupIdx, uint64_t totalStringLengthToAdd) { +bool DictionaryColumn::canDataCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, + uint64_t totalStringLengthToAdd) { // Make sure there is sufficient space in the data chunk (not currently compressed) auto dataColumnMetadata = dataColumn->getMetadata(nodeGroupIdx, transaction->getType()); auto totalStringDataAfterUpdate = dataColumnMetadata.numValues + totalStringLengthToAdd; @@ -202,8 +207,8 @@ bool DictionaryColumn::canOffsetCommitInPlace(Transaction* transaction, return true; } -uint64_t DictionaryColumn::getNumValuesInOffsets( - Transaction* transaction, node_group_idx_t nodeGroupIdx) { +uint64_t DictionaryColumn::getNumValuesInOffsets(Transaction* transaction, + node_group_idx_t nodeGroupIdx) { return offsetColumn->getMetadata(nodeGroupIdx, transaction->getType()).numValues; } diff --git a/src/storage/store/list_column.cpp b/src/storage/store/list_column.cpp new file mode 100644 index 00000000000..47189aa20b7 --- /dev/null +++ b/src/storage/store/list_column.cpp @@ -0,0 +1,389 @@ +#include "storage/store/list_column.h" + +#include "storage/store/column.h" +#include "storage/store/list_column_chunk.h" +#include "storage/store/null_column.h" +#include + +using namespace kuzu::common; +using namespace kuzu::transaction; + +namespace kuzu { +namespace storage { + +offset_t ListOffsetSizeInfo::getListStartOffset(uint64_t pos) const { + if (numTotal == 0) { + return 0; + } + return pos == numTotal ? getListEndOffset(pos - 1) : getListEndOffset(pos) - getListSize(pos); +} + +offset_t ListOffsetSizeInfo::getListEndOffset(uint64_t pos) const { + if (numTotal == 0) { + return 0; + } + KU_ASSERT(pos < offsetColumnChunk->getNumValues()); + return offsetColumnChunk->getValue(pos); +} + +list_size_t ListOffsetSizeInfo::getListSize(uint64_t pos) const { + if (numTotal == 0) { + return 0; + } + KU_ASSERT(pos < sizeColumnChunk->getNumValues()); + return sizeColumnChunk->getValue(pos); +} + +bool ListOffsetSizeInfo::isOffsetSortedAscending(uint64_t startPos, uint64_t endPos) const { + offset_t prevEndOffset = getListStartOffset(startPos); + for (auto i = startPos; i < endPos; i++) { + offset_t currentEndOffset = getListEndOffset(i); + auto size = getListSize(i); + prevEndOffset += size; + if (currentEndOffset != prevEndOffset) { + return false; + } + } + return true; +} + +ListColumn::ListColumn(std::string name, LogicalType dataType, + const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, + BufferManager* bufferManager, WAL* wal, Transaction* transaction, + RWPropertyStats propertyStatistics, bool enableCompression) + : Column{name, std::move(dataType), metaDAHeaderInfo, dataFH, metadataFH, bufferManager, wal, + transaction, propertyStatistics, enableCompression, true /* requireNullColumn */} { + auto sizeColName = StorageUtils::getColumnName(name, StorageUtils::ColumnType::OFFSET, ""); + auto dataColName = StorageUtils::getColumnName(name, StorageUtils::ColumnType::DATA, ""); + sizeColumn = ColumnFactory::createColumn(sizeColName, *LogicalType::UINT32(), + *metaDAHeaderInfo.childrenInfos[0], dataFH, metadataFH, bufferManager, wal, transaction, + propertyStatistics, enableCompression); + dataColumn = ColumnFactory::createColumn(dataColName, + *ListType::getChildType(&this->dataType)->copy(), *metaDAHeaderInfo.childrenInfos[1], + dataFH, metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); +} + +void ListColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, + offset_t startOffsetInGroup, offset_t endOffsetInGroup, ValueVector* resultVector, + uint64_t offsetInVector) { + nullColumn->scan(transaction, nodeGroupIdx, startOffsetInGroup, endOffsetInGroup, resultVector, + offsetInVector); + auto listOffsetInfoInStorage = + getListOffsetSizeInfo(transaction, nodeGroupIdx, startOffsetInGroup, endOffsetInGroup); + offset_t listOffsetInVector = + offsetInVector == 0 ? 0 : + resultVector->getValue(offsetInVector - 1).offset + + resultVector->getValue(offsetInVector - 1).size; + auto offsetToWriteListData = listOffsetInVector; + auto numValues = endOffsetInGroup - startOffsetInGroup; + KU_ASSERT(numValues >= 0); + for (auto i = 0u; i < numValues; i++) { + list_size_t size = listOffsetInfoInStorage.getListSize(i); + resultVector->setValue(i + offsetInVector, list_entry_t{listOffsetInVector, size}); + listOffsetInVector += size; + } + ListVector::resizeDataVector(resultVector, listOffsetInVector); + auto dataVector = ListVector::getDataVector(resultVector); + bool isOffsetSortedAscending = listOffsetInfoInStorage.isOffsetSortedAscending(0, numValues); + if (isOffsetSortedAscending) { + dataColumn->scan(transaction, nodeGroupIdx, listOffsetInfoInStorage.getListStartOffset(0), + listOffsetInfoInStorage.getListStartOffset(numValues), dataVector, + offsetToWriteListData); + } else { + for (auto i = 0u; i < numValues; i++) { + offset_t startOffset = listOffsetInfoInStorage.getListStartOffset(i); + offset_t appendSize = listOffsetInfoInStorage.getListSize(i); + KU_ASSERT(appendSize >= 0); + dataColumn->scan(transaction, nodeGroupIdx, startOffset, startOffset + appendSize, + dataVector, offsetToWriteListData); + offsetToWriteListData += appendSize; + } + } +} + +void ListColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, + kuzu::storage::ColumnChunk* columnChunk, offset_t startOffset, offset_t endOffset) { + if (nodeGroupIdx >= metadataDA->getNumElements(transaction->getType())) { + columnChunk->setNumValues(0); + } else { + auto listColumnChunk = ku_dynamic_cast(columnChunk); + Column::scan(transaction, nodeGroupIdx, columnChunk, startOffset, endOffset); + auto sizeColumnChunk = listColumnChunk->getSizeColumnChunk(); + sizeColumn->scan(transaction, nodeGroupIdx, sizeColumnChunk, startOffset, endOffset); + auto resizeNumValues = listColumnChunk->getDataColumnChunk()->getNumValues(); + bool isOffsetSortedAscending = true; + offset_t prevOffset = listColumnChunk->getListStartOffset(0); + for (auto i = 0u; i < columnChunk->getNumValues(); i++) { + auto currentEndOffset = listColumnChunk->getListEndOffset(i); + auto appendSize = listColumnChunk->getListSize(i); + prevOffset += appendSize; + if (currentEndOffset != prevOffset) { + isOffsetSortedAscending = false; + } + resizeNumValues += appendSize; + } + if (isOffsetSortedAscending) { + listColumnChunk->resizeDataColumnChunk(std::bit_ceil(resizeNumValues)); + offset_t startListOffset = listColumnChunk->getListStartOffset(0); + offset_t endListOffset = + listColumnChunk->getListStartOffset(columnChunk->getNumValues()); + dataColumn->scan(transaction, nodeGroupIdx, listColumnChunk->getDataColumnChunk(), + startListOffset, endListOffset); + listColumnChunk->resetOffset(); + } else { + listColumnChunk->resizeDataColumnChunk(std::bit_ceil(resizeNumValues)); + auto tmpDataColumnChunk = + std::make_unique(ColumnChunkFactory::createColumnChunk( + *ListType::getChildType(&this->dataType)->copy(), enableCompression, + std::bit_ceil(resizeNumValues))); + auto dataListColumnChunk = listColumnChunk->getDataColumnChunk(); + for (auto i = 0u; i < columnChunk->getNumValues(); i++) { + offset_t startListOffset = listColumnChunk->getListStartOffset(i); + offset_t endListOffset = listColumnChunk->getListEndOffset(i); + dataColumn->scan(transaction, nodeGroupIdx, + tmpDataColumnChunk->dataColumnChunk.get(), startListOffset, endListOffset); + KU_ASSERT(endListOffset - startListOffset == + tmpDataColumnChunk->dataColumnChunk->getNumValues()); + dataListColumnChunk->append(tmpDataColumnChunk->dataColumnChunk.get(), 0, + tmpDataColumnChunk->dataColumnChunk->getNumValues()); + } + listColumnChunk->resetOffset(); + } + } +} + +void ListColumn::scanInternal(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { + resultVector->resetAuxiliaryBuffer(); + auto startNodeOffset = nodeIDVector->readNodeOffset(0); + auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(startNodeOffset); + auto startNodeOffsetInGroup = + startNodeOffset - StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); + KU_ASSERT(resultVector->state); + auto listOffsetSizeInfo = getListOffsetSizeInfo(transaction, nodeGroupIdx, + startNodeOffsetInGroup, startNodeOffsetInGroup + nodeIDVector->state->getOriginalSize()); + if (resultVector->state->selVector->isUnfiltered()) { + scanUnfiltered(transaction, nodeGroupIdx, resultVector, listOffsetSizeInfo); + } else { + scanFiltered(transaction, nodeGroupIdx, resultVector, listOffsetSizeInfo); + } +} + +void ListColumn::lookupValue(Transaction* transaction, offset_t nodeOffset, + ValueVector* resultVector, uint32_t posInVector) { + auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(nodeOffset); + auto nodeOffsetInGroup = nodeOffset - StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); + auto listEndOffset = readOffset(transaction, nodeGroupIdx, nodeOffsetInGroup); + auto size = readSize(transaction, nodeGroupIdx, nodeOffsetInGroup); + auto listStartOffset = listEndOffset - size; + auto offsetInVector = posInVector == 0 ? 0 : resultVector->getValue(posInVector - 1); + resultVector->setValue(posInVector, list_entry_t{offsetInVector, size}); + ListVector::resizeDataVector(resultVector, offsetInVector + size); + auto dataVector = ListVector::getDataVector(resultVector); + dataColumn->scan(transaction, StorageUtils::getNodeGroupIdx(nodeOffset), listStartOffset, + listEndOffset, dataVector, offsetInVector); +} + +void ListColumn::append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) { + KU_ASSERT(columnChunk->getDataType().getPhysicalType() == dataType.getPhysicalType()); + auto listColumnChunk = ku_dynamic_cast(columnChunk); + Column::append(listColumnChunk, nodeGroupIdx); + auto sizeColumnChunk = listColumnChunk->getSizeColumnChunk(); + sizeColumn->append(sizeColumnChunk, nodeGroupIdx); + auto dataColumnChunk = listColumnChunk->getDataColumnChunk(); + dataColumn->append(dataColumnChunk, nodeGroupIdx); +} + +void ListColumn::scanUnfiltered(Transaction* transaction, node_group_idx_t nodeGroupIdx, + ValueVector* resultVector, const ListOffsetSizeInfo& listOffsetInfoInStorage) { + auto numValuesToScan = resultVector->state->selVector->selectedSize; + offset_t offsetInVector = 0; + for (auto i = 0u; i < numValuesToScan; i++) { + auto listLen = listOffsetInfoInStorage.getListSize(i); + resultVector->setValue(i, list_entry_t{offsetInVector, listLen}); + offsetInVector += listLen; + } + ListVector::resizeDataVector(resultVector, offsetInVector); + auto dataVector = ListVector::getDataVector(resultVector); + offsetInVector = 0; + bool checkOffsetOrder = listOffsetInfoInStorage.isOffsetSortedAscending(0, numValuesToScan); + if (checkOffsetOrder) { + auto startListOffsetInStorage = listOffsetInfoInStorage.getListStartOffset(0); + numValuesToScan = numValuesToScan == 0 ? 0 : numValuesToScan - 1; + auto endListOffsetInStorage = listOffsetInfoInStorage.getListEndOffset(numValuesToScan); + dataColumn->scan(transaction, nodeGroupIdx, startListOffsetInStorage, + endListOffsetInStorage, dataVector, 0 /* offsetInVector */); + } else { + for (auto i = 0u; i < numValuesToScan; i++) { + auto startListOffsetInStorage = listOffsetInfoInStorage.getListStartOffset(i); + auto appendSize = listOffsetInfoInStorage.getListSize(i); + dataColumn->scan(transaction, nodeGroupIdx, startListOffsetInStorage, + startListOffsetInStorage + appendSize, dataVector, offsetInVector); + offsetInVector += appendSize; + } + } +} + +void ListColumn::scanFiltered(Transaction* transaction, node_group_idx_t nodeGroupIdx, + ValueVector* resultVector, const ListOffsetSizeInfo& listOffsetSizeInfo) { + offset_t listOffset = 0; + for (auto i = 0u; i < resultVector->state->selVector->selectedSize; i++) { + auto pos = resultVector->state->selVector->selectedPositions[i]; + auto listSize = listOffsetSizeInfo.getListSize(pos); + resultVector->setValue(pos, list_entry_t{(offset_t)listOffset, listSize}); + listOffset += listSize; + } + ListVector::resizeDataVector(resultVector, listOffset); + listOffset = 0; + for (auto i = 0u; i < resultVector->state->selVector->selectedSize; i++) { + auto pos = resultVector->state->selVector->selectedPositions[i]; + auto startOffsetInStorageToScan = listOffsetSizeInfo.getListStartOffset(pos); + auto appendSize = listOffsetSizeInfo.getListSize(pos); + auto dataVector = ListVector::getDataVector(resultVector); + dataColumn->scan(transaction, nodeGroupIdx, startOffsetInStorageToScan, + startOffsetInStorageToScan + appendSize, dataVector, listOffset); + listOffset += resultVector->getValue(pos).size; + } +} + +void ListColumn::prepareCommit() { + Column::prepareCommit(); + sizeColumn->prepareCommit(); + dataColumn->prepareCommit(); +} + +void ListColumn::checkpointInMemory() { + Column::checkpointInMemory(); + sizeColumn->checkpointInMemory(); + dataColumn->checkpointInMemory(); +} + +void ListColumn::rollbackInMemory() { + Column::rollbackInMemory(); + sizeColumn->rollbackInMemory(); + dataColumn->rollbackInMemory(); +} + +offset_t ListColumn::readOffset(Transaction* transaction, node_group_idx_t nodeGroupIdx, + offset_t offsetInNodeGroup) { + auto chunkMeta = metadataDA->get(nodeGroupIdx, transaction->getType()); + auto pageCursor = PageUtils::getPageCursorForPos(offsetInNodeGroup, + chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)); + pageCursor.pageIdx += chunkMeta.pageIdx; + offset_t value; + readFromPage(transaction, pageCursor.pageIdx, [&](uint8_t* frame) -> void { + readToPageFunc(frame, pageCursor, (uint8_t*)&value, 0 /* posInVector */, + 1 /* numValuesToRead */, chunkMeta.compMeta); + }); + return value; +} + +list_size_t ListColumn::readSize(Transaction* transaction, node_group_idx_t nodeGroupIdx, + offset_t offsetInNodeGroup) { + auto chunkMeta = sizeColumn->getMetadataDA()->get(nodeGroupIdx, transaction->getType()); + auto pageCursor = PageUtils::getPageCursorForPos(offsetInNodeGroup, + chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)); + pageCursor.pageIdx += chunkMeta.pageIdx; + offset_t value; + readFromPage(transaction, pageCursor.pageIdx, [&](uint8_t* frame) -> void { + readToPageFunc(frame, pageCursor, (uint8_t*)&value, 0 /* posInVector */, + 1 /* numValuesToRead */, chunkMeta.compMeta); + }); + return value; +} + +ListOffsetSizeInfo ListColumn::getListOffsetSizeInfo(Transaction* transaction, + node_group_idx_t nodeGroupIdx, offset_t startOffsetInNodeGroup, offset_t endOffsetInNodeGroup) { + auto numOffsetsToRead = endOffsetInNodeGroup - startOffsetInNodeGroup; + auto offsetColumnChunk = ColumnChunkFactory::createColumnChunk(*common::LogicalType::INT64(), + enableCompression, numOffsetsToRead); + auto sizeColumnChunk = ColumnChunkFactory::createColumnChunk(*common::LogicalType::UINT32(), + enableCompression, numOffsetsToRead); + Column::scan(transaction, nodeGroupIdx, offsetColumnChunk.get(), startOffsetInNodeGroup, + endOffsetInNodeGroup); + sizeColumn->scan(transaction, nodeGroupIdx, sizeColumnChunk.get(), startOffsetInNodeGroup, + endOffsetInNodeGroup); + return {numOffsetsToRead, std::move(offsetColumnChunk), std::move(sizeColumnChunk)}; +} + +void ListColumn::prepareCommitForChunk(Transaction* transaction, node_group_idx_t nodeGroupIdx, + const ChunkCollection& localInsertChunks, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunks, const offset_to_row_idx_t& updateInfo, + const offset_set_t& deleteInfo) { + auto currentNumNodeGroups = metadataDA->getNumElements(transaction->getType()); + auto isNewNodeGroup = nodeGroupIdx >= currentNumNodeGroups; + if (isNewNodeGroup) { + commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, localInsertChunks, + insertInfo, localUpdateChunks, updateInfo, deleteInfo); + } else { + auto columnChunk = getEmptyChunkForCommit(updateInfo.size() + insertInfo.size()); + std::vector dstOffsets; + for (auto& [offsetInDstChunk, rowIdx] : updateInfo) { + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + auto localUpdateChunk = localUpdateChunks[chunkIdx]; + dstOffsets.push_back(offsetInDstChunk); + columnChunk->append(localUpdateChunk, offsetInLocalChunk, 1); + } + for (auto& [offsetInDstChunk, rowIdx] : insertInfo) { + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + auto localInsertChunk = localInsertChunks[chunkIdx]; + dstOffsets.push_back(offsetInDstChunk); + columnChunk->append(localInsertChunk, offsetInLocalChunk, 1); + } + prepareCommitForChunk(transaction, nodeGroupIdx, dstOffsets, columnChunk.get(), 0); + } +} + +void ListColumn::prepareCommitForChunk(Transaction* transaction, node_group_idx_t nodeGroupIdx, + const std::vector& dstOffsets, ColumnChunk* chunk, offset_t startSrcOffset) { + auto currentNumNodeGroups = metadataDA->getNumElements(transaction->getType()); + auto isNewNodeGroup = nodeGroupIdx >= currentNumNodeGroups; + if (isNewNodeGroup) { + commitColumnChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk, + startSrcOffset); + } else { + // we separate the commit into three parts: offset chunk commit, size column chunk commit, + // data column chunk + auto listChunk = ku_dynamic_cast(chunk); + sizeColumn->prepareCommitForChunk(transaction, nodeGroupIdx, dstOffsets, + listChunk->getSizeColumnChunk(), startSrcOffset); + auto dataColumnSize = + dataColumn->getMetadata(nodeGroupIdx, transaction->getType()).numValues; + auto dataColumnChunk = listChunk->getDataColumnChunk(); + auto numListsToAppend = std::min(chunk->getNumValues(), (uint64_t)dstOffsets.size()); + auto dataSize = 0u; + auto startListOffset = listChunk->getListStartOffset(startSrcOffset); + std::vector dstOffsetsInDataColumn; + for (auto i = 0u; i < numListsToAppend; i++) { + for (auto j = 0u; j < listChunk->getListSize(startSrcOffset + i); j++) { + dstOffsetsInDataColumn.push_back(dataColumnSize + dataSize++); + } + } + dataColumn->prepareCommitForChunk(transaction, nodeGroupIdx, dstOffsetsInDataColumn, + dataColumnChunk, startListOffset); + // we need to update the offset since we do not do in-place list data update but append data + // in the end of list data column we need to plus to original data column size to get the + // new offset + // TODO(Jiamin): A better way is to store the offset in a offset column, just like size + // column. Then we can reuse prepareCommitForChunk interface for offset column. + auto offsetChunkMeta = getMetadata(nodeGroupIdx, transaction->getType()); + auto offsetColumnChunk = ColumnChunkFactory::createColumnChunk(*dataType.copy(), + enableCompression, 1.5 * std::bit_ceil(offsetChunkMeta.numValues + dstOffsets.size())); + Column::scan(transaction, nodeGroupIdx, offsetColumnChunk.get()); + for (auto i = 0u; i < numListsToAppend; i++) { + auto listEndOffset = listChunk->getListEndOffset(startSrcOffset + i); + auto isNull = listChunk->getNullChunk()->isNull(startSrcOffset + i); + offsetColumnChunk->setValue(dataColumnSize + listEndOffset, dstOffsets[i]); + offsetColumnChunk->getNullChunk()->setNull(dstOffsets[i], isNull); + } + auto offsetListChunk = + ku_dynamic_cast(offsetColumnChunk.get()); + offsetListChunk->getSizeColumnChunk()->setNumValues(offsetColumnChunk->getNumValues()); + Column::append(offsetColumnChunk.get(), nodeGroupIdx); + } +} + +} // namespace storage +} // namespace kuzu diff --git a/src/storage/store/list_column_chunk.cpp b/src/storage/store/list_column_chunk.cpp new file mode 100644 index 00000000000..e3b80d29a9e --- /dev/null +++ b/src/storage/store/list_column_chunk.cpp @@ -0,0 +1,357 @@ +#include "storage/store/list_column_chunk.h" + +#include "common/cast.h" +#include "common/data_chunk/sel_vector.h" +#include "common/types/value/value.h" +#include "storage/store/column_chunk.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace storage { + +void ListDataColumnChunk::reset() const { + dataColumnChunk->resetToEmpty(); +} + +void ListDataColumnChunk::resizeBuffer(uint64_t numValues) { + if (numValues <= capacity) { + return; + } + capacity = capacity == 0 ? 1 : capacity; + while (capacity < numValues) { + capacity = std::ceil(capacity * CHUNK_RESIZE_RATIO); + } + dataColumnChunk->resize(capacity); +} + +ListColumnChunk::ListColumnChunk(LogicalType dataType, uint64_t capacity, bool enableCompression, + bool inMemory) + : ColumnChunk{std::move(dataType), capacity, enableCompression, true /* hasNullChunk */} { + sizeColumnChunk = ColumnChunkFactory::createColumnChunk(*common::LogicalType::UINT32(), + enableCompression, capacity); + listDataColumnChunk = std::make_unique( + ColumnChunkFactory::createColumnChunk(*ListType::getChildType(&this->dataType)->copy(), + enableCompression, 0 /* capacity */, inMemory)); + checkOffsetSortedAsc = false; + KU_ASSERT(this->dataType.getPhysicalType() == PhysicalTypeID::LIST); +} + +bool ListColumnChunk::isOffsetsConsecutiveAndSortedAscending(uint64_t startPos, + uint64_t endPos) const { + offset_t prevEndOffset = getListStartOffset(startPos); + for (auto i = startPos; i < endPos; i++) { + offset_t currentEndOffset = getListEndOffset(i); + auto size = getListSize(i); + prevEndOffset += size; + if (currentEndOffset != prevEndOffset) { + return false; + } + } + return true; +} + +offset_t ListColumnChunk::getListStartOffset(offset_t offset) const { + if (numValues == 0) + return 0; + return offset == numValues ? getListEndOffset(offset - 1) : + getListEndOffset(offset) - getListSize(offset); +} + +offset_t ListColumnChunk::getListEndOffset(offset_t offset) const { + if (numValues == 0) + return 0; + KU_ASSERT(offset < numValues); + return getValue(offset); +} + +list_size_t ListColumnChunk::getListSize(common::offset_t offset) const { + if (numValues == 0) + return 0; + KU_ASSERT(offset < sizeColumnChunk->getNumValues()); + return sizeColumnChunk->getValue(offset); +} + +void ListColumnChunk::append(ColumnChunk* other, offset_t startPosInOtherChunk, + uint32_t numValuesToAppend) { + checkOffsetSortedAsc = true; + auto otherListChunk = ku_dynamic_cast(other); + nullChunk->append(other->getNullChunk(), startPosInOtherChunk, numValuesToAppend); + sizeColumnChunk->getNullChunk()->append(other->getNullChunk(), startPosInOtherChunk, + numValuesToAppend); + offset_t offsetInDataChunkToAppend = listDataColumnChunk->getNumValues(); + for (auto i = 0u; i < numValuesToAppend; i++) { + auto appendSize = otherListChunk->getListSize(startPosInOtherChunk + i); + sizeColumnChunk->setValue(appendSize, numValues); + offsetInDataChunkToAppend += appendSize; + setValue(offsetInDataChunkToAppend, numValues); + } + listDataColumnChunk->resizeBuffer(offsetInDataChunkToAppend); + for (auto i = 0u; i < numValuesToAppend; i++) { + auto startOffset = otherListChunk->getListStartOffset(startPosInOtherChunk + i); + auto appendSize = otherListChunk->getListSize(startPosInOtherChunk + i); + listDataColumnChunk->dataColumnChunk->append( + otherListChunk->listDataColumnChunk->dataColumnChunk.get(), startOffset, appendSize); + } + sanityCheck(); +} + +void ListColumnChunk::resetToEmpty() { + ColumnChunk::resetToEmpty(); + sizeColumnChunk->resetToEmpty(); + listDataColumnChunk = std::make_unique( + ColumnChunkFactory::createColumnChunk(*ListType::getChildType(&this->dataType)->copy(), + enableCompression, 0 /* capacity */)); +} + +void ListColumnChunk::append(ValueVector* vector, const SelectionVector& selVector) { + auto numToAppend = selVector.selectedSize; + auto newCapacity = capacity; + while (numValues + numToAppend >= newCapacity) { + newCapacity = std::ceil(newCapacity * 1.5); + } + if (capacity < newCapacity) { + resize(newCapacity); + } + offset_t nextListOffsetInChunk = listDataColumnChunk->getNumValues(); + auto offsetBufferToWrite = (offset_t*)(buffer.get()); + for (auto i = 0u; i < selVector.selectedSize; i++) { + auto pos = selVector.selectedPositions[i]; + auto listLen = vector->isNull(pos) ? 0 : vector->getValue(pos).size; + sizeColumnChunk->setValue(listLen, numValues + i); + sizeColumnChunk->getNullChunk()->setNull(numValues + i, vector->isNull(pos)); + nullChunk->setNull(numValues + i, vector->isNull(pos)); + nextListOffsetInChunk += listLen; + offsetBufferToWrite[numValues + i] = nextListOffsetInChunk; + } + listDataColumnChunk->resizeBuffer(nextListOffsetInChunk); + auto dataVector = ListVector::getDataVector(vector); + // TODO(Guodong): we should not set vector to a new state. + dataVector->setState(std::make_unique()); + dataVector->state->selVector->setToFiltered(); + for (auto i = 0u; i < selVector.selectedSize; i++) { + auto pos = selVector.selectedPositions[i]; + if (vector->isNull(pos)) { + continue; + } + copyListValues(vector->getValue(pos), dataVector); + } + numValues += numToAppend; + sanityCheck(); +} + +void ListColumnChunk::appendNullList() { + offset_t nextListOffsetInChunk = listDataColumnChunk->getNumValues(); + auto offsetBufferToWrite = (offset_t*)(buffer.get()); + sizeColumnChunk->setValue(0, numValues); + sizeColumnChunk->getNullChunk()->setNull(numValues, true); + offsetBufferToWrite[numValues] = nextListOffsetInChunk; + nullChunk->setNull(numValues, true); + numValues++; +} + +void ListColumnChunk::lookup(offset_t offsetInChunk, ValueVector& output, + sel_t posInOutputVector) const { + KU_ASSERT(offsetInChunk < numValues); + output.setNull(posInOutputVector, nullChunk->isNull(offsetInChunk)); + if (output.isNull(posInOutputVector)) { + return; + } + auto startOffset = offsetInChunk == 0 ? 0 : getValue(offsetInChunk - 1); + auto listSize = getListSize(offsetInChunk); + auto dataVector = ListVector::getDataVector(&output); + auto currentListDataSize = ListVector::getDataVectorSize(&output); + ListVector::resizeDataVector(&output, currentListDataSize + listSize); + // TODO(Guodong): Should add `scan` interface and use `scan` here. + for (auto i = 0u; i < listSize; i++) { + listDataColumnChunk->dataColumnChunk->lookup(startOffset + i, *dataVector, i); + } +} + +void ListColumnChunk::write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + RelMultiplicity /*multiplicity*/) { + KU_ASSERT(chunk->getDataType().getPhysicalType() == dataType.getPhysicalType() && + dstOffsets->getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID && + chunk->getNumValues() == dstOffsets->getNumValues()); + checkOffsetSortedAsc = true; + offset_t currentIndex = listDataColumnChunk->getNumValues(); + auto otherListChunk = ku_dynamic_cast(chunk); + listDataColumnChunk->resizeBuffer( + listDataColumnChunk->getNumValues() + otherListChunk->listDataColumnChunk->getNumValues()); + listDataColumnChunk->dataColumnChunk->append( + otherListChunk->listDataColumnChunk->dataColumnChunk.get(), 0, + otherListChunk->listDataColumnChunk->getNumValues()); + offset_t maxDstOffset = 0; + for (auto i = 0u; i < dstOffsets->getNumValues(); i++) { + auto posInChunk = dstOffsets->getValue(i); + if (posInChunk > maxDstOffset) { + maxDstOffset = posInChunk; + } + } + while (maxDstOffset >= numValues) { + appendNullList(); + } + for (auto i = 0u; i < dstOffsets->getNumValues(); i++) { + auto posInChunk = dstOffsets->getValue(i); + auto appendSize = otherListChunk->getListSize(i); + currentIndex += appendSize; + setValue(currentIndex, posInChunk); + nullChunk->setNull(posInChunk, otherListChunk->nullChunk->isNull(i)); + sizeColumnChunk->setValue(appendSize, posInChunk); + sizeColumnChunk->getNullChunk()->setNull(posInChunk, otherListChunk->nullChunk->isNull(i)); + } + sanityCheck(); +} + +void ListColumnChunk::write(ValueVector* vector, offset_t offsetInVector, offset_t offsetInChunk) { + checkOffsetSortedAsc = true; + auto selVector = std::make_unique(1); + selVector->setToFiltered(); + selVector->selectedPositions[0] = offsetInVector; + auto appendSize = + vector->isNull(offsetInVector) ? 0 : vector->getValue(offsetInVector).size; + listDataColumnChunk->resizeBuffer(listDataColumnChunk->getNumValues() + appendSize); + // TODO(Guodong): Do not set vector to a new state. + auto dataVector = ListVector::getDataVector(vector); + dataVector->setState(std::make_unique()); + dataVector->state->selVector->setToFiltered(); + copyListValues(vector->getValue(offsetInVector), dataVector); + while (offsetInChunk >= numValues) { + appendNullList(); + } + auto isNull = vector->isNull(offsetInVector); + nullChunk->setNull(offsetInChunk, isNull); + sizeColumnChunk->getNullChunk()->setNull(offsetInChunk, isNull); + if (!isNull) { + sizeColumnChunk->setValue(appendSize, offsetInChunk); + setValue(listDataColumnChunk->getNumValues(), offsetInChunk); + } + sanityCheck(); +} + +void ListColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, + offset_t dstOffsetInChunk, offset_t numValuesToCopy) { + KU_ASSERT(srcChunk->getDataType().getPhysicalType() == PhysicalTypeID::LIST); + checkOffsetSortedAsc = true; + auto srcListChunk = ku_dynamic_cast(srcChunk); + auto offsetInDataChunkToAppend = listDataColumnChunk->getNumValues(); + for (auto i = 0u; i < numValuesToCopy; i++) { + auto appendSize = srcListChunk->getListSize(srcOffsetInChunk + i); + offsetInDataChunkToAppend += appendSize; + sizeColumnChunk->setValue(appendSize, dstOffsetInChunk + i); + setValue(offsetInDataChunkToAppend, dstOffsetInChunk + i); + nullChunk->setNull(dstOffsetInChunk + i, + srcListChunk->nullChunk->isNull(srcOffsetInChunk + i)); + sizeColumnChunk->getNullChunk()->setNull(dstOffsetInChunk + i, + srcListChunk->nullChunk->isNull(srcOffsetInChunk + i)); + } + listDataColumnChunk->resizeBuffer(offsetInDataChunkToAppend); + for (auto i = 0u; i < numValuesToCopy; i++) { + auto startOffsetInSrcChunk = srcListChunk->getListStartOffset(srcOffsetInChunk + i); + auto appendSize = srcListChunk->getListSize(srcOffsetInChunk + i); + listDataColumnChunk->dataColumnChunk->append( + srcListChunk->listDataColumnChunk->dataColumnChunk.get(), startOffsetInSrcChunk, + appendSize); + } + sanityCheck(); +} + +void ListColumnChunk::copy(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, + offset_t dstOffsetInChunk, offset_t numValuesToCopy) { + KU_ASSERT(srcChunk->getDataType().getPhysicalType() == PhysicalTypeID::LIST); + KU_ASSERT(dstOffsetInChunk >= numValues); + while (numValues < dstOffsetInChunk) { + appendNullList(); + } + append(srcChunk, srcOffsetInChunk, numValuesToCopy); +} + +void ListColumnChunk::copyListValues(const list_entry_t& entry, ValueVector* dataVector) { + auto numListValuesToCopy = entry.size; + auto numListValuesCopied = 0u; + while (numListValuesCopied < numListValuesToCopy) { + auto numListValuesToCopyInBatch = + std::min(numListValuesToCopy - numListValuesCopied, DEFAULT_VECTOR_CAPACITY); + dataVector->state->selVector->selectedSize = numListValuesToCopyInBatch; + for (auto j = 0u; j < numListValuesToCopyInBatch; j++) { + dataVector->state->selVector->selectedPositions[j] = + entry.offset + numListValuesCopied + j; + } + listDataColumnChunk->append(dataVector, *dataVector->state->selVector); + numListValuesCopied += numListValuesToCopyInBatch; + } +} + +void ListColumnChunk::resetOffset() { + offset_t nextListOffsetReset = 0; + for (auto i = 0u; i < numValues; i++) { + auto listSize = getListSize(i); + nextListOffsetReset += uint64_t(listSize); + setValue(nextListOffsetReset, i); + sizeColumnChunk->setValue(listSize, i); + } +} + +void ListColumnChunk::finalize() { + // rewrite the column chunk for better scanning performance + auto newColumnChunk = ColumnChunkFactory::createColumnChunk(std::move(*dataType.copy()), + enableCompression, capacity); + uint64_t totalListLen = listDataColumnChunk->getNumValues(); + uint64_t resizeThreshold = listDataColumnChunk->capacity / 2; + // if the list is not very long, we do not need to rewrite + if (totalListLen < resizeThreshold) { + return; + } + // if we do not trigger random write, we do not need to rewrite + if (!checkOffsetSortedAsc) { + return; + } + // if the list is in ascending order, we do not need to rewrite + if (isOffsetsConsecutiveAndSortedAscending(0, numValues)) { + return; + } + auto newListChunk = ku_dynamic_cast(newColumnChunk.get()); + newListChunk->resize(numValues); + newListChunk->getDataColumnChunk()->resize(totalListLen); + auto dataColumnChunk = newListChunk->getDataColumnChunk(); + newListChunk->listDataColumnChunk->resizeBuffer(totalListLen); + offset_t offsetInChunk = 0; + offset_t currentIndex = 0; + for (auto i = 0u; i < numValues; i++) { + if (nullChunk->isNull(i)) { + newListChunk->appendNullList(); + } else { + auto startOffset = getListStartOffset(i); + auto listSize = getListSize(i); + dataColumnChunk->append(listDataColumnChunk->dataColumnChunk.get(), startOffset, + listSize); + offsetInChunk += listSize; + newListChunk->getNullChunk()->setNull(currentIndex, false); + newListChunk->sizeColumnChunk->getNullChunk()->setNull(currentIndex, false); + newListChunk->sizeColumnChunk->setValue(listSize, currentIndex); + newListChunk->setValue(offsetInChunk, currentIndex); + } + currentIndex++; + } + newListChunk->sanityCheck(); + // Move offsets, null, data from newListChunk to this column chunk. And release indices. + resetFromOtherChunk(newListChunk); +} +void ListColumnChunk::resetFromOtherChunk(ListColumnChunk* other) { + buffer = std::move(other->buffer); + nullChunk = std::move(other->nullChunk); + sizeColumnChunk = std::move(other->sizeColumnChunk); + listDataColumnChunk = std::move(other->listDataColumnChunk); + numValues = other->numValues; + checkOffsetSortedAsc = false; +} + +bool ListColumnChunk::sanityCheck() { + KU_ASSERT(ColumnChunk::sanityCheck()); + KU_ASSERT(sizeColumnChunk->sanityCheck()); + KU_ASSERT(getDataColumnChunk()->sanityCheck()); + return sizeColumnChunk->getNumValues() == numValues; +} + +} // namespace storage +} // namespace kuzu diff --git a/src/storage/store/node_table.cpp b/src/storage/store/node_table.cpp index 4fe71968168..4a85880909a 100644 --- a/src/storage/store/node_table.cpp +++ b/src/storage/store/node_table.cpp @@ -5,6 +5,7 @@ #include "common/exception/runtime.h" #include "common/types/ku_string.h" #include "common/types/types.h" +#include "storage/local_storage/local_node_table.h" #include "storage/store/node_table_data.h" #include "transaction/transaction.h" @@ -16,7 +17,7 @@ namespace kuzu { namespace storage { NodeTable::NodeTable(BMFileHandle* dataFH, BMFileHandle* metadataFH, - catalog::NodeTableCatalogEntry* nodeTableEntry, + NodeTableCatalogEntry* nodeTableEntry, NodesStoreStatsAndDeletedIDs* nodesStatisticsAndDeletedIDs, MemoryManager* memoryManager, WAL* wal, bool readOnly, bool enableCompression, VirtualFileSystem* vfs) : Table{nodeTableEntry, nodesStatisticsAndDeletedIDs, memoryManager, wal}, @@ -26,8 +27,8 @@ NodeTable::NodeTable(BMFileHandle* dataFH, BMFileHandle* metadataFH, initializePKIndex(nodeTableEntry, readOnly, vfs); } -void NodeTable::initializePKIndex( - catalog::NodeTableCatalogEntry* nodeTableEntry, bool readOnly, VirtualFileSystem* vfs) { +void NodeTable::initializePKIndex(NodeTableCatalogEntry* nodeTableEntry, bool readOnly, + VirtualFileSystem* vfs) { if (nodeTableEntry->getPrimaryKey()->getDataType()->getLogicalTypeID() != LogicalTypeID::SERIAL) { pkIndex = std::make_unique( @@ -37,87 +38,109 @@ void NodeTable::initializePKIndex( } } -void NodeTable::read(Transaction* transaction, TableReadState& readState, ValueVector* nodeIDVector, - const std::vector& outputVectors) { - if (nodeIDVector->isSequential()) { - tableData->scan(transaction, readState, nodeIDVector, outputVectors); +void NodeTable::read(Transaction* transaction, TableReadState& readState) { + if (readState.nodeIDVector.isSequential()) { + scan(transaction, readState); } else { - tableData->lookup(transaction, readState, nodeIDVector, outputVectors); + lookup(transaction, readState); } } -common::offset_t NodeTable::validateUniquenessConstraint( - Transaction* tx, const std::vector& propertyVectors) { +void NodeTable::scan(Transaction* transaction, TableReadState& readState) { + tableData->scan(transaction, *readState.dataReadState, readState.nodeIDVector, + readState.outputVectors); + if (transaction->isWriteTransaction()) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID); + if (localTable) { + localTable->scan(readState); + } + } +} + +void NodeTable::lookup(Transaction* transaction, TableReadState& readState) { + tableData->lookup(transaction, *readState.dataReadState, readState.nodeIDVector, + readState.outputVectors); + if (transaction->isWriteTransaction()) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID); + if (localTable) { + localTable->lookup(readState); + } + } +} + +offset_t NodeTable::validateUniquenessConstraint(Transaction* tx, + const std::vector& propertyVectors) { if (pkIndex == nullptr) { return INVALID_OFFSET; } auto pkVector = propertyVectors[pkColumnID]; KU_ASSERT(pkVector->state->selVector->selectedSize == 1); auto pkVectorPos = pkVector->state->selVector->selectedPositions[0]; - common::offset_t offset; + offset_t offset; if (pkIndex->lookup(tx, propertyVectors[pkColumnID], pkVectorPos, offset)) { return offset; } return INVALID_OFFSET; } -offset_t NodeTable::insert(Transaction* transaction, ValueVector* nodeIDVector, - const std::vector& propertyVectors) { - auto maxNodeOffset = 0u; - for (auto i = 0u; i < nodeIDVector->state->selVector->selectedSize; i++) { - auto pos = nodeIDVector->state->selVector->selectedPositions[i]; - auto offset = - ku_dynamic_cast(tablesStatistics) - ->addNode(tableID); - if (offset > maxNodeOffset) { - maxNodeOffset = offset; - } - nodeIDVector->setValue(pos, nodeID_t{offset, tableID}); - nodeIDVector->setNull(pos, false); - } +void NodeTable::insert(Transaction* transaction, TableInsertState& insertState) { + auto nodesStats = + ku_dynamic_cast(tablesStatistics); + auto& nodeInsertState = ku_dynamic_cast(insertState); + KU_ASSERT(nodeInsertState.nodeIDVector.state->selVector->selectedSize == 1); + auto pos = nodeInsertState.nodeIDVector.state->selVector->selectedPositions[0]; + auto offset = nodesStats->addNode(tableID); + nodeInsertState.nodeIDVector.setValue(pos, nodeID_t{offset, tableID}); + nodeInsertState.nodeIDVector.setNull(pos, false); if (pkIndex) { - insertPK(nodeIDVector, propertyVectors[pkColumnID]); + insertPK(nodeInsertState.nodeIDVector, nodeInsertState.pkVector); } - tableData->insert(transaction, nodeIDVector, propertyVectors); - return maxNodeOffset; + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + localTable->insert(insertState); } -void NodeTable::update(transaction::Transaction* transaction, common::column_id_t columnID, - common::ValueVector* nodeIDVector, common::ValueVector* propertyVector) { +void NodeTable::update(Transaction* transaction, TableUpdateState& updateState) { // NOTE: We assume all input all flatten now. This is to simplify the implementation. // We should optimize this to take unflat input later. - KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1 && - propertyVector->state->selVector->selectedSize == 1); - if (columnID == pkColumnID && pkIndex) { - updatePK(transaction, columnID, nodeIDVector, propertyVector); + auto& nodeUpdateState = ku_dynamic_cast(updateState); + KU_ASSERT(nodeUpdateState.nodeIDVector.state->selVector->selectedSize == 1 && + nodeUpdateState.propertyVector.state->selVector->selectedSize == 1); + if (nodeUpdateState.columnID == pkColumnID && pkIndex) { + updatePK(transaction, updateState.columnID, nodeUpdateState.nodeIDVector, + updateState.propertyVector); } - tableData->update(transaction, columnID, nodeIDVector, propertyVector); + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + localTable->update(updateState); } -void NodeTable::delete_( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* pkVector) { - auto readState = std::make_unique(); - tableData->initializeReadState(transaction, {pkColumnID}, nodeIDVector, readState.get()); - read(transaction, *readState, nodeIDVector, {pkVector}); +void NodeTable::delete_(Transaction* transaction, TableDeleteState& deleteState) { + auto& nodeDeleteState = ku_dynamic_cast(deleteState); + KU_ASSERT(nodeDeleteState.nodeIDVector.state->selVector->selectedSize == 1); + auto pos = nodeDeleteState.nodeIDVector.state->selVector->selectedPositions[0]; + if (nodeDeleteState.nodeIDVector.isNull(pos)) { + return; + } + auto pkColumnIDs = {pkColumnID}; + auto pkVectors = std::vector{&nodeDeleteState.pkVector}; + auto readState = + std::make_unique(nodeDeleteState.nodeIDVector, pkColumnIDs, pkVectors); + initializeReadState(transaction, pkColumnIDs, nodeDeleteState.nodeIDVector, *readState); + read(transaction, *readState); if (pkIndex) { - pkIndex->delete_(pkVector); - } - // TODO(Guodong): We actually have flatten the input here. But the code is left unchanged for - // now, so we can remove the flattenAll logic later. - for (auto i = 0u; i < nodeIDVector->state->selVector->selectedSize; i++) { - auto pos = nodeIDVector->state->selVector->selectedPositions[i]; - if (nodeIDVector->isNull(pos)) { - continue; - } - auto nodeOffset = nodeIDVector->readNodeOffset(pos); - ku_dynamic_cast(tablesStatistics) - ->deleteNode(tableID, nodeOffset); + pkIndex->delete_(&nodeDeleteState.pkVector); } - tableData->delete_(transaction, nodeIDVector); + auto nodeOffset = nodeDeleteState.nodeIDVector.readNodeOffset(pos); + ku_dynamic_cast(tablesStatistics) + ->deleteNode(tableID, nodeOffset); + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + localTable->delete_(deleteState); } -void NodeTable::addColumn(transaction::Transaction* transaction, const catalog::Property& property, - common::ValueVector* defaultValueVector) { +void NodeTable::addColumn(Transaction* transaction, const Property& property, + ValueVector* defaultValueVector) { auto nodesStats = ku_dynamic_cast(tablesStatistics); nodesStats->setPropertyStatisticsForTable(tableID, property.getPropertyID(), @@ -135,11 +158,20 @@ void NodeTable::prepareCommit(Transaction* transaction, LocalTable* localTable) if (pkIndex) { pkIndex->prepareCommit(); } - tableData->prepareLocalTableToCommit(transaction, localTable->getLocalTableData(0)); + auto localNodeTable = ku_dynamic_cast(localTable); + tableData->prepareLocalTableToCommit(transaction, localNodeTable->getTableData()); + tableData->prepareCommit(); wal->addToUpdatedTables(tableID); } -void NodeTable::prepareRollback(LocalTableData* localTable) { +void NodeTable::prepareCommit() { + if (pkIndex) { + pkIndex->prepareCommit(); + } + tableData->prepareCommit(); +} + +void NodeTable::prepareRollback(LocalTable* localTable) { if (pkIndex) { pkIndex->prepareRollback(); } @@ -161,34 +193,36 @@ void NodeTable::rollbackInMemory() { } void NodeTable::updatePK(Transaction* transaction, column_id_t columnID, - common::ValueVector* keyVector, common::ValueVector* payloadVector) { + const ValueVector& nodeIDVector, const ValueVector& payloadVector) { auto pkVector = std::make_unique(getColumn(pkColumnID)->getDataType(), memoryManager); - pkVector->state = keyVector->state; - auto readState = std::make_unique(); - initializeReadState(transaction, {columnID}, keyVector, readState.get()); - read(transaction, *readState, keyVector, {pkVector.get()}); + pkVector->state = nodeIDVector.state; + auto outputVectors = std::vector{pkVector.get()}; + auto columnIDs = {columnID}; + auto readState = std::make_unique(nodeIDVector, columnIDs, outputVectors); + initializeReadState(transaction, columnIDs, nodeIDVector, *readState); + read(transaction, *readState); pkIndex->delete_(pkVector.get()); - insertPK(keyVector, payloadVector); + insertPK(nodeIDVector, payloadVector); } -void NodeTable::insertPK(ValueVector* nodeIDVector, ValueVector* primaryKeyVector) { - for (auto i = 0u; i < nodeIDVector->state->selVector->selectedSize; i++) { - auto nodeIDPos = nodeIDVector->state->selVector->selectedPositions[i]; - auto offset = nodeIDVector->readNodeOffset(nodeIDPos); - auto pkPos = primaryKeyVector->state->selVector->selectedPositions[i]; - if (primaryKeyVector->isNull(pkPos)) { +void NodeTable::insertPK(const ValueVector& nodeIDVector, const ValueVector& primaryKeyVector) { + for (auto i = 0u; i < nodeIDVector.state->selVector->selectedSize; i++) { + auto nodeIDPos = nodeIDVector.state->selVector->selectedPositions[i]; + auto offset = nodeIDVector.readNodeOffset(nodeIDPos); + auto pkPos = primaryKeyVector.state->selVector->selectedPositions[i]; + if (primaryKeyVector.isNull(pkPos)) { throw RuntimeException(ExceptionMessage::nullPKException()); } - if (!pkIndex->insert(primaryKeyVector, pkPos, offset)) { + if (!pkIndex->insert(const_cast(&primaryKeyVector), pkPos, offset)) { std::string pkStr; TypeUtils::visit( - primaryKeyVector->dataType.getPhysicalType(), + primaryKeyVector.dataType.getPhysicalType(), [&](ku_string_t) { - pkStr = primaryKeyVector->getValue(pkPos).getAsString(); + pkStr = primaryKeyVector.getValue(pkPos).getAsString(); }, [&]( - T) { pkStr = TypeUtils::toString(primaryKeyVector->getValue(pkPos)); }); + T) { pkStr = TypeUtils::toString(primaryKeyVector.getValue(pkPos)); }); throw RuntimeException(ExceptionMessage::duplicatePKException(pkStr)); } } diff --git a/src/storage/store/node_table_data.cpp b/src/storage/store/node_table_data.cpp index 575a0b2cc64..4dbaed168cd 100644 --- a/src/storage/store/node_table_data.cpp +++ b/src/storage/store/node_table_data.cpp @@ -31,93 +31,57 @@ NodeTableData::NodeTableData(BMFileHandle* dataFH, BMFileHandle* metadataFH, } } -void NodeTableData::scan(Transaction* transaction, TableReadState& readState, - ValueVector* nodeIDVector, const std::vector& outputVectors) { - KU_ASSERT(readState.columnIDs.size() == outputVectors.size() && !nodeIDVector->state->isFlat()); +void NodeTableData::scan(Transaction* transaction, TableDataReadState& readState, + const ValueVector& nodeIDVector, const std::vector& outputVectors) { + KU_ASSERT(readState.columnIDs.size() == outputVectors.size() && !nodeIDVector.state->isFlat()); for (auto i = 0u; i < readState.columnIDs.size(); i++) { if (readState.columnIDs[i] == INVALID_COLUMN_ID) { outputVectors[i]->setAllNull(); } else { KU_ASSERT(readState.columnIDs[i] < columns.size()); - columns[readState.columnIDs[i]]->scan(transaction, nodeIDVector, outputVectors[i]); + columns[readState.columnIDs[i]]->scan(transaction, + const_cast(&nodeIDVector), outputVectors[i]); } } - if (transaction->isWriteTransaction()) { - auto localTableData = transaction->getLocalStorage()->getLocalTableData(tableID); - if (localTableData) { - auto localRelTableData = - ku_dynamic_cast(localTableData); - localRelTableData->scan(nodeIDVector, readState.columnIDs, outputVectors); - } - } -} - -void NodeTableData::insert(Transaction* transaction, ValueVector* nodeIDVector, - const std::vector& propertyVectors) { - // We assume that offsets are given in the ascending order, thus lastOffset is the max one. - KU_ASSERT(nodeIDVector->state->selVector->selectedSize == 1); - auto localTableData = ku_dynamic_cast( - transaction->getLocalStorage()->getOrCreateLocalTableData(tableID, columns)); - localTableData->insert(nodeIDVector, propertyVectors); -} - -void NodeTableData::update(Transaction* transaction, column_id_t columnID, - ValueVector* nodeIDVector, ValueVector* propertyVector) { - KU_ASSERT(columnID < columns.size()); - auto localTableData = ku_dynamic_cast( - transaction->getLocalStorage()->getOrCreateLocalTableData(tableID, columns)); - localTableData->update(nodeIDVector, columnID, propertyVector); -} - -void NodeTableData::delete_(Transaction* transaction, ValueVector* nodeIDVector) { - auto localTableData = ku_dynamic_cast( - transaction->getLocalStorage()->getOrCreateLocalTableData(tableID, columns)); - localTableData->delete_(nodeIDVector); } -void NodeTableData::lookup(Transaction* transaction, TableReadState& readState, - ValueVector* nodeIDVector, const std::vector& outputVectors) { - auto pos = nodeIDVector->state->selVector->selectedPositions[0]; +void NodeTableData::lookup(Transaction* transaction, TableDataReadState& readState, + const ValueVector& nodeIDVector, const std::vector& outputVectors) { + auto pos = nodeIDVector.state->selVector->selectedPositions[0]; for (auto i = 0u; i < readState.columnIDs.size(); i++) { auto columnID = readState.columnIDs[i]; if (columnID == INVALID_COLUMN_ID) { outputVectors[i]->setNull(pos, true); } else { KU_ASSERT(readState.columnIDs[i] < columns.size()); - columns[readState.columnIDs[i]]->lookup(transaction, nodeIDVector, outputVectors[i]); - } - } - if (transaction->isWriteTransaction()) { - auto localTableData = transaction->getLocalStorage()->getLocalTableData(tableID); - if (localTableData) { - auto localRelTableData = - ku_dynamic_cast(localTableData); - localRelTableData->lookup(nodeIDVector, readState.columnIDs, outputVectors); + columns[readState.columnIDs[i]]->lookup(transaction, + const_cast(&nodeIDVector), outputVectors[i]); } } } -void NodeTableData::append(kuzu::storage::NodeGroup* nodeGroup) { +void NodeTableData::append(ChunkedNodeGroup* nodeGroup) { for (auto columnID = 0u; columnID < columns.size(); columnID++) { - auto columnChunk = nodeGroup->getColumnChunk(columnID); + auto& columnChunk = nodeGroup->getColumnChunkUnsafe(columnID); KU_ASSERT(columnID < columns.size()); - columns[columnID]->append(columnChunk, nodeGroup->getNodeGroupIdx()); + columns[columnID]->append(&columnChunk, nodeGroup->getNodeGroupIdx()); } } -void NodeTableData::prepareLocalTableToCommit( - Transaction* transaction, LocalTableData* localTable) { - for (auto& [nodeGroupIdx, nodeGroup] : localTable->nodeGroups) { +void NodeTableData::prepareLocalTableToCommit(Transaction* transaction, + LocalTableData* localTable) { + for (auto& [nodeGroupIdx, localNodeGroup] : localTable->nodeGroups) { for (auto columnID = 0u; columnID < columns.size(); columnID++) { auto column = columns[columnID].get(); - auto columnChunk = nodeGroup->getLocalColumnChunk(columnID); - if (columnChunk->getNumRows() == 0) { + auto localInsertChunk = localNodeGroup->getInsesrtChunks().getLocalChunk(columnID); + auto localUpdateChunk = localNodeGroup->getUpdateChunks(columnID).getLocalChunk(0); + if (localInsertChunk.empty() && localUpdateChunk.empty()) { continue; } - auto localNodeGroup = ku_dynamic_cast(nodeGroup.get()); - column->prepareCommitForChunk(transaction, nodeGroupIdx, columnChunk, - localNodeGroup->getInsertInfoRef(columnID), - localNodeGroup->getUpdateInfoRef(columnID), {} /* deleteInfo */); + auto localNodeNG = ku_dynamic_cast(localNodeGroup.get()); + column->prepareCommitForChunk(transaction, nodeGroupIdx, localInsertChunk, + localNodeNG->getInsertInfoRef(), localUpdateChunk, + localNodeNG->getUpdateInfoRef(columnID), {} /* deleteInfo */); } } } diff --git a/src/storage/store/null_column.cpp b/src/storage/store/null_column.cpp index 3dbd9761cc2..352689bdcef 100644 --- a/src/storage/store/null_column.cpp +++ b/src/storage/store/null_column.cpp @@ -17,8 +17,8 @@ struct NullColumnFunc { auto value = ConstantCompression::getValue(metadata); resultVector->setNullRange(posInVector, numValuesToRead, value); } else { - resultVector->setNullFromBits( - (uint64_t*)frame, pageCursor.elemPosInPage, posInVector, numValuesToRead); + resultVector->setNullFromBits((uint64_t*)frame, pageCursor.elemPosInPage, posInVector, + numValuesToRead); } } @@ -46,8 +46,8 @@ NullColumn::NullColumn(std::string name, page_idx_t metaDAHPageIdx, BMFileHandle batchLookupFunc = nullptr; } -void NullColumn::scan( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void NullColumn::scan(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { if (propertyStatistics.mayHaveNull(*transaction)) { scanInternal(transaction, nodeIDVector, resultVector); } else { @@ -62,8 +62,8 @@ void NullColumn::scan(transaction::Transaction* transaction, node_group_idx_t no Column::scan(transaction, nodeGroupIdx, startOffsetInGroup, endOffsetInGroup, resultVector, offsetInVector); } else { - resultVector->setNullRange( - offsetInVector, endOffsetInGroup - startOffsetInGroup, false /*set non-null*/); + resultVector->setNullRange(offsetInVector, endOffsetInGroup - startOffsetInGroup, + false /*set non-null*/); } } @@ -85,8 +85,8 @@ void NullColumn::scan(transaction::Transaction* transaction, node_group_idx_t no } } -void NullColumn::lookup( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void NullColumn::lookup(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { if (propertyStatistics.mayHaveNull(*transaction)) { lookupInternal(transaction, nodeIDVector, resultVector); } else { @@ -108,16 +108,16 @@ void NullColumn::append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) { } } -bool NullColumn::isNull( - transaction::Transaction* transaction, node_group_idx_t nodeGroupIdx, offset_t offsetInChunk) { +bool NullColumn::isNull(transaction::Transaction* transaction, node_group_idx_t nodeGroupIdx, + offset_t offsetInChunk) { auto state = getReadState(transaction->getType(), nodeGroupIdx); uint64_t result = false; if (offsetInChunk >= state.metadata.numValues) { return true; } // Must be aligned to an 8-byte chunk for NullMask read to not overflow - Column::scan( - transaction, state, offsetInChunk, offsetInChunk + 1, reinterpret_cast(&result)); + Column::scan(transaction, state, offsetInChunk, offsetInChunk + 1, + reinterpret_cast(&result)); return result; } @@ -125,8 +125,8 @@ void NullColumn::setNull(node_group_idx_t nodeGroupIdx, offset_t offsetInChunk, auto chunkMeta = metadataDA->get(nodeGroupIdx, TransactionType::WRITE); propertyStatistics.setHasNull(DUMMY_WRITE_TRANSACTION); // Must be aligned to an 8-byte chunk for NullMask read to not overflow - auto state = ReadState{ - chunkMeta, chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)}; + auto state = ReadState{chunkMeta, + chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)}; writeValues(state, offsetInChunk, reinterpret_cast(&value)); if (offsetInChunk >= chunkMeta.numValues) { chunkMeta.numValues = offsetInChunk + 1; @@ -147,8 +147,8 @@ void NullColumn::write(node_group_idx_t nodeGroupIdx, offset_t offsetInChunk, } } -void NullColumn::write(node_group_idx_t nodeGroupIdx, offset_t offsetInChunk, - kuzu::storage::ColumnChunk* data, offset_t dataOffset, length_t numValues) { +void NullColumn::write(node_group_idx_t nodeGroupIdx, offset_t offsetInChunk, ColumnChunk* data, + offset_t dataOffset, length_t numValues) { auto state = getReadState(TransactionType::WRITE, nodeGroupIdx); writeValues(state, offsetInChunk, data->getData(), dataOffset, numValues); auto nullChunk = ku_dynamic_cast(data); @@ -163,72 +163,25 @@ void NullColumn::write(node_group_idx_t nodeGroupIdx, offset_t offsetInChunk, } } -bool NullColumn::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo) { - auto metadata = getMetadata(nodeGroupIdx, transaction->getType()); - if (metadata.compMeta.canAlwaysUpdateInPlace()) { - return true; - } - std::vector rowIdxesToRead; - for (auto& [_, rowIdx] : updateInfo) { - rowIdxesToRead.push_back(rowIdx); - } - for (auto& [_, rowIdx] : insertInfo) { - rowIdxesToRead.push_back(rowIdx); - } - std::sort(rowIdxesToRead.begin(), rowIdxesToRead.end()); - for (auto rowIdx : rowIdxesToRead) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - bool value = localVector->getVector()->isNull(offsetInVector); - if (!metadata.compMeta.canUpdateInPlace( - reinterpret_cast(&value), 0, dataType.getPhysicalType())) { - return false; - } - } - return true; -} - -bool NullColumn::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - const std::vector& dstOffsets, ColumnChunk* chunk, offset_t srcOffset) { - KU_ASSERT(chunk->getNullChunk() == nullptr && - chunk->getDataType().getPhysicalType() == PhysicalTypeID::BOOL); - auto metadata = getMetadata(nodeGroupIdx, transaction->getType()); - auto maxDstOffset = getMaxOffset(dstOffsets); - if ((metadata.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType) * - metadata.numPages) < maxDstOffset) { - // Note that for constant compression, `metadata.numPages` will be equal to 0. Thus, this - // function will always return false. - return false; - } - if (metadata.compMeta.canAlwaysUpdateInPlace()) { - return true; - } - auto nullChunk = ku_dynamic_cast(chunk); - for (auto i = 0u; i < dstOffsets.size(); i++) { - bool value = nullChunk->isNull(srcOffset + i); - if (!metadata.compMeta.canUpdateInPlace( - reinterpret_cast(&value), 0, dataType.getPhysicalType())) { - return false; - } - } - return true; -} - void NullColumn::commitLocalChunkInPlace(Transaction* /*transaction*/, - node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo, - const offset_set_t& deleteInfo) { + node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, + const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) { for (auto& [offsetInChunk, rowIdx] : updateInfo) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - write(nodeGroupIdx, offsetInChunk, localVector->getVector(), offsetInVector); + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + auto localChunk = localUpdateChunks[chunkIdx]; + KU_ASSERT(localChunk->getDataType().getPhysicalType() == PhysicalTypeID::BOOL && + !localChunk->getNullChunk()); + write(nodeGroupIdx, offsetInChunk, localChunk, offsetInLocalChunk, 1 /*numValues*/); } for (auto& [offsetInChunk, rowIdx] : insertInfo) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - write(nodeGroupIdx, offsetInChunk, localVector->getVector(), offsetInVector); + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + auto localChunk = localInsertChunks[chunkIdx]; + KU_ASSERT(localChunk->getDataType().getPhysicalType() == PhysicalTypeID::BOOL && + !localChunk->getNullChunk()); + write(nodeGroupIdx, offsetInChunk, localChunk, offsetInLocalChunk, 1 /*numValues*/); } // Set nulls based on deleteInfo. Note that this code path actually only gets executed when // the column is a regular format one. This is not a good design, should be unified with csr diff --git a/src/storage/store/rel_table.cpp b/src/storage/store/rel_table.cpp index def92c61c50..c39e14cc328 100644 --- a/src/storage/store/rel_table.cpp +++ b/src/storage/store/rel_table.cpp @@ -2,6 +2,7 @@ #include "common/cast.h" #include "common/exception/message.h" +#include "storage/local_storage/local_rel_table.h" #include "storage/stats/rels_store_statistics.h" #include "storage/store/rel_table_data.h" @@ -30,37 +31,32 @@ RelTable::RelTable(BMFileHandle* dataFH, BMFileHandle* metadataFH, RelsStoreStat relTableEntry, relsStoreStats, RelDataDirection::BWD, enableCompression); } -void RelTable::read(Transaction* transaction, TableReadState& readState, - ValueVector* inNodeIDVector, const std::vector& outputVectors) { - auto& relReadState = ku_dynamic_cast(readState); - scan(transaction, relReadState, inNodeIDVector, outputVectors); +void RelTable::read(Transaction* transaction, TableReadState& readState) { + auto& relReadState = ku_dynamic_cast(readState); + scan(transaction, relReadState); } -void RelTable::insert(Transaction* transaction, ValueVector* srcNodeIDVector, - ValueVector* dstNodeIDVector, const std::vector& propertyVectors) { - fwdRelTableData->insert(transaction, srcNodeIDVector, dstNodeIDVector, propertyVectors); - bwdRelTableData->insert(transaction, dstNodeIDVector, srcNodeIDVector, propertyVectors); - auto relsStats = ku_dynamic_cast(tablesStatistics); - relsStats->updateNumRelsByValue(tableID, 1); +void RelTable::insert(Transaction* transaction, TableInsertState& insertState) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + if (localTable->insert(insertState)) { + auto relsStats = ku_dynamic_cast(tablesStatistics); + relsStats->updateNumTuplesByValue(tableID, 1); + } } -void RelTable::update(transaction::Transaction* transaction, column_id_t columnID, - ValueVector* srcNodeIDVector, ValueVector* dstNodeIDVector, ValueVector* relIDVector, - ValueVector* propertyVector) { - fwdRelTableData->update(transaction, columnID, srcNodeIDVector, relIDVector, propertyVector); - bwdRelTableData->update(transaction, columnID, dstNodeIDVector, relIDVector, propertyVector); +void RelTable::update(Transaction* transaction, TableUpdateState& updateState) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + localTable->update(updateState); } -void RelTable::delete_(Transaction* transaction, ValueVector* srcNodeIDVector, - ValueVector* dstNodeIDVector, ValueVector* relIDVector) { - auto fwdDeleted = - fwdRelTableData->delete_(transaction, srcNodeIDVector, dstNodeIDVector, relIDVector); - auto bwdDeleted = - bwdRelTableData->delete_(transaction, dstNodeIDVector, srcNodeIDVector, relIDVector); - KU_ASSERT(fwdDeleted == bwdDeleted); - if (fwdDeleted && bwdDeleted) { +void RelTable::delete_(Transaction* transaction, TableDeleteState& deleteState) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + if (localTable->delete_(deleteState)) { auto relsStats = ku_dynamic_cast(tablesStatistics); - relsStats->updateNumRelsByValue(tableID, -1); + relsStats->updateNumTuplesByValue(tableID, -1); } } @@ -71,16 +67,20 @@ void RelTable::detachDelete(Transaction* transaction, RelDataDirection direction direction == RelDataDirection::FWD ? fwdRelTableData.get() : bwdRelTableData.get(); auto reverseTableData = direction == RelDataDirection::FWD ? bwdRelTableData.get() : fwdRelTableData.get(); - auto relDataReadState = std::make_unique(); - initializeReadState(transaction, direction, {0}, srcNodeIDVector, relDataReadState.get()); + std::vector relIDColumns = {REL_ID_COLUMN_ID}; + auto relIDVectors = std::vector{deleteState->dstNodeIDVector.get(), + deleteState->relIDVector.get()}; + auto relReadState = std::make_unique(*srcNodeIDVector, relIDColumns, + relIDVectors, direction); + initializeReadState(transaction, direction, relIDColumns, *srcNodeIDVector, *relReadState); row_idx_t numRelsDeleted = detachDeleteForCSRRels(transaction, tableData, reverseTableData, - srcNodeIDVector, relDataReadState.get(), deleteState); + srcNodeIDVector, relReadState.get(), deleteState); auto relsStats = ku_dynamic_cast(tablesStatistics); - relsStats->updateNumRelsByValue(tableID, -numRelsDeleted); + relsStats->updateNumTuplesByValue(tableID, -numRelsDeleted); } -void RelTable::checkIfNodeHasRels( - Transaction* transaction, RelDataDirection direction, ValueVector* srcNodeIDVector) { +void RelTable::checkIfNodeHasRels(Transaction* transaction, RelDataDirection direction, + ValueVector* srcNodeIDVector) { KU_ASSERT(srcNodeIDVector->state->isFlat()); auto nodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; auto nodeOffset = srcNodeIDVector->getValue(nodeIDPos).offset; @@ -94,54 +94,53 @@ void RelTable::checkIfNodeHasRels( } } +// TODO(Guodong): Rework detach delete to go through local storage. row_idx_t RelTable::detachDeleteForCSRRels(Transaction* transaction, RelTableData* tableData, RelTableData* reverseTableData, ValueVector* srcNodeIDVector, - RelDataReadState* relDataReadState, RelDetachDeleteState* deleteState) { + RelTableReadState* relDataReadState, RelDetachDeleteState* deleteState) { row_idx_t numRelsDeleted = 0; auto tempState = deleteState->dstNodeIDVector->state.get(); while (relDataReadState->hasMoreToRead(transaction)) { - scan(transaction, *relDataReadState, srcNodeIDVector, - {deleteState->dstNodeIDVector.get(), deleteState->relIDVector.get()}); + scan(transaction, *relDataReadState); auto numRelsScanned = tempState->selVector->selectedSize; - tempState->selVector->resetSelectorToValuePosBufferWithSize(1); + tempState->selVector->setToFiltered(1); for (auto i = 0u; i < numRelsScanned; i++) { tempState->selVector->selectedPositions[0] = i; - auto deleted = tableData->delete_(transaction, srcNodeIDVector, + auto deleted = + tableData->delete_(transaction, srcNodeIDVector, deleteState->relIDVector.get()); + auto reverseDeleted = reverseTableData->delete_(transaction, deleteState->dstNodeIDVector.get(), deleteState->relIDVector.get()); - auto reverseDeleted = - reverseTableData->delete_(transaction, deleteState->dstNodeIDVector.get(), - srcNodeIDVector, deleteState->relIDVector.get()); KU_ASSERT(deleted == reverseDeleted); numRelsDeleted += (deleted && reverseDeleted); } - tempState->selVector->resetSelectorToUnselectedWithSize(DEFAULT_VECTOR_CAPACITY); + tempState->selVector->setToUnfiltered(); } return numRelsDeleted; } -void RelTable::scan(Transaction* transaction, RelDataReadState& scanState, - ValueVector* inNodeIDVector, const std::vector& outputVectors) { +void RelTable::scan(Transaction* transaction, RelTableReadState& scanState) { auto tableData = getDirectedTableData(scanState.direction); - tableData->scan(transaction, scanState, inNodeIDVector, outputVectors); + tableData->scan(transaction, *scanState.dataReadState, scanState.nodeIDVector, + scanState.outputVectors); } -void RelTable::addColumn( - Transaction* transaction, const Property& property, ValueVector* defaultValueVector) { +void RelTable::addColumn(Transaction* transaction, const Property& property, + ValueVector* defaultValueVector) { auto relsStats = ku_dynamic_cast(tablesStatistics); relsStats->setPropertyStatisticsForTable(tableID, property.getPropertyID(), PropertyStatistics{!defaultValueVector->hasNoNullsGuarantee()}); relsStats->addMetadataDAHInfo(tableID, *property.getDataType()); fwdRelTableData->addColumn(transaction, RelDataDirectionUtils::relDirectionToString(RelDataDirection::FWD), - fwdRelTableData->getAdjColumn()->getMetadataDA(), - *relsStats->getPropertyMetadataDAHInfo( - transaction, tableID, fwdRelTableData->getNumColumns(), RelDataDirection::FWD), + fwdRelTableData->getNbrIDColumn()->getMetadataDA(), + *relsStats->getColumnMetadataDAHInfo(transaction, tableID, fwdRelTableData->getNumColumns(), + RelDataDirection::FWD), property, defaultValueVector, relsStats); bwdRelTableData->addColumn(transaction, RelDataDirectionUtils::relDirectionToString(RelDataDirection::BWD), - bwdRelTableData->getAdjColumn()->getMetadataDA(), - *relsStats->getPropertyMetadataDAHInfo( - transaction, tableID, bwdRelTableData->getNumColumns(), RelDataDirection::BWD), + bwdRelTableData->getNbrIDColumn()->getMetadataDA(), + *relsStats->getColumnMetadataDAHInfo(transaction, tableID, bwdRelTableData->getNumColumns(), + RelDataDirection::BWD), property, defaultValueVector, relsStats); // TODO(Guodong): addColumn is not going through localStorage design for now. So it needs to add // tableID into the wal's updated table set separately, as it won't trigger prepareCommit. @@ -150,12 +149,21 @@ void RelTable::addColumn( void RelTable::prepareCommit(Transaction* transaction, LocalTable* localTable) { wal->addToUpdatedTables(tableID); - fwdRelTableData->prepareLocalTableToCommit(transaction, localTable->getLocalTableData(0)); - bwdRelTableData->prepareLocalTableToCommit(transaction, localTable->getLocalTableData(1)); + auto localRelTable = ku_dynamic_cast(localTable); + fwdRelTableData->prepareLocalTableToCommit(transaction, + localRelTable->getTableData(RelDataDirection::FWD)); + bwdRelTableData->prepareLocalTableToCommit(transaction, + localRelTable->getTableData(RelDataDirection::BWD)); + prepareCommit(); +} + +void RelTable::prepareRollback(LocalTable* localTable) { + localTable->clear(); } -void RelTable::prepareRollback(LocalTableData* localTableData) { - localTableData->clear(); +void RelTable::prepareCommit() { + fwdRelTableData->prepareCommit(); + bwdRelTableData->prepareCommit(); } void RelTable::checkpointInMemory() { diff --git a/src/storage/store/rel_table_data.cpp b/src/storage/store/rel_table_data.cpp index ef3bcea03c8..1ce731568e9 100644 --- a/src/storage/store/rel_table_data.cpp +++ b/src/storage/store/rel_table_data.cpp @@ -21,13 +21,13 @@ RelDataReadState::RelDataReadState() bool RelDataReadState::hasMoreToReadFromLocalStorage() const { KU_ASSERT(localNodeGroup); - return posInCurrentCSR < localNodeGroup->getRelNGInfo()->getNumInsertedTuples( - currentNodeOffset - startNodeOffset); + return posInCurrentCSR < + localNodeGroup->getNumInsertedRels(currentNodeOffset - startNodeOffset); } bool RelDataReadState::trySwitchToLocalStorage() { - if (localNodeGroup && localNodeGroup->getRelNGInfo()->getNumInsertedTuples( - currentNodeOffset - startNodeOffset) > 0) { + if (localNodeGroup && + localNodeGroup->getNumInsertedRels(currentNodeOffset - startNodeOffset) > 0) { readFromLocalStorage = true; posInCurrentCSR = 0; return true; @@ -35,7 +35,7 @@ bool RelDataReadState::trySwitchToLocalStorage() { return false; } -bool RelDataReadState::hasMoreToRead(transaction::Transaction* transaction) { +bool RelDataReadState::hasMoreToRead(Transaction* transaction) { if (transaction->isWriteTransaction()) { if (readFromLocalStorage) { // Already read from local storage. Check if there are more in local storage. @@ -71,8 +71,8 @@ std::pair RelDataReadState::getStartAndEndOffset() { return {startOffset, startOffset + numRowsToRead}; } -offset_t CSRHeaderColumns::getNumNodes( - Transaction* transaction, node_group_idx_t nodeGroupIdx) const { +offset_t CSRHeaderColumns::getNumNodes(Transaction* transaction, + node_group_idx_t nodeGroupIdx) const { auto numPersistentNodeGroups = offset->getNumNodeGroups(transaction); return nodeGroupIdx >= numPersistentNodeGroups ? 0 : @@ -139,21 +139,23 @@ RelTableData::RelTableData(BMFileHandle* dataFH, BMFileHandle* metadataFH, csrHeaderColumns.length = std::make_unique(csrLengthColumnName, *LogicalType::UINT64(), *csrLengthMetadataDAHInfo, dataFH, metadataFH, bufferManager, wal, &DUMMY_WRITE_TRANSACTION, RWPropertyStats::empty(), enableCompression, false /* requireNUllColumn */); - // Adj column. - auto adjMetadataDAHInfo = - relsStoreStats->getAdjMetadataDAHInfo(&DUMMY_WRITE_TRANSACTION, tableID, direction); - auto adjColName = StorageUtils::getColumnName( - "", StorageUtils::ColumnType::ADJ, RelDataDirectionUtils::relDirectionToString(direction)); - adjColumn = ColumnFactory::createColumn(adjColName, *LogicalType::INTERNAL_ID(), - *adjMetadataDAHInfo, dataFH, metadataFH, bufferManager, wal, &DUMMY_WRITE_TRANSACTION, - RWPropertyStats::empty(), enableCompression); - // Property columns. + // Columns (nbrID + properties). auto& properties = tableEntry->getPropertiesRef(); - columns.reserve(properties.size()); + columns.reserve(properties.size() + 1); + auto nbrIDMetadataDAHInfo = relsStoreStats->getColumnMetadataDAHInfo(&DUMMY_WRITE_TRANSACTION, + tableID, NBR_ID_COLUMN_ID, direction); + auto nbrIDColName = StorageUtils::getColumnName("NBR_ID", StorageUtils::ColumnType::DEFAULT, + RelDataDirectionUtils::relDirectionToString(direction)); + auto nbrIDColumn = std::make_unique(nbrIDColName, *nbrIDMetadataDAHInfo, + dataFH, metadataFH, bufferManager, wal, &DUMMY_WRITE_TRANSACTION, RWPropertyStats::empty(), + enableCompression); + columns.push_back(std::move(nbrIDColumn)); + // Property columns. for (auto i = 0u; i < properties.size(); i++) { auto& property = properties[i]; - auto metadataDAHInfo = relsStoreStats->getPropertyMetadataDAHInfo( - &DUMMY_WRITE_TRANSACTION, tableID, i, direction); + auto columnID = tableEntry->getColumnID(property.getPropertyID()); + auto metadataDAHInfo = relsStoreStats->getColumnMetadataDAHInfo(&DUMMY_WRITE_TRANSACTION, + tableID, columnID, direction); auto colName = StorageUtils::getColumnName(property.getName(), StorageUtils::ColumnType::DEFAULT, RelDataDirectionUtils::relDirectionToString(direction)); @@ -161,65 +163,67 @@ RelTableData::RelTableData(BMFileHandle* dataFH, BMFileHandle* metadataFH, *metadataDAHInfo, dataFH, metadataFH, bufferManager, wal, &DUMMY_WRITE_TRANSACTION, RWPropertyStats(relsStoreStats, tableID, property.getPropertyID()), enableCompression)); } - // Set common tableID for adjColumn and relIDColumn. + // Set common tableID for nbrIDColumn and relIDColumn. auto nbrTableID = ku_dynamic_cast(tableEntry) ->getNbrTableID(direction); - dynamic_cast(adjColumn.get())->setCommonTableID(nbrTableID); - dynamic_cast(columns[REL_ID_COLUMN_ID].get())->setCommonTableID(tableID); + ku_dynamic_cast(columns[NBR_ID_COLUMN_ID].get()) + ->setCommonTableID(nbrTableID); + ku_dynamic_cast(columns[REL_ID_COLUMN_ID].get()) + ->setCommonTableID(tableID); packedCSRInfo = PackedCSRInfo(); } void RelTableData::initializeReadState(Transaction* transaction, std::vector columnIDs, - ValueVector* inNodeIDVector, RelDataReadState* readState) { - readState->direction = direction; - readState->columnIDs = std::move(columnIDs); + const ValueVector& inNodeIDVector, RelDataReadState& readState) { + readState.direction = direction; + readState.columnIDs.clear(); + readState.columnIDs.push_back(NBR_ID_COLUMN_ID); + readState.columnIDs.insert(readState.columnIDs.end(), columnIDs.begin(), columnIDs.end()); // Reset to read from persistent storage. - readState->readFromLocalStorage = false; + readState.readFromLocalStorage = false; auto nodeOffset = - inNodeIDVector->readNodeOffset(inNodeIDVector->state->selVector->selectedPositions[0]); + inNodeIDVector.readNodeOffset(inNodeIDVector.state->selVector->selectedPositions[0]); auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(nodeOffset); auto startNodeOffset = StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); // Reset to read from beginning for the csr of the new node offset. - readState->posInCurrentCSR = 0; - if (readState->isOutOfRange(nodeOffset)) { + readState.posInCurrentCSR = 0; + if (readState.isOutOfRange(nodeOffset)) { // Scan csr offsets and populate csr list entries for the new node group. - readState->startNodeOffset = startNodeOffset; - csrHeaderColumns.scan(transaction, nodeGroupIdx, readState->csrHeaderChunks); - KU_ASSERT(readState->csrHeaderChunks.offset->getNumValues() == - readState->csrHeaderChunks.length->getNumValues()); - readState->numNodes = readState->csrHeaderChunks.offset->getNumValues(); - readState->populateCSRListEntries(); + readState.startNodeOffset = startNodeOffset; + csrHeaderColumns.scan(transaction, nodeGroupIdx, readState.csrHeaderChunks); + KU_ASSERT(readState.csrHeaderChunks.offset->getNumValues() == + readState.csrHeaderChunks.length->getNumValues()); + readState.numNodes = readState.csrHeaderChunks.offset->getNumValues(); + readState.populateCSRListEntries(); if (transaction->isWriteTransaction()) { - readState->localNodeGroup = getLocalNodeGroup(transaction, nodeGroupIdx); + readState.localNodeGroup = getLocalNodeGroup(transaction, nodeGroupIdx); } } - if (nodeOffset != readState->currentNodeOffset) { - readState->currentNodeOffset = nodeOffset; + if (nodeOffset != readState.currentNodeOffset) { + readState.currentNodeOffset = nodeOffset; } } -void RelTableData::scan(Transaction* transaction, TableReadState& readState, - ValueVector* inNodeIDVector, const std::vector& outputVectors) { - auto& relReadState = ku_dynamic_cast(readState); +void RelTableData::scan(Transaction* transaction, TableDataReadState& readState, + const ValueVector& inNodeIDVector, const std::vector& outputVectors) { + auto& relReadState = ku_dynamic_cast(readState); if (relReadState.readFromLocalStorage) { auto offsetInChunk = relReadState.currentNodeOffset - relReadState.startNodeOffset; KU_ASSERT(relReadState.localNodeGroup); - auto numValuesRead = relReadState.localNodeGroup->scanCSR( - offsetInChunk, relReadState.posInCurrentCSR, relReadState.columnIDs, outputVectors); + auto numValuesRead = relReadState.localNodeGroup->scanCSR(offsetInChunk, + relReadState.posInCurrentCSR, relReadState.columnIDs, outputVectors); relReadState.posInCurrentCSR += numValuesRead; return; } auto [startOffset, endOffset] = relReadState.getStartAndEndOffset(); auto numRowsToRead = endOffset - startOffset; - outputVectors[0]->state->selVector->resetSelectorToUnselectedWithSize(numRowsToRead); + outputVectors[0]->state->selVector->setToUnfiltered(numRowsToRead); outputVectors[0]->state->setOriginalSize(numRowsToRead); auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(relReadState.currentNodeOffset); - adjColumn->scan(transaction, nodeGroupIdx, startOffset, endOffset, outputVectors[0], - 0 /* offsetInVector */); auto relIDVectorIdx = INVALID_VECTOR_IDX; for (auto i = 0u; i < relReadState.columnIDs.size(); i++) { auto columnID = relReadState.columnIDs[i]; - auto outputVectorId = i + 1; // Skip output from adj column. + auto outputVectorId = i; // Skip output from nbrID column. if (columnID == INVALID_COLUMN_ID) { outputVectors[outputVectorId]->setAllNull(); continue; @@ -227,57 +231,37 @@ void RelTableData::scan(Transaction* transaction, TableReadState& readState, if (columnID == REL_ID_COLUMN_ID) { relIDVectorIdx = outputVectorId; } - columns[relReadState.columnIDs[i]]->scan(transaction, nodeGroupIdx, startOffset, endOffset, + getColumn(columnID)->scan(transaction, nodeGroupIdx, startOffset, endOffset, outputVectors[outputVectorId], 0 /* offsetInVector */); } if (transaction->isWriteTransaction() && relReadState.localNodeGroup) { auto nodeOffset = - inNodeIDVector->readNodeOffset(inNodeIDVector->state->selVector->selectedPositions[0]); + inNodeIDVector.readNodeOffset(inNodeIDVector.state->selVector->selectedPositions[0]); KU_ASSERT(relIDVectorIdx != INVALID_VECTOR_IDX); auto relIDVector = outputVectors[relIDVectorIdx]; - relReadState.localNodeGroup->applyLocalChangesForCSRColumns( + relReadState.localNodeGroup->applyLocalChangesToScannedVectors( nodeOffset - relReadState.startNodeOffset, relReadState.columnIDs, relIDVector, outputVectors); } } -void RelTableData::lookup(Transaction* /*transaction*/, TableReadState& /*readState*/, - ValueVector* /*inNodeIDVector*/, const std::vector& /*outputVectors*/) { +void RelTableData::lookup(Transaction* /*transaction*/, TableDataReadState& /*readState*/, + const ValueVector& /*inNodeIDVector*/, const std::vector& /*outputVectors*/) { KU_ASSERT(false); } -void RelTableData::insert(transaction::Transaction* transaction, ValueVector* srcNodeIDVector, - ValueVector* dstNodeIDVector, const std::vector& propertyVectors) { - auto localTableData = ku_dynamic_cast( - transaction->getLocalStorage()->getOrCreateLocalTableData( - tableID, columns, TableType::REL, getDataIdxFromDirection(direction), multiplicity)); - auto checkPersistent = - localTableData->insert(srcNodeIDVector, dstNodeIDVector, propertyVectors); - if (checkPersistent && multiplicity == common::RelMultiplicity::ONE) { - checkRelMultiplicityConstraint(transaction, srcNodeIDVector); - } -} - -void RelTableData::update(transaction::Transaction* transaction, column_id_t columnID, - ValueVector* srcNodeIDVector, ValueVector* relIDVector, ValueVector* propertyVector) { - KU_ASSERT(columnID < columns.size() && columnID != REL_ID_COLUMN_ID); - auto localTableData = ku_dynamic_cast( - transaction->getLocalStorage()->getOrCreateLocalTableData( - tableID, columns, TableType::REL, getDataIdxFromDirection(direction), multiplicity)); - localTableData->update(srcNodeIDVector, relIDVector, columnID, propertyVector); -} - bool RelTableData::delete_(Transaction* transaction, ValueVector* srcNodeIDVector, - ValueVector* dstNodeIDVector, ValueVector* relIDVector) { - auto localTableData = ku_dynamic_cast( - transaction->getLocalStorage()->getOrCreateLocalTableData( - tableID, columns, TableType::REL, getDataIdxFromDirection(direction), multiplicity)); - return localTableData->delete_(srcNodeIDVector, dstNodeIDVector, relIDVector); + ValueVector* relIDVector) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID, + LocalStorage::NotExistAction::CREATE); + auto localRelTable = ku_dynamic_cast(localTable); + auto localTableData = localRelTable->getTableData(direction); + return localTableData->delete_(srcNodeIDVector, relIDVector); } -void RelTableData::checkRelMultiplicityConstraint( - Transaction* transaction, ValueVector* srcNodeIDVector) const { - KU_ASSERT(srcNodeIDVector->state->isFlat() && multiplicity == common::RelMultiplicity::ONE); +void RelTableData::checkRelMultiplicityConstraint(Transaction* transaction, + ValueVector* srcNodeIDVector) const { + KU_ASSERT(srcNodeIDVector->state->isFlat() && multiplicity == RelMultiplicity::ONE); auto nodeIDPos = srcNodeIDVector->state->selVector->selectedPositions[0]; auto nodeOffset = srcNodeIDVector->getValue(nodeIDPos).offset; if (checkIfNodeHasRels(transaction, nodeOffset)) { @@ -301,27 +285,26 @@ bool RelTableData::checkIfNodeHasRels(Transaction* transaction, offset_t nodeOff return length > 0; } -void RelTableData::append(NodeGroup* nodeGroup) { - auto csrNodeGroup = ku_dynamic_cast(nodeGroup); +void RelTableData::append(ChunkedNodeGroup* nodeGroup) { + auto csrNodeGroup = ku_dynamic_cast(nodeGroup); csrHeaderColumns.append(csrNodeGroup->getCSRHeader(), nodeGroup->getNodeGroupIdx()); - adjColumn->append(nodeGroup->getColumnChunk(0), nodeGroup->getNodeGroupIdx()); for (auto columnID = 0u; columnID < columns.size(); columnID++) { - columns[columnID]->append( - nodeGroup->getColumnChunk(columnID + 1), nodeGroup->getNodeGroupIdx()); + getColumn(columnID)->append(&nodeGroup->getColumnChunkUnsafe(columnID), + nodeGroup->getNodeGroupIdx()); } } -static length_t getGapSizeForNode(const CSRHeaderChunks& header, offset_t nodeOffset) { +static length_t getGapSizeForNode(const ChunkedCSRHeader& header, offset_t nodeOffset) { return header.getEndCSROffset(nodeOffset) - header.getStartCSROffset(nodeOffset) - header.getCSRLength(nodeOffset); } -static length_t getRegionCapacity(const CSRHeaderChunks& header, PackedCSRRegion region) { +static length_t getRegionCapacity(const ChunkedCSRHeader& header, PackedCSRRegion region) { auto [startNodeOffset, endNodeOffset] = region.getNodeOffsetBoundaries(); return header.getEndCSROffset(endNodeOffset) - header.getStartCSROffset(startNodeOffset); } -length_t RelTableData::getNewRegionSize(const CSRHeaderChunks& header, +length_t RelTableData::getNewRegionSize(const ChunkedCSRHeader& header, const std::vector& sizeChangesPerSegment, PackedCSRRegion& region) { auto [startNodeOffsetInNG, endNodeOffsetInNG] = region.getNodeOffsetBoundaries(); endNodeOffsetInNG = std::min(endNodeOffsetInNG, header.offset->getNumValues() - 1); @@ -338,8 +321,8 @@ static PackedCSRRegion upgradeLevel(const PackedCSRRegion& region) { return PackedCSRRegion{regionIdx, region.level + 1}; } -static uint64_t findPosOfRelIDFromArray( - ColumnChunk* relIDInRegion, offset_t startPos, offset_t endPos, offset_t relOffset) { +static uint64_t findPosOfRelIDFromArray(ColumnChunk* relIDInRegion, offset_t startPos, + offset_t endPos, offset_t relOffset) { KU_ASSERT(endPos <= relIDInRegion->getNumValues()); for (auto i = startPos; i < endPos; i++) { if (relIDInRegion->getValue(i) == relOffset) { @@ -349,8 +332,8 @@ static uint64_t findPosOfRelIDFromArray( return UINT64_MAX; } -offset_t RelTableData::findCSROffsetInRegion( - const PersistentState& persistentState, offset_t nodeOffset, offset_t relOffset) const { +offset_t RelTableData::findCSROffsetInRegion(const PersistentState& persistentState, + offset_t nodeOffset, offset_t relOffset) const { auto startPos = persistentState.header.getStartCSROffset(nodeOffset) - persistentState.leftCSROffset; auto endPos = startPos + persistentState.header.getCSRLength(nodeOffset); @@ -360,6 +343,14 @@ offset_t RelTableData::findCSROffsetInRegion( return posInCSRList + persistentState.leftCSROffset; } +bool RelTableData::isNewNodeGroup(Transaction* transaction, node_group_idx_t nodeGroupIdx) const { + if (nodeGroupIdx >= getNumNodeGroups(transaction) || + getNbrIDColumn()->getMetadata(nodeGroupIdx, transaction->getType()).numValues == 0) { + return true; + } + return false; +} + void RelTableData::prepareLocalTableToCommit(Transaction* transaction, LocalTableData* localTable) { auto localRelTableData = ku_dynamic_cast(localTable); for (auto& [nodeGroupIdx, nodeGroup] : localRelTableData->nodeGroups) { @@ -368,7 +359,7 @@ void RelTableData::prepareLocalTableToCommit(Transaction* transaction, LocalTabl } } -bool RelTableData::isWithinDensityBound(const CSRHeaderChunks& header, +bool RelTableData::isWithinDensityBound(const ChunkedCSRHeader& header, const std::vector& sizeChangesPerSegment, PackedCSRRegion& region) { auto sizeInRegion = getNewRegionSize(header, sizeChangesPerSegment, region); auto capacityInRegion = getRegionCapacity(header, region); @@ -385,66 +376,44 @@ double RelTableData::getHighDensity(uint64_t level) const { (packedCSRInfo.highDensityStep * (double)(packedCSRInfo.calibratorTreeHeight - level)); } -static vector_idx_t getSegmentIdx(offset_t offset) { - return offset >> StorageConstants::CSR_SEGMENT_SIZE_LOG2; -} - -void RelTableData::LocalState::initChangesPerSegment() { - auto numSegments = StorageConstants::NODE_GROUP_SIZE / StorageConstants::CSR_SEGMENT_SIZE; - sizeChangesPerSegment.resize(numSegments, 0 /*initValue*/); - hasChangesPerSegment.resize(numSegments, false /*initValue*/); - auto relNGInfo = localNG->getRelNGInfo(); - for (auto& [offset, insertions] : relNGInfo->adjInsertInfo) { - auto segmentIdx = getSegmentIdx(offset); - sizeChangesPerSegment[segmentIdx] += insertions.size(); - hasChangesPerSegment[segmentIdx] = true; - } - for (auto& [offset, deletions] : relNGInfo->deleteInfo) { - auto segmentIdx = getSegmentIdx(offset); - sizeChangesPerSegment[segmentIdx] -= deletions.size(); - hasChangesPerSegment[segmentIdx] = true; - } - for (auto& updateInfoPerColumn : relNGInfo->updateInfoPerChunk) { - for (auto& [offset, updates] : updateInfoPerColumn) { - auto segmentIdx = getSegmentIdx(offset); - hasChangesPerSegment[segmentIdx] = true; - } - } +RelTableData::LocalState::LocalState(LocalRelNG* localNG) : localNG{localNG} { + localNG->getChangesPerCSRSegment(sizeChangesPerSegment, hasChangesPerSegment); } void RelTableData::applyUpdatesToChunk(const PersistentState& persistentState, - const PackedCSRRegion& region, LocalVectorCollection* localChunk, - const update_insert_info_t& updateInfo, ColumnChunk* chunk) { - std::map csrOffsetInRegionToRowIdx; - auto [leftNodeBoundary, rightNodeBoundary] = region.getNodeOffsetBoundaries(); - for (auto& [nodeOffset, updates] : updateInfo) { + LocalState& localState, const ChunkCollection& localChunk, ColumnChunk* chunk, + column_id_t columnID) { + offset_to_row_idx_t csrOffsetInRegionToRowIdx; + auto [leftNodeBoundary, rightNodeBoundary] = localState.region.getNodeOffsetBoundaries(); + auto& updateChunk = localState.localNG->getUpdateChunks(columnID); + for (auto& [nodeOffset, updates] : updateChunk.getSrcNodeOffsetToRelOffsets()) { if (nodeOffset < leftNodeBoundary || nodeOffset > rightNodeBoundary) { continue; } - for (auto [relID, rowIdx] : updates) { - auto csrOffsetInRegion = findCSROffsetInRegion(persistentState, nodeOffset, relID); - csrOffsetInRegionToRowIdx[csrOffsetInRegion] = rowIdx; + for (auto relOffset : updates) { + auto csrOffsetInRegion = findCSROffsetInRegion(persistentState, nodeOffset, relOffset); + csrOffsetInRegionToRowIdx[csrOffsetInRegion] = + updateChunk.getRowIdxFromOffset(relOffset); } } Column::applyLocalChunkToColumnChunk(localChunk, chunk, csrOffsetInRegionToRowIdx); } void RelTableData::applyInsertionsToChunk(const PersistentState& persistentState, - const LocalState& localState, LocalVectorCollection* localChunk, - const update_insert_info_t& insertInfo, ColumnChunk* newChunk) { - std::map csrOffsetToRowIdx; + const LocalState& localState, const ChunkCollection& localChunk, ColumnChunk* newChunk) { + offset_to_row_idx_t csrOffsetToRowIdx; auto [leftNodeBoundary, rightNodeBoundary] = localState.region.getNodeOffsetBoundaries(); - for (auto& [nodeOffset, insertions] : insertInfo) { + auto& insertChunks = localState.localNG->insertChunks; + for (auto& [nodeOffset, insertions] : insertChunks.getSrcNodeOffsetToRelOffsets()) { if (nodeOffset < leftNodeBoundary || nodeOffset > rightNodeBoundary) { continue; } - // TODO: Separate this into a function. auto csrOffsetInRegion = localState.header.getStartCSROffset(nodeOffset) + persistentState.header.getCSRLength(nodeOffset) - localState.leftCSROffset; - for (auto& [_, rowIdx] : insertions) { + for (auto relOffset : insertions) { KU_ASSERT(csrOffsetInRegion != UINT64_MAX); - csrOffsetToRowIdx[csrOffsetInRegion++] = rowIdx; + csrOffsetToRowIdx[csrOffsetInRegion++] = insertChunks.getRowIdxFromOffset(relOffset); } } Column::applyLocalChunkToColumnChunk(localChunk, newChunk, csrOffsetToRowIdx); @@ -453,8 +422,9 @@ void RelTableData::applyInsertionsToChunk(const PersistentState& persistentState // TODO(Guodong): This should be refactored to share the same control logic with // `applyDeletionsToColumn`. void RelTableData::applyDeletionsToChunk(const PersistentState& persistentState, - const LocalState& localState, const delete_info_t& deleteInfo, ColumnChunk* chunk) { - for (auto& [offset, deletions] : deleteInfo) { + const LocalState& localState, ColumnChunk* chunk) { + auto& deleteInfo = localState.localNG->deleteInfo; + for (auto& [offset, deletions] : deleteInfo.getSrcNodeOffsetToRelOffsetVec()) { if (localState.region.isOutOfBoundary(offset)) { continue; } @@ -488,27 +458,26 @@ void RelTableData::applyDeletionsToChunk(const PersistentState& persistentState, void RelTableData::distributeAndUpdateColumn(Transaction* transaction, node_group_idx_t nodeGroupIdx, column_id_t columnID, const PersistentState& persistentState, LocalState& localState) { - KU_ASSERT(columnID < columns.size() || columnID == INVALID_COLUMN_ID); + auto column = getColumn(columnID); auto [leftNodeBoundary, rightNodeBoundary] = localState.region.getNodeOffsetBoundaries(); - auto column = columnID == INVALID_COLUMN_ID ? adjColumn.get() : columns[columnID].get(); KU_ASSERT(localState.regionCapacity >= (localState.rightCSROffset - localState.leftCSROffset)); // First, scan the whole region to a temp chunk. auto oldSize = persistentState.rightCSROffset - persistentState.leftCSROffset + 1; - auto chunk = ColumnChunkFactory::createColumnChunk( - *column->getDataType().copy(), enableCompression, oldSize); + auto chunk = ColumnChunkFactory::createColumnChunk(*column->getDataType().copy(), + enableCompression, oldSize); column->scan(transaction, nodeGroupIdx, chunk.get(), persistentState.leftCSROffset, persistentState.rightCSROffset + 1); - auto relNGInfo = localState.localNG->getRelNGInfo(); - auto& updateInfo = relNGInfo->getUpdateInfo(columnID); - auto localChunk = getLocalChunk(localState, columnID); - applyUpdatesToChunk(persistentState, localState.region, localChunk, updateInfo, chunk.get()); - applyDeletionsToChunk(persistentState, localState, relNGInfo->deleteInfo, chunk.get()); + auto localUpdateChunk = + localState.localNG->getUpdateChunks(columnID).getLocalChunk(0 /*columnID*/); + applyUpdatesToChunk(persistentState, localState, localUpdateChunk, chunk.get(), columnID); + applyDeletionsToChunk(persistentState, localState, chunk.get()); // Second, create a new temp chunk for the region. auto newSize = localState.rightCSROffset - localState.leftCSROffset + 1; - auto newChunk = ColumnChunkFactory::createColumnChunk( - *column->getDataType().copy(), enableCompression, newSize); - auto maxNumNodesToDistribute = std::min( - rightNodeBoundary - leftNodeBoundary + 1, persistentState.header.offset->getNumValues()); + auto newChunk = ColumnChunkFactory::createColumnChunk(*column->getDataType().copy(), + enableCompression, newSize); + newChunk->getNullChunk()->resetToAllNull(); + auto maxNumNodesToDistribute = std::min(rightNodeBoundary - leftNodeBoundary + 1, + persistentState.header.offset->getNumValues()); // Third, copy the rels to the new chunk. for (auto i = 0u; i < maxNumNodesToDistribute; i++) { auto nodeOffset = i + leftNodeBoundary; @@ -520,21 +489,21 @@ void RelTableData::distributeAndUpdateColumn(Transaction* transaction, } auto newCSROffsetInRegion = localState.header.getStartCSROffset(nodeOffset) - localState.leftCSROffset; - KU_ASSERT(!relNGInfo->deleteInfo.contains(nodeOffset)); KU_ASSERT(newCSROffsetInRegion >= newChunk->getNumValues()); newChunk->copy(chunk.get(), csrOffsetInRegion, newCSROffsetInRegion, length); } - auto& insertInfo = relNGInfo->getInsertInfo(columnID); - applyInsertionsToChunk(persistentState, localState, localChunk, insertInfo, newChunk.get()); + auto insertLocalChunk = localState.localNG->insertChunks.getLocalChunk(columnID); + applyInsertionsToChunk(persistentState, localState, insertLocalChunk, newChunk.get()); std::vector dstOffsets; dstOffsets.resize(newChunk->getNumValues()); fillSequence(dstOffsets, localState.leftCSROffset); - column->prepareCommitForChunk( - transaction, nodeGroupIdx, dstOffsets, newChunk.get(), 0 /*srcOffset*/); + KU_ASSERT(newChunk->sanityCheck()); + column->prepareCommitForChunk(transaction, nodeGroupIdx, dstOffsets, newChunk.get(), + 0 /*srcOffset*/); } -std::vector RelTableData::findRegions( - const CSRHeaderChunks& headerChunks, LocalState& localState) { +std::vector RelTableData::findRegions(const ChunkedCSRHeader& headerChunks, + LocalState& localState) { std::vector regions; auto segmentIdx = 0u; auto numSegments = StorageConstants::NODE_GROUP_SIZE / StorageConstants::CSR_SEGMENT_SIZE; @@ -566,35 +535,32 @@ std::vector RelTableData::findRegions( void RelTableData::updateRegion(Transaction* transaction, node_group_idx_t nodeGroupIdx, PersistentState& persistentState, LocalState& localState) { - auto localInfo = localState.localNG->getRelNGInfo(); // Scan RelID column chunk when there are updates or deletions. // TODO(Guodong): Should track for each region if it has updates or deletions. - if (localInfo->hasUpdates() || !localInfo->deleteInfo.empty()) { + if (localState.localNG->hasUpdatesOrDeletions()) { // NOTE: There is an implicit trick happening. Due to the mismatch of storage type and // in-memory representation of INTERNAL_ID, we only store offset as INT64 on disk. Here // we directly read relID's offset part from disk into an INT64 column chunk. - persistentState.relIDChunk = ColumnChunkFactory::createColumnChunk( - *LogicalType::INT64(), enableCompression, localState.regionCapacity); - columns[REL_ID_COLUMN_ID]->scan(transaction, nodeGroupIdx, persistentState.relIDChunk.get(), - persistentState.leftCSROffset, persistentState.rightCSROffset + 1); + persistentState.relIDChunk = ColumnChunkFactory::createColumnChunk(*LogicalType::INT64(), + enableCompression, localState.regionCapacity); + getColumn(REL_ID_COLUMN_ID) + ->scan(transaction, nodeGroupIdx, persistentState.relIDChunk.get(), + persistentState.leftCSROffset, persistentState.rightCSROffset + 1); } if (localState.region.level == 0) { - updateColumn(transaction, nodeGroupIdx, INVALID_COLUMN_ID, persistentState, localState); for (auto columnID = 0u; columnID < columns.size(); columnID++) { updateColumn(transaction, nodeGroupIdx, columnID, persistentState, localState); } } else { - distributeAndUpdateColumn( - transaction, nodeGroupIdx, INVALID_COLUMN_ID, persistentState, localState); for (auto columnID = 0u; columnID < columns.size(); columnID++) { - distributeAndUpdateColumn( - transaction, nodeGroupIdx, columnID, persistentState, localState); + distributeAndUpdateColumn(transaction, nodeGroupIdx, columnID, persistentState, + localState); } } } -void RelTableData::findPositionsForInsertions( - offset_t nodeOffset, length_t numInsertions, LocalState& localState) { +void RelTableData::findPositionsForInsertions(offset_t nodeOffset, length_t numInsertions, + LocalState& localState) { auto& header = localState.header; KU_ASSERT(nodeOffset < header.offset->getNumValues()); // Try insert to the end of nodeOffset. @@ -609,8 +575,8 @@ void RelTableData::findPositionsForInsertions( } } -void RelTableData::slideForInsertions( - offset_t nodeOffset, length_t numInsertions, LocalState& localState) { +void RelTableData::slideForInsertions(offset_t nodeOffset, length_t numInsertions, + LocalState& localState) { // Now, we have to slide. Heuristically, the sliding happens both left and right. auto& header = localState.header; auto [leftBoundary, rightBoundary] = localState.region.getNodeOffsetBoundaries(); @@ -701,16 +667,6 @@ void RelTableData::slideRightForInsertions(offset_t nodeOffset, offset_t rightBo } } -LocalVectorCollection* RelTableData::getLocalChunk( - const RelTableData::LocalState& localState, column_id_t columnID) { - return columnID == INVALID_COLUMN_ID ? localState.localNG->getAdjChunk() : - localState.localNG->getPropertyChunk(columnID); -} - -Column* RelTableData::getColumn(column_id_t columnID) { - return columnID == INVALID_COLUMN_ID ? adjColumn.get() : TableData::getColumn(columnID); -} - void RelTableData::updateColumn(Transaction* transaction, node_group_idx_t nodeGroupIdx, column_id_t columnID, const RelTableData::PersistentState& persistentState, LocalState& localState) { @@ -718,41 +674,39 @@ void RelTableData::updateColumn(Transaction* transaction, node_group_idx_t nodeG applyUpdatesToColumn(transaction, nodeGroupIdx, columnID, persistentState, localState, column); applyDeletionsToColumn(transaction, nodeGroupIdx, localState, persistentState, column); applySliding(transaction, nodeGroupIdx, localState, persistentState, column); - applyInsertionsToColumn( - transaction, nodeGroupIdx, columnID, localState, persistentState, column); + applyInsertionsToColumn(transaction, nodeGroupIdx, columnID, localState, persistentState, + column); } void RelTableData::applyUpdatesToColumn(Transaction* transaction, node_group_idx_t nodeGroupIdx, column_id_t columnID, const PersistentState& persistentState, LocalState& localState, Column* column) { - std::map writeInfo; - auto relNGInfo = localState.localNG->getRelNGInfo(); - auto& updateInfo = relNGInfo->getUpdateInfo(columnID); - for (auto& [offset, updatesPerNode] : updateInfo) { - if (localState.region.isOutOfBoundary(offset)) { + offset_to_row_idx_t writeInfo; + auto& updateChunk = localState.localNG->getUpdateChunks(columnID); + for (auto& [srcOffset, updatesPerNode] : updateChunk.getSrcNodeOffsetToRelOffsets()) { + if (localState.region.isOutOfBoundary(srcOffset)) { // TODO: Should also partition local storage into regions. So we can avoid this check. continue; } - for (auto& [relID, rowIdx] : updatesPerNode) { - auto csrOffsetInRegion = findCSROffsetInRegion(persistentState, offset, relID); - writeInfo[csrOffsetInRegion] = rowIdx; + for (auto relOffset : updatesPerNode) { + auto csrOffsetInRegion = findCSROffsetInRegion(persistentState, srcOffset, relOffset); + writeInfo[csrOffsetInRegion] = updateChunk.getRowIdxFromOffset(relOffset); } } if (!writeInfo.empty()) { - auto localChunk = getLocalChunk(localState, columnID); - column->prepareCommitForChunk( - transaction, nodeGroupIdx, localChunk, {} /*insertInfo*/, writeInfo, {} /*deleteInfo*/); + auto localChunk = updateChunk.getLocalChunk(0 /*columnID*/); + column->prepareCommitForChunk(transaction, nodeGroupIdx, {}, {} /*insertInfo*/, localChunk, + writeInfo, {} /*deleteInfo*/); } } void RelTableData::applyInsertionsToColumn(Transaction* transaction, node_group_idx_t nodeGroupIdx, column_id_t columnID, LocalState& localState, const PersistentState& persistentState, Column* column) { - std::map writeInfo; - auto relNGInfo = localState.localNG->getRelNGInfo(); - auto& insertInfo = relNGInfo->getInsertInfo(columnID); - auto& deleteInfo = relNGInfo->getDeleteInfo(); - for (auto& [offset, insertions] : insertInfo) { + (void)persistentState; // Avoid unused variable warning. + offset_to_row_idx_t writeInfo; + auto& insertChunks = localState.localNG->insertChunks; + for (auto& [offset, insertions] : insertChunks.getSrcNodeOffsetToRelOffsets()) { if (localState.region.isOutOfBoundary(offset)) { continue; } @@ -760,22 +714,22 @@ void RelTableData::applyInsertionsToColumn(Transaction* transaction, node_group_ auto length = localState.header.getCSRLength(offset); KU_ASSERT(length >= insertions.size()); KU_ASSERT((startCSROffset + persistentState.header.getCSRLength(offset) - - (deleteInfo.contains(offset) ? deleteInfo.at(offset).size() : 0) + + localState.localNG->deleteInfo.getNumDeletedRelsFromSrcOffset(offset) + insertions.size()) <= localState.header.getEndCSROffset(offset)); auto idx = startCSROffset + length - insertions.size(); - for (auto& [relID, rowIdx] : insertions) { - writeInfo[idx++] = rowIdx; + for (auto relOffset : insertions) { + writeInfo[idx++] = insertChunks.getRowIdxFromOffset(relOffset); } } - auto localChunk = getLocalChunk(localState, columnID); - column->prepareCommitForChunk(transaction, nodeGroupIdx, localChunk, writeInfo, {}, {}); + auto localChunk = insertChunks.getLocalChunk(columnID); + column->prepareCommitForChunk(transaction, nodeGroupIdx, localChunk, writeInfo, {}, {}, {}); } std::vector> RelTableData::getSlidesForDeletions( - const PersistentState& persistentState, const LocalState& localState, - const delete_info_t& deleteInfo) { + const PersistentState& persistentState, const LocalState& localState) { std::vector> slides; - for (auto& [offset, deletions] : deleteInfo) { + for (auto& [offset, deletions] : + localState.localNG->deleteInfo.getSrcNodeOffsetToRelOffsetVec()) { if (localState.region.isOutOfBoundary(offset)) { continue; } @@ -817,21 +771,19 @@ std::vector> RelTableData::getSlidesForDeletions( // 3. `getSlidesForDeletions` can be done once for all columns. void RelTableData::applyDeletionsToColumn(Transaction* transaction, node_group_idx_t nodeGroupIdx, LocalState& localState, const PersistentState& persistentState, Column* column) { - auto relNGInfo = localState.localNG->getRelNGInfo(); - auto& deleteInfo = relNGInfo->getDeleteInfo(); - auto slides = getSlidesForDeletions(persistentState, localState, deleteInfo); + auto slides = getSlidesForDeletions(persistentState, localState); if (slides.empty()) { return; } - auto chunk = ColumnChunkFactory::createColumnChunk( - *column->getDataType().copy(), enableCompression, slides.size()); + auto chunk = ColumnChunkFactory::createColumnChunk(*column->getDataType().copy(), + enableCompression, slides.size()); std::vector dstOffsets; dstOffsets.resize(slides.size()); auto tmpChunkForRead = ColumnChunkFactory::createColumnChunk(*column->getDataType().copy(), enableCompression, 1); for (auto i = 0u; i < slides.size(); i++) { - column->scan( - transaction, nodeGroupIdx, tmpChunkForRead.get(), slides[i].first, slides[i].first + 1); + column->scan(transaction, nodeGroupIdx, tmpChunkForRead.get(), slides[i].first, + slides[i].first + 1); chunk->append(tmpChunkForRead.get(), 0, 1); dstOffsets[i] = slides[i].second; } @@ -864,26 +816,26 @@ void RelTableData::applySliding(Transaction* transaction, node_group_idx_t nodeG if (slides.empty()) { return; } - auto chunk = ColumnChunkFactory::createColumnChunk( - *column->getDataType().copy(), enableCompression, slides.size()); + auto chunk = ColumnChunkFactory::createColumnChunk(*column->getDataType().copy(), + enableCompression, slides.size()); std::vector dstOffsets; dstOffsets.resize(slides.size()); auto tmpChunkForRead = ColumnChunkFactory::createColumnChunk(*column->getDataType().copy(), enableCompression, 1); for (auto i = 0u; i < slides.size(); i++) { - column->scan( - transaction, nodeGroupIdx, tmpChunkForRead.get(), slides[i].first, slides[i].first + 1); + column->scan(transaction, nodeGroupIdx, tmpChunkForRead.get(), slides[i].first, + slides[i].first + 1); chunk->append(tmpChunkForRead.get(), 0, 1); dstOffsets[i] = slides[i].second; } column->prepareCommitForChunk(transaction, nodeGroupIdx, dstOffsets, chunk.get(), 0); } -static offset_t getMaxNumNodesInRegion( - const CSRHeaderChunks& header, const PackedCSRRegion& region, const RelNGInfo* localInfo) { +offset_t RelTableData::getMaxNumNodesInRegion(const ChunkedCSRHeader& header, + const PackedCSRRegion& region, const LocalRelNG* localNG) { auto numNodes = header.offset->getNumValues(); KU_ASSERT(numNodes == header.length->getNumValues()); - for (auto& [offset, _] : localInfo->adjInsertInfo) { + for (auto& [offset, _] : localNG->insertChunks.getSrcNodeOffsetToRelOffsets()) { if (!region.isOutOfBoundary(offset) && offset >= numNodes) { numNodes = offset + 1; } @@ -893,26 +845,27 @@ static offset_t getMaxNumNodesInRegion( void RelTableData::updateCSRHeader(Transaction* transaction, node_group_idx_t nodeGroupIdx, PersistentState& persistentState, LocalState& localState) { - auto localInfo = localState.localNG->getRelNGInfo(); auto [leftBoundary, rightBoundary] = localState.region.getNodeOffsetBoundaries(); auto& header = persistentState.header; - auto maxNumNodesInRegion = getMaxNumNodesInRegion(header, localState.region, localInfo); + auto maxNumNodesInRegion = + getMaxNumNodesInRegion(header, localState.region, localState.localNG); // Update the region boundary based on actual num nodes in the region. localState.region.leftBoundary = std::min(leftBoundary, header.offset->getNumValues()); localState.region.rightBoundary = std::min(rightBoundary, maxNumNodesInRegion - 1); persistentState.leftCSROffset = header.getStartCSROffset(localState.region.leftBoundary); persistentState.rightCSROffset = header.getEndCSROffset(localState.region.rightBoundary); - localState.header = CSRHeaderChunks(enableCompression, maxNumNodesInRegion); + localState.header = ChunkedCSRHeader(enableCompression, maxNumNodesInRegion); auto& newHeader = localState.header; newHeader.copyFrom(header); newHeader.fillDefaultValues(localState.region.rightBoundary + 1); - if (localInfo->adjInsertInfo.empty() && localInfo->deleteInfo.empty()) { + if (localState.localNG->insertChunks.isEmpty() && localState.localNG->deleteInfo.isEmpty()) { // No need to update the csr header. localState.leftCSROffset = persistentState.leftCSROffset; localState.rightCSROffset = persistentState.rightCSROffset; return; } - for (auto& [offset, deletions] : localInfo->deleteInfo) { + for (auto& [offset, deletions] : + localState.localNG->deleteInfo.getSrcNodeOffsetToRelOffsetVec()) { if (localState.region.isOutOfBoundary(offset)) { continue; } @@ -920,19 +873,21 @@ void RelTableData::updateCSRHeader(Transaction* transaction, node_group_idx_t no int64_t newLength = (int64_t)oldLength - deletions.size(); KU_ASSERT(newLength >= 0); newHeader.length->setValue(newLength, offset); + newHeader.length->getNullChunk()->setNull(offset, false); } - for (auto& [offset, _] : localInfo->adjInsertInfo) { + for (auto& [offset, _] : localState.localNG->insertChunks.getSrcNodeOffsetToRelOffsets()) { if (localState.region.isOutOfBoundary(offset)) { continue; } auto oldLength = newHeader.getCSRLength(offset); - auto numInsertions = localInfo->adjInsertInfo.at(offset).size(); + auto numInsertions = localState.localNG->getNumInsertedRels(offset); if (localState.region.level == 0) { findPositionsForInsertions(offset, numInsertions, localState); } int64_t newLength = (int64_t)oldLength + numInsertions; KU_ASSERT(newLength >= 0); newHeader.length->setValue(newLength, offset); + newHeader.length->getNullChunk()->setNull(offset, false); } if (localState.region.level > 0) { distributeOffsets(header, localState, localState.region.leftBoundary, maxNumNodesInRegion); @@ -941,7 +896,6 @@ void RelTableData::updateCSRHeader(Transaction* transaction, node_group_idx_t no getNewRegionSize(header, localState.sizeChangesPerSegment, localState.region); localState.regionCapacity = getRegionCapacity(header, localState.region); } - KU_ASSERT(newHeader.sanityCheck()); localState.leftCSROffset = newHeader.getStartCSROffset(localState.region.leftBoundary); localState.rightCSROffset = newHeader.getEndCSROffset(localState.region.rightBoundary); std::vector dstOffsets; @@ -953,7 +907,7 @@ void RelTableData::updateCSRHeader(Transaction* transaction, node_group_idx_t no newHeader.length.get(), localState.region.leftBoundary); } -void RelTableData::distributeOffsets(const CSRHeaderChunks& header, LocalState& localState, +void RelTableData::distributeOffsets(const ChunkedCSRHeader& header, LocalState& localState, offset_t leftBoundary, offset_t rightBoundary) { if (localState.region.level > packedCSRInfo.calibratorTreeHeight) { // Need to resize the capacity and reset regionToDistribute to the top level one. @@ -961,8 +915,8 @@ void RelTableData::distributeOffsets(const CSRHeaderChunks& header, LocalState& PackedCSRRegion{0, static_cast(packedCSRInfo.calibratorTreeHeight)}; localState.regionSize = getNewRegionSize(header, localState.sizeChangesPerSegment, localState.region); - localState.regionCapacity = StorageUtils::divideAndRoundUpTo( - localState.regionSize, StorageConstants::PACKED_CSR_DENSITY); + localState.regionCapacity = StorageUtils::divideAndRoundUpTo(localState.regionSize, + StorageConstants::PACKED_CSR_DENSITY); } else { localState.regionSize = getNewRegionSize(header, localState.sizeChangesPerSegment, localState.region); @@ -978,12 +932,13 @@ void RelTableData::distributeOffsets(const CSRHeaderChunks& header, LocalState& auto startCSROffset = newHeader.getStartCSROffset(nodeOffset); auto newOffset = startCSROffset + newLength + newGap; newHeader.offset->setValue(newOffset, nodeOffset); + newHeader.offset->getNullChunk()->setNull(nodeOffset, false); } localState.needSliding = true; } -void RelTableData::prepareCommitNodeGroup( - Transaction* transaction, node_group_idx_t nodeGroupIdx, LocalRelNG* localRelNG) { +void RelTableData::prepareCommitNodeGroup(Transaction* transaction, node_group_idx_t nodeGroupIdx, + LocalRelNG* localRelNG) { auto numNodesInPersistentStorage = csrHeaderColumns.getNumNodes(transaction, nodeGroupIdx); PersistentState persistentState(numNodesInPersistentStorage); csrHeaderColumns.scan(transaction, nodeGroupIdx, persistentState.header); @@ -998,33 +953,37 @@ void RelTableData::prepareCommitNodeGroup( } } -LocalRelNG* RelTableData::getLocalNodeGroup( - transaction::Transaction* transaction, node_group_idx_t nodeGroupIdx) { - auto localTableData = transaction->getLocalStorage()->getLocalTableData( - tableID, getDataIdxFromDirection(direction)); +LocalRelNG* RelTableData::getLocalNodeGroup(Transaction* transaction, + node_group_idx_t nodeGroupIdx) { + auto localTable = transaction->getLocalStorage()->getLocalTable(tableID); + if (!localTable) { + return nullptr; + } + auto localRelTable = ku_dynamic_cast(localTable); + auto localTableData = localRelTable->getTableData(direction); LocalRelNG* localNodeGroup = nullptr; - if (localTableData) { - auto localRelTableData = - ku_dynamic_cast(localTableData); - if (localRelTableData->nodeGroups.contains(nodeGroupIdx)) { - localNodeGroup = ku_dynamic_cast( - localRelTableData->nodeGroups.at(nodeGroupIdx).get()); - } + if (localTableData->nodeGroups.contains(nodeGroupIdx)) { + localNodeGroup = ku_dynamic_cast( + localTableData->nodeGroups.at(nodeGroupIdx).get()); } return localNodeGroup; } +void RelTableData::prepareCommit() { + csrHeaderColumns.offset->prepareCommit(); + csrHeaderColumns.length->prepareCommit(); + TableData::prepareCommit(); +} + void RelTableData::checkpointInMemory() { csrHeaderColumns.offset->checkpointInMemory(); csrHeaderColumns.length->checkpointInMemory(); - adjColumn->checkpointInMemory(); TableData::checkpointInMemory(); } void RelTableData::rollbackInMemory() { csrHeaderColumns.offset->rollbackInMemory(); csrHeaderColumns.length->rollbackInMemory(); - adjColumn->rollbackInMemory(); TableData::rollbackInMemory(); } diff --git a/src/storage/store/string_column.cpp b/src/storage/store/string_column.cpp index eb333fbc6e8..ba2a155f96d 100644 --- a/src/storage/store/string_column.cpp +++ b/src/storage/store/string_column.cpp @@ -1,5 +1,6 @@ #include "storage/store/string_column.h" +#include "storage/store/column.h" #include "storage/store/null_column.h" #include "storage/store/string_column_chunk.h" @@ -52,8 +53,8 @@ void StringColumn::writeValue(const ColumnChunkMetadata& chunkMeta, node_group_i auto& kuStr = vectorToWriteFrom->getValue(posInVectorToWriteFrom); auto index = dictionary.append(nodeGroupIdx, kuStr.getAsStringView()); // Write index to main column - auto state = ReadState{ - chunkMeta, chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)}; + auto state = ReadState{chunkMeta, + chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)}; Column::writeValues(state, offsetInChunk, (uint8_t*)&index); } @@ -81,8 +82,8 @@ void StringColumn::write(node_group_idx_t nodeGroupIdx, offset_t dstOffset, Colu } } -void StringColumn::scanInternal( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void StringColumn::scanInternal(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { KU_ASSERT(resultVector->dataType.getPhysicalType() == PhysicalTypeID::STRING); auto startNodeOffset = nodeIDVector->readNodeOffset(0); KU_ASSERT(startNodeOffset % DEFAULT_VECTOR_CAPACITY == 0); @@ -103,8 +104,8 @@ void StringColumn::scanUnfiltered(transaction::Transaction* transaction, auto numValuesToRead = endOffsetInGroup - startOffsetInGroup; auto indices = std::make_unique(numValuesToRead); auto indexState = getReadState(transaction->getType(), nodeGroupIdx); - Column::scan( - transaction, indexState, startOffsetInGroup, endOffsetInGroup, (uint8_t*)indices.get()); + Column::scan(transaction, indexState, startOffsetInGroup, endOffsetInGroup, + (uint8_t*)indices.get()); std::vector> offsetsToScan; for (auto i = 0u; i < numValuesToRead; i++) { @@ -131,8 +132,8 @@ void StringColumn::scanFiltered(transaction::Transaction* transaction, // TODO(bmwinger): optimize index scans by grouping them when adjacent auto offsetInGroup = startOffsetInGroup + pos; string_index_t index; - Column::scan( - transaction, indexState, offsetInGroup, offsetInGroup + 1, (uint8_t*)&index); + Column::scan(transaction, indexState, offsetInGroup, offsetInGroup + 1, + (uint8_t*)&index); offsetsToScan.emplace_back(index, pos); } } @@ -143,8 +144,8 @@ void StringColumn::scanFiltered(transaction::Transaction* transaction, dictionary.scan(transaction, nodeGroupIdx, offsetsToScan, resultVector, indexState.metadata); } -void StringColumn::lookupInternal( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void StringColumn::lookupInternal(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { KU_ASSERT(dataType.getPhysicalType() == PhysicalTypeID::STRING); auto startNodeOffset = nodeIDVector->readNodeOffset(0); auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(startNodeOffset); @@ -157,8 +158,8 @@ void StringColumn::lookupInternal( auto offsetInGroup = nodeIDVector->readNodeOffset(pos) - StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); string_index_t index; - Column::scan( - transaction, indexState, offsetInGroup, offsetInGroup + 1, (uint8_t*)&index); + Column::scan(transaction, indexState, offsetInGroup, offsetInGroup + 1, + (uint8_t*)&index); offsetsToScan.emplace_back(index, pos); } } @@ -170,28 +171,29 @@ void StringColumn::lookupInternal( } bool StringColumn::canCommitInPlace(transaction::Transaction* transaction, - node_group_idx_t nodeGroupIdx, LocalVectorCollection* localChunk, - const offset_to_row_idx_t& insertInfo, const offset_to_row_idx_t& updateInfo) { - std::vector rowIdxesToRead; - for (auto& [offset, rowIdx] : updateInfo) { - rowIdxesToRead.push_back(rowIdx); + node_group_idx_t nodeGroupIdx, const ChunkCollection& localInsertChunks, + const offset_to_row_idx_t& insertInfo, const ChunkCollection& localUpdateChunks, + const offset_to_row_idx_t& updateInfo) { + auto strLenToAdd = 0u; + for (auto& [_, rowIdx] : updateInfo) { + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + auto localUpdateChunk = localUpdateChunks[chunkIdx]; + auto kuStr = localUpdateChunk->getValue(offsetInLocalChunk); + strLenToAdd += kuStr.len; } offset_t maxOffset = 0u; for (auto& [offset, rowIdx] : insertInfo) { - rowIdxesToRead.push_back(rowIdx); if (offset > maxOffset) { maxOffset = offset; } - } - std::sort(rowIdxesToRead.begin(), rowIdxesToRead.end()); - auto strLenToAdd = 0u; - for (auto rowIdx : rowIdxesToRead) { - auto localVector = localChunk->getLocalVector(rowIdx); - auto offsetInVector = rowIdx & (DEFAULT_VECTOR_CAPACITY - 1); - auto kuStr = localVector->getVector()->getValue(offsetInVector); + auto [chunkIdx, offsetInLocalChunk] = + LocalChunkedGroupCollection::getChunkIdxAndOffsetInChunk(rowIdx); + auto localInsertChunk = localInsertChunks[chunkIdx]; + auto kuStr = localInsertChunk->getValue(offsetInLocalChunk); strLenToAdd += kuStr.len; } - auto numStrings = rowIdxesToRead.size(); + auto numStrings = insertInfo.size() + updateInfo.size(); if (!dictionary.canCommitInPlace(transaction, nodeGroupIdx, numStrings, strLenToAdd)) { return false; } @@ -204,6 +206,9 @@ bool StringColumn::canCommitInPlace(Transaction* transaction, node_group_idx_t n auto strChunk = ku_dynamic_cast(chunk); auto length = std::min((uint64_t)dstOffsets.size(), strChunk->getNumValues()); for (auto i = 0u; i < length; i++) { + if (strChunk->getNullChunk()->isNull(i)) { + continue; + } strLenToAdd += strChunk->getStringLength(i + srcOffset); } auto numStrings = dstOffsets.size(); @@ -226,13 +231,18 @@ bool StringColumn::canIndexCommitInPlace(Transaction* transaction, node_group_id auto totalStringsAfterUpdate = dictionary.getNumValuesInOffsets(transaction, nodeGroupIdx) + numStrings; // Check if the index column can store the largest new index in-place - if (!metadata.compMeta.canUpdateInPlace( - (const uint8_t*)&totalStringsAfterUpdate, 0 /*pos*/, dataType.getPhysicalType())) { + if (!metadata.compMeta.canUpdateInPlace((const uint8_t*)&totalStringsAfterUpdate, 0 /*pos*/, + PhysicalTypeID::UINT32)) { return false; } return true; } +void StringColumn::prepareCommit() { + Column::prepareCommit(); + dictionary.prepareCommit(); +} + void StringColumn::checkpointInMemory() { Column::checkpointInMemory(); dictionary.checkpointInMemory(); diff --git a/src/storage/store/string_column_chunk.cpp b/src/storage/store/string_column_chunk.cpp index bb0d20075a9..1c64f32c47b 100644 --- a/src/storage/store/string_column_chunk.cpp +++ b/src/storage/store/string_column_chunk.cpp @@ -1,39 +1,44 @@ #include "storage/store/string_column_chunk.h" +#include "common/data_chunk/sel_vector.h" +#include "storage/store/column_chunk.h" +#include "storage/store/dictionary_chunk.h" + using namespace kuzu::common; namespace kuzu { namespace storage { -StringColumnChunk::StringColumnChunk( - LogicalType dataType, uint64_t capacity, bool enableCompression) +StringColumnChunk::StringColumnChunk(LogicalType dataType, uint64_t capacity, + bool enableCompression, bool inMemory) : ColumnChunk{std::move(dataType), capacity, enableCompression}, - dictionaryChunk{capacity, enableCompression}, needFinalize{false} {} + dictionaryChunk{ + std::make_unique(inMemory ? 0 : capacity, enableCompression)}, + needFinalize{false} {} void StringColumnChunk::resetToEmpty() { ColumnChunk::resetToEmpty(); - dictionaryChunk.resetToEmpty(); + dictionaryChunk->resetToEmpty(); } -void StringColumnChunk::append(ValueVector* vector) { - KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { +void StringColumnChunk::append(ValueVector* vector, const SelectionVector& selVector) { + for (auto i = 0u; i < selVector.selectedSize; i++) { + // index is stored in main chunk, data is stored in the data chunk + auto pos = selVector.selectedPositions[i]; + KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); // index is stored in main chunk, data is stored in the data chunk - auto pos = vector->state->selVector->selectedPositions[i]; nullChunk->setNull(numValues, vector->isNull(pos)); + auto dstPos = numValues++; if (vector->isNull(pos)) { - numValues++; continue; } auto kuString = vector->getValue(pos); - auto dstPos = numValues; - numValues++; - setValueFromString(kuString.getAsString().c_str(), kuString.len, dstPos); + setValueFromString(kuString.getAsStringView(), dstPos); } } -void StringColumnChunk::append( - ColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { +void StringColumnChunk::append(ColumnChunk* other, offset_t startPosInOtherChunk, + uint32_t numValuesToAppend) { auto otherChunk = ku_dynamic_cast(other); nullChunk->append(otherChunk->getNullChunk(), startPosInOtherChunk, numValuesToAppend); switch (dataType.getLogicalTypeID()) { @@ -47,8 +52,19 @@ void StringColumnChunk::append( } } -void StringColumnChunk::write( - ValueVector* vector, offset_t offsetInVector, offset_t offsetInChunk) { +void StringColumnChunk::lookup(offset_t offsetInChunk, ValueVector& output, + sel_t posInOutputVector) const { + KU_ASSERT(offsetInChunk < numValues); + output.setNull(posInOutputVector, nullChunk->isNull(offsetInChunk)); + if (nullChunk->isNull(offsetInChunk)) { + return; + } + auto str = getValue(offsetInChunk); + output.setValue(posInOutputVector, str); +} + +void StringColumnChunk::write(ValueVector* vector, offset_t offsetInVector, + offset_t offsetInChunk) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRING); if (!needFinalize && offsetInChunk < numValues) [[unlikely]] { needFinalize = true; @@ -59,30 +75,27 @@ void StringColumnChunk::write( } if (!vector->isNull(offsetInVector)) { auto kuStr = vector->getValue(offsetInVector); - setValueFromString(kuStr.getAsString().c_str(), kuStr.len, offsetInChunk); + setValueFromString(kuStr.getAsStringView(), offsetInChunk); } } -void StringColumnChunk::write( - ValueVector* valueVector, ValueVector* offsetInChunkVector, bool /*isCSR*/) { - KU_ASSERT(valueVector->dataType.getPhysicalType() == PhysicalTypeID::STRING && - offsetInChunkVector->dataType.getPhysicalType() == PhysicalTypeID::INT64 && - valueVector->state->selVector->selectedSize == - offsetInChunkVector->state->selVector->selectedSize); - for (auto i = 0u; i < valueVector->state->selVector->selectedSize; i++) { - auto pos = valueVector->state->selVector->selectedPositions[i]; - auto offsetInChunk = offsetInChunkVector->getValue(pos); +void StringColumnChunk::write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + RelMultiplicity /*multiplicity*/) { + KU_ASSERT(chunk->getDataType().getPhysicalType() == PhysicalTypeID::STRING && + dstOffsets->getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID && + chunk->getNumValues() == dstOffsets->getNumValues()); + for (auto i = 0u; i < chunk->getNumValues(); i++) { + auto offsetInChunk = dstOffsets->getValue(i); if (!needFinalize && offsetInChunk < numValues) [[unlikely]] { needFinalize = true; } - auto offsetInVector = valueVector->state->selVector->selectedPositions[i]; - nullChunk->setNull(offsetInChunk, valueVector->isNull(offsetInVector)); + nullChunk->setNull(offsetInChunk, chunk->getNullChunk()->isNull(i)); if (offsetInChunk >= numValues) { numValues = offsetInChunk + 1; } - if (!valueVector->isNull(offsetInVector)) { - auto kuStr = valueVector->getValue(offsetInVector); - setValueFromString((const char*)kuStr.getData(), kuStr.len, offsetInChunk); + if (!chunk->getNullChunk()->isNull(i)) { + auto stringChunk = ku_dynamic_cast(chunk); + setValueFromString(stringChunk->getValue(i), offsetInChunk); } } } @@ -90,6 +103,9 @@ void StringColumnChunk::write( void StringColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, offset_t dstOffsetInChunk, offset_t numValuesToCopy) { KU_ASSERT(srcChunk->getDataType().getPhysicalType() == PhysicalTypeID::STRING); + if ((dstOffsetInChunk + numValuesToCopy) >= numValues) { + numValues = dstOffsetInChunk + numValuesToCopy; + } for (auto i = 0u; i < numValuesToCopy; i++) { auto srcPos = srcOffsetInChunk + i; auto dstPos = dstOffsetInChunk + i; @@ -98,8 +114,7 @@ void StringColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, continue; } auto srcStringChunk = ku_dynamic_cast(srcChunk); - auto stringInOtherChunk = srcStringChunk->getValue(srcPos); - setValueFromString(stringInOtherChunk.data(), stringInOtherChunk.size(), dstPos); + setValueFromString(srcStringChunk->getValue(srcPos), dstPos); } } @@ -117,8 +132,8 @@ void StringColumnChunk::copy(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, append(srcStringChunk, srcOffsetInChunk, numValuesToCopy); } -void StringColumnChunk::appendStringColumnChunk( - StringColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { +void StringColumnChunk::appendStringColumnChunk(StringColumnChunk* other, + offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { auto indices = reinterpret_cast(buffer.get()); for (auto i = 0u; i < numValuesToAppend; i++) { auto posInChunk = numValues; @@ -128,14 +143,12 @@ void StringColumnChunk::appendStringColumnChunk( indices[posInChunk] = 0; continue; } - auto stringInOtherChunk = other->getValue(posInOtherChunk); - setValueFromString(stringInOtherChunk.data(), stringInOtherChunk.size(), posInChunk); + setValueFromString(other->getValue(posInOtherChunk), posInChunk); } } -void StringColumnChunk::setValueFromString(const char* value, uint64_t length, uint64_t pos) { - KU_ASSERT(pos < numValues); - auto index = dictionaryChunk.appendString(std::string_view(value, length)); +void StringColumnChunk::setValueFromString(std::string_view value, uint64_t pos) { + auto index = dictionaryChunk->appendString(value); ColumnChunk::setValue(index, pos); } @@ -147,14 +160,14 @@ void StringColumnChunk::finalize() { // We already de-duplicate as we go, but when out of place updates occur new values will be // appended to the end and the original values may be able to be pruned before flushing them to // disk - DictionaryChunk newDictionaryChunk{numValues, enableCompression}; + auto newDictionaryChunk = std::make_unique(numValues, enableCompression); // Each index is replaced by a new one for the de-duplicated data in the new dictionary. for (auto i = 0u; i < numValues; i++) { if (nullChunk->isNull(i)) { continue; } auto stringData = getValue(i); - auto index = newDictionaryChunk.appendString(stringData); + auto index = newDictionaryChunk->appendString(stringData); setValue(index, i); } dictionaryChunk = std::move(newDictionaryChunk); @@ -164,8 +177,9 @@ void StringColumnChunk::finalize() { template<> std::string_view StringColumnChunk::getValue(offset_t pos) const { KU_ASSERT(pos < numValues); + KU_ASSERT(!nullChunk->isNull(pos)); auto index = ColumnChunk::getValue(pos); - return dictionaryChunk.getString(index); + return dictionaryChunk->getString(index); } template<> diff --git a/src/storage/store/struct_column.cpp b/src/storage/store/struct_column.cpp index 70427e381d0..8be95b9ff1a 100644 --- a/src/storage/store/struct_column.cpp +++ b/src/storage/store/struct_column.cpp @@ -21,8 +21,8 @@ StructColumn::StructColumn(std::string name, LogicalType dataType, KU_ASSERT(metaDAHeaderInfo.childrenInfos.size() == fieldTypes.size()); childColumns.resize(fieldTypes.size()); for (auto i = 0u; i < fieldTypes.size(); i++) { - auto childColName = StorageUtils::getColumnName( - name, StorageUtils::ColumnType::STRUCT_CHILD, std::to_string(i)); + auto childColName = StorageUtils::getColumnName(name, + StorageUtils::ColumnType::STRUCT_CHILD, std::to_string(i)); childColumns[i] = ColumnFactory::createColumn(childColName, *fieldTypes[i]->copy(), *metaDAHeaderInfo.childrenInfos[i], dataFH, metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); @@ -32,8 +32,8 @@ StructColumn::StructColumn(std::string name, LogicalType dataType, void StructColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, ColumnChunk* columnChunk, offset_t startOffset, offset_t endOffset) { KU_ASSERT(columnChunk->getDataType().getPhysicalType() == PhysicalTypeID::STRUCT); - nullColumn->scan( - transaction, nodeGroupIdx, columnChunk->getNullChunk(), startOffset, endOffset); + nullColumn->scan(transaction, nodeGroupIdx, columnChunk->getNullChunk(), startOffset, + endOffset); if (nodeGroupIdx >= metadataDA->getNumElements(transaction->getType())) { columnChunk->setNumValues(0); } else { @@ -45,8 +45,8 @@ void StructColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, } auto structColumnChunk = ku_dynamic_cast(columnChunk); for (auto i = 0u; i < childColumns.size(); i++) { - childColumns[i]->scan( - transaction, nodeGroupIdx, structColumnChunk->getChild(i), startOffset, endOffset); + childColumns[i]->scan(transaction, nodeGroupIdx, structColumnChunk->getChild(i), + startOffset, endOffset); } } @@ -62,16 +62,16 @@ void StructColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, } } -void StructColumn::scanInternal( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void StructColumn::scanInternal(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { for (auto i = 0u; i < childColumns.size(); i++) { auto fieldVector = StructVector::getFieldVector(resultVector, i).get(); childColumns[i]->scan(transaction, nodeIDVector, fieldVector); } } -void StructColumn::lookupInternal( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { +void StructColumn::lookupInternal(Transaction* transaction, ValueVector* nodeIDVector, + ValueVector* resultVector) { for (auto i = 0u; i < childColumns.size(); i++) { auto fieldVector = StructVector::getFieldVector(resultVector, i).get(); childColumns[i]->lookup(transaction, nodeIDVector, fieldVector); @@ -125,47 +125,66 @@ void StructColumn::rollbackInMemory() { } } +void StructColumn::prepareCommit() { + Column::prepareCommit(); + for (const auto& childColumn : childColumns) { + childColumn->prepareCommit(); + } +} + bool StructColumn::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo) { + const ChunkCollection& localInsertChunk, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunk, const offset_to_row_idx_t& updateInfo) { // STRUCT column doesn't have actual data stored in buffer. Only need to check the null column. // Children columns are committed separately. - return nullColumn->canCommitInPlace( - transaction, nodeGroupIdx, localChunk, insertInfo, updateInfo); + return nullColumn->canCommitInPlace(transaction, nodeGroupIdx, + getNullChunkCollection(localInsertChunk), insertInfo, + getNullChunkCollection(localUpdateChunk), updateInfo); } bool StructColumn::canCommitInPlace(Transaction* transaction, node_group_idx_t nodeGroupIdx, const std::vector& dstOffsets, ColumnChunk* chunk, offset_t srcOffset) { - return nullColumn->canCommitInPlace( - transaction, nodeGroupIdx, dstOffsets, chunk->getNullChunk(), srcOffset); + return nullColumn->canCommitInPlace(transaction, nodeGroupIdx, dstOffsets, + chunk->getNullChunk(), srcOffset); } void StructColumn::prepareCommitForChunk(Transaction* transaction, node_group_idx_t nodeGroupIdx, - LocalVectorCollection* localColumnChunk, const offset_to_row_idx_t& insertInfo, - const offset_to_row_idx_t& updateInfo, const offset_set_t& deleteInfo) { + const ChunkCollection& localInsertChunk, const offset_to_row_idx_t& insertInfo, + const ChunkCollection& localUpdateChunk, const offset_to_row_idx_t& updateInfo, + const offset_set_t& deleteInfo) { auto currentNumNodeGroups = metadataDA->getNumElements(transaction->getType()); auto isNewNodeGroup = nodeGroupIdx >= currentNumNodeGroups; if (isNewNodeGroup) { // If this is a new node group, updateInfo should be empty. We should perform out-of-place // commit with a new column chunk. - commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, localColumnChunk, isNewNodeGroup, - insertInfo, updateInfo, deleteInfo); + commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, localInsertChunk, + insertInfo, localUpdateChunk, updateInfo, deleteInfo); } else { // STRUCT column doesn't have actual data stored in buffer. Only need to update the null // column. - if (canCommitInPlace(transaction, nodeGroupIdx, localColumnChunk, insertInfo, updateInfo)) { - nullColumn->commitLocalChunkInPlace( - transaction, nodeGroupIdx, localColumnChunk, insertInfo, updateInfo, deleteInfo); + if (canCommitInPlace(transaction, nodeGroupIdx, localInsertChunk, insertInfo, + localUpdateChunk, updateInfo)) { + nullColumn->commitLocalChunkInPlace(transaction, nodeGroupIdx, + getNullChunkCollection(localInsertChunk), insertInfo, + getNullChunkCollection(localUpdateChunk), updateInfo, deleteInfo); } else { - nullColumn->commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, localColumnChunk, - isNewNodeGroup, insertInfo, updateInfo, deleteInfo); + nullColumn->commitLocalChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, + getNullChunkCollection(localInsertChunk), insertInfo, + getNullChunkCollection(localUpdateChunk), updateInfo, deleteInfo); + } + auto chunkMeta = metadataDA->get(nodeGroupIdx, transaction->getType()); + if (nullColumn->getMetadata(nodeGroupIdx, transaction->getType()).numValues != + chunkMeta.numValues) { + chunkMeta.numValues = + nullColumn->getMetadata(nodeGroupIdx, transaction->getType()).numValues; + metadataDA->update(nodeGroupIdx, chunkMeta); } // Update each child column separately for (auto i = 0u; i < childColumns.size(); i++) { const auto& childColumn = childColumns[i]; - auto childLocalColumnChunk = localColumnChunk->getStructChildVectorCollection(i); childColumn->prepareCommitForChunk(transaction, nodeGroupIdx, - childLocalColumnChunk.get(), insertInfo, updateInfo, deleteInfo); + getStructChildChunkCollection(localInsertChunk, i), insertInfo, + getStructChildChunkCollection(localUpdateChunk, i), updateInfo, deleteInfo); } } } @@ -178,27 +197,44 @@ void StructColumn::prepareCommitForChunk(Transaction* transaction, node_group_id if (isNewNodeGroup) { // If this is a new node group, updateInfo should be empty. We should perform out-of-place // commit with a new column chunk. - commitColumnChunkOutOfPlace( - transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk, srcOffset); + commitColumnChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk, + srcOffset); } else { // STRUCT column doesn't have actual data stored in buffer. Only need to update the null // column. if (canCommitInPlace(transaction, nodeGroupIdx, dstOffsets, chunk, srcOffset)) { - nullColumn->commitColumnChunkInPlace( - nodeGroupIdx, dstOffsets, chunk->getNullChunk(), srcOffset); + nullColumn->commitColumnChunkInPlace(nodeGroupIdx, dstOffsets, chunk->getNullChunk(), + srcOffset); } else { nullColumn->commitColumnChunkOutOfPlace(transaction, nodeGroupIdx, isNewNodeGroup, dstOffsets, chunk->getNullChunk(), srcOffset); } + auto chunkMeta = metadataDA->get(nodeGroupIdx, transaction->getType()); + if (nullColumn->getMetadata(nodeGroupIdx, transaction->getType()).numValues != + chunkMeta.numValues) { + chunkMeta.numValues = + nullColumn->getMetadata(nodeGroupIdx, transaction->getType()).numValues; + metadataDA->update(nodeGroupIdx, chunkMeta); + } // Update each child column separately for (auto i = 0u; i < childColumns.size(); i++) { const auto& childColumn = childColumns[i]; auto childChunk = ku_dynamic_cast(chunk)->getChild(i); - childColumn->prepareCommitForChunk( - transaction, nodeGroupIdx, dstOffsets, childChunk, srcOffset); + childColumn->prepareCommitForChunk(transaction, nodeGroupIdx, dstOffsets, childChunk, + srcOffset); } } } +ChunkCollection StructColumn::getStructChildChunkCollection(const ChunkCollection& chunkCollection, + vector_idx_t childIdx) { + ChunkCollection childChunkCollection; + for (const auto& chunk : chunkCollection) { + auto structChunk = ku_dynamic_cast(chunk); + childChunkCollection.push_back(structChunk->getChild(childIdx)); + } + return childChunkCollection; +} + } // namespace storage } // namespace kuzu diff --git a/src/storage/store/struct_column_chunk.cpp b/src/storage/store/struct_column_chunk.cpp index f047221be5f..439a10ec141 100644 --- a/src/storage/store/struct_column_chunk.cpp +++ b/src/storage/store/struct_column_chunk.cpp @@ -1,5 +1,10 @@ #include "storage/store/struct_column_chunk.h" +#include "common/data_chunk/sel_vector.h" +#include "common/types/internal_id_t.h" +#include "common/types/types.h" +#include "storage/store/column_chunk.h" + using namespace kuzu::common; namespace kuzu { @@ -7,14 +12,14 @@ namespace storage { // TODO: need to handle this case, when the whole struct entry is null, should set all fields to // null too. -StructColumnChunk::StructColumnChunk( - LogicalType dataType, uint64_t capacity, bool enableCompression) +StructColumnChunk::StructColumnChunk(LogicalType dataType, uint64_t capacity, + bool enableCompression, bool inMemory) : ColumnChunk{std::move(dataType), capacity} { auto fieldTypes = StructType::getFieldTypes(&this->dataType); childChunks.resize(fieldTypes.size()); for (auto i = 0u; i < fieldTypes.size(); i++) { - childChunks[i] = ColumnChunkFactory::createColumnChunk( - *fieldTypes[i]->copy(), enableCompression, capacity); + childChunks[i] = ColumnChunkFactory::createColumnChunk(*fieldTypes[i]->copy(), + enableCompression, capacity, inMemory); } } @@ -24,33 +29,44 @@ void StructColumnChunk::finalize() { } } -void StructColumnChunk::append( - ColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { +void StructColumnChunk::append(ColumnChunk* other, offset_t startPosInOtherChunk, + uint32_t numValuesToAppend) { KU_ASSERT(other->getDataType().getPhysicalType() == PhysicalTypeID::STRUCT); auto otherStructChunk = ku_dynamic_cast(other); KU_ASSERT(childChunks.size() == otherStructChunk->childChunks.size()); nullChunk->append(other->getNullChunk(), startPosInOtherChunk, numValuesToAppend); for (auto i = 0u; i < childChunks.size(); i++) { - childChunks[i]->append( - otherStructChunk->childChunks[i].get(), startPosInOtherChunk, numValuesToAppend); + childChunks[i]->append(otherStructChunk->childChunks[i].get(), startPosInOtherChunk, + numValuesToAppend); } numValues += numValuesToAppend; } -void StructColumnChunk::append(ValueVector* vector) { +void StructColumnChunk::append(ValueVector* vector, const SelectionVector& selVector) { auto numFields = StructType::getNumFields(&dataType); for (auto i = 0u; i < numFields; i++) { - childChunks[i]->append(StructVector::getFieldVector(vector, i).get()); + childChunks[i]->append(StructVector::getFieldVector(vector, i).get(), selVector); } - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - nullChunk->setNull( - numValues + i, vector->isNull(vector->state->selVector->selectedPositions[i])); + for (auto i = 0u; i < selVector.selectedSize; i++) { + nullChunk->setNull(numValues + i, vector->isNull(selVector.selectedPositions[i])); + } + numValues += selVector.selectedSize; +} + +void StructColumnChunk::lookup(offset_t offsetInChunk, ValueVector& output, + sel_t posInOutputVector) const { + KU_ASSERT(offsetInChunk < numValues); + auto numFields = StructType::getNumFields(&dataType); + output.setNull(posInOutputVector, nullChunk->isNull(offsetInChunk)); + for (auto i = 0u; i < numFields; i++) { + childChunks[i]->lookup(offsetInChunk, *StructVector::getFieldVector(&output, i).get(), + posInOutputVector); } - numValues += vector->state->selVector->selectedSize; } void StructColumnChunk::resize(uint64_t newCapacity) { ColumnChunk::resize(newCapacity); + capacity = newCapacity; for (auto& child : childChunks) { child->resize(newCapacity); } @@ -63,8 +79,8 @@ void StructColumnChunk::resetToEmpty() { } } -void StructColumnChunk::write( - ValueVector* vector, offset_t offsetInVector, offset_t offsetInChunk) { +void StructColumnChunk::write(ValueVector* vector, offset_t offsetInVector, + offset_t offsetInChunk) { KU_ASSERT(vector->dataType.getPhysicalType() == PhysicalTypeID::STRUCT); nullChunk->setNull(offsetInChunk, vector->isNull(offsetInVector)); auto fields = StructVector::getFieldVectors(vector); @@ -76,18 +92,19 @@ void StructColumnChunk::write( } } -void StructColumnChunk::write( - ValueVector* valueVector, ValueVector* offsetInChunkVector, bool isCSR) { - KU_ASSERT(valueVector->dataType.getPhysicalType() == PhysicalTypeID::STRUCT); - auto offsets = reinterpret_cast(offsetInChunkVector->getData()); - for (auto i = 0u; i < offsetInChunkVector->state->selVector->selectedSize; i++) { - auto offsetInChunk = offsets[offsetInChunkVector->state->selVector->selectedPositions[i]]; +void StructColumnChunk::write(ColumnChunk* chunk, ColumnChunk* dstOffsets, + RelMultiplicity multiplicity) { + KU_ASSERT(chunk->getDataType().getPhysicalType() == PhysicalTypeID::STRUCT && + dstOffsets->getDataType().getPhysicalType() == PhysicalTypeID::INTERNAL_ID); + for (auto i = 0u; i < dstOffsets->getNumValues(); i++) { + auto offsetInChunk = dstOffsets->getValue(i); KU_ASSERT(offsetInChunk < capacity); - nullChunk->setNull(offsetInChunk, valueVector->isNull(i)); + nullChunk->setNull(offsetInChunk, chunk->getNullChunk()->isNull(i)); + numValues = offsetInChunk >= numValues ? offsetInChunk + 1 : numValues; } - auto fields = StructVector::getFieldVectors(valueVector); - for (auto i = 0u; i < fields.size(); i++) { - childChunks[i]->write(fields[i].get(), offsetInChunkVector, isCSR); + auto structChunk = ku_dynamic_cast(chunk); + for (auto i = 0u; i < childChunks.size(); i++) { + childChunks[i]->write(structChunk->getChild(i), dstOffsets, multiplicity); } } @@ -97,6 +114,9 @@ void StructColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, auto srcStructChunk = ku_dynamic_cast(srcChunk); KU_ASSERT(childChunks.size() == srcStructChunk->childChunks.size()); nullChunk->write(srcChunk->getNullChunk(), srcOffsetInChunk, dstOffsetInChunk, numValuesToCopy); + if ((dstOffsetInChunk + numValuesToCopy) >= numValues) { + numValues = dstOffsetInChunk + numValuesToCopy; + } for (auto i = 0u; i < childChunks.size(); i++) { childChunks[i]->write(srcStructChunk->childChunks[i].get(), srcOffsetInChunk, dstOffsetInChunk, numValuesToCopy); diff --git a/src/storage/store/table_data.cpp b/src/storage/store/table_data.cpp index a7bdc0b7dca..80ceb6ead37 100644 --- a/src/storage/store/table_data.cpp +++ b/src/storage/store/table_data.cpp @@ -1,17 +1,26 @@ #include "storage/store/table_data.h" +#include "catalog/catalog_entry/table_catalog_entry.h" + using namespace kuzu::common; using namespace kuzu::transaction; namespace kuzu { namespace storage { +TableData::TableData(BMFileHandle* dataFH, BMFileHandle* metadataFH, + catalog::TableCatalogEntry* tableEntry, BufferManager* bufferManager, WAL* wal, + bool enableCompression) + : dataFH{dataFH}, metadataFH{metadataFH}, tableID{tableEntry->getTableID()}, + tableName{tableEntry->getName()}, bufferManager{bufferManager}, wal{wal}, + enableCompression{enableCompression} {} + void TableData::addColumn(Transaction* transaction, const std::string& colNamePrefix, InMemDiskArray* metadataDA, const MetadataDAHInfo& metadataDAHInfo, const catalog::Property& property, ValueVector* defaultValueVector, TablesStatistics* tablesStats) { - auto colName = StorageUtils::getColumnName( - property.getName(), StorageUtils::ColumnType::DEFAULT, colNamePrefix); + auto colName = StorageUtils::getColumnName(property.getName(), + StorageUtils::ColumnType::DEFAULT, colNamePrefix); auto column = ColumnFactory::createColumn(colName, *property.getDataType()->copy(), metadataDAHInfo, dataFH, metadataFH, bufferManager, wal, transaction, RWPropertyStats(tablesStats, tableID, property.getPropertyID()), enableCompression); @@ -19,6 +28,12 @@ void TableData::addColumn(Transaction* transaction, const std::string& colNamePr columns.push_back(std::move(column)); } +void TableData::prepareCommit() { + for (auto& column : columns) { + column->prepareCommit(); + } +} + void TableData::checkpointInMemory() { for (auto& column : columns) { column->checkpointInMemory(); diff --git a/src/storage/store/var_list_column.cpp b/src/storage/store/var_list_column.cpp deleted file mode 100644 index a10cf48aa16..00000000000 --- a/src/storage/store/var_list_column.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include "storage/store/var_list_column.h" - -#include "storage/store/column.h" -#include "storage/store/null_column.h" -#include "storage/store/var_list_column_chunk.h" -#include - -using namespace kuzu::common; -using namespace kuzu::transaction; - -namespace kuzu { -namespace storage { - -offset_t ListOffsetInfoInStorage::getListOffset(uint64_t nodePos) const { - if (nodePos == 0) { - return prevNodeListOffset; - } else { - auto offsetVector = offsetVectors[(nodePos - 1) / DEFAULT_VECTOR_CAPACITY].get(); - return offsetVector->getValue((nodePos - 1) % DEFAULT_VECTOR_CAPACITY); - } -} - -VarListColumn::VarListColumn(std::string name, LogicalType dataType, - const MetadataDAHInfo& metaDAHeaderInfo, BMFileHandle* dataFH, BMFileHandle* metadataFH, - BufferManager* bufferManager, WAL* wal, Transaction* transaction, - RWPropertyStats propertyStatistics, bool enableCompression) - : Column{name, std::move(dataType), metaDAHeaderInfo, dataFH, metadataFH, bufferManager, wal, - transaction, propertyStatistics, enableCompression, true /* requireNullColumn */} { - auto dataColName = StorageUtils::getColumnName(name, StorageUtils::ColumnType::DATA, ""); - dataColumn = ColumnFactory::createColumn(dataColName, - *VarListType::getChildType(&this->dataType)->copy(), *metaDAHeaderInfo.childrenInfos[0], - dataFH, metadataFH, bufferManager, wal, transaction, propertyStatistics, enableCompression); -} - -void VarListColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, - offset_t startOffsetInGroup, offset_t endOffsetInGroup, ValueVector* resultVector, - uint64_t offsetInVector) { - // TODO(Ziyi): the current scan function requires two dynamic allocation of vectors which may be - // a bottleneck of the scan performance. We need to further optimize this. - nullColumn->scan(transaction, nodeGroupIdx, startOffsetInGroup, endOffsetInGroup, resultVector, - offsetInVector); - auto listOffsetInfoInStorage = getListOffsetInfoInStorage( - transaction, nodeGroupIdx, startOffsetInGroup, endOffsetInGroup, resultVector->state); - offset_t listOffsetInVector = - offsetInVector == 0 ? 0 : - resultVector->getValue(offsetInVector - 1).offset + - resultVector->getValue(offsetInVector - 1).size; - auto offsetToWriteListData = listOffsetInVector; - auto numValues = endOffsetInGroup - startOffsetInGroup; - for (auto i = 0u; i < numValues; i++) { - auto length = listOffsetInfoInStorage.getListLength(i); - resultVector->setValue(i + offsetInVector, list_entry_t{listOffsetInVector, length}); - listOffsetInVector += length; - } - ListVector::resizeDataVector(resultVector, listOffsetInVector); - dataColumn->scan(transaction, nodeGroupIdx, listOffsetInfoInStorage.getListOffset(0), - listOffsetInfoInStorage.getListOffset(numValues), ListVector::getDataVector(resultVector), - offsetToWriteListData); -} - -void VarListColumn::scan(Transaction* transaction, node_group_idx_t nodeGroupIdx, - kuzu::storage::ColumnChunk* columnChunk, offset_t startOffset, offset_t endOffset) { - if (nodeGroupIdx >= metadataDA->getNumElements(transaction->getType())) { - columnChunk->setNumValues(0); - } else { - Column::scan(transaction, nodeGroupIdx, columnChunk, startOffset, endOffset); - // TODO: FIX-ME. - auto varListColumnChunk = ku_dynamic_cast(columnChunk); - auto startVarListOffset = varListColumnChunk->getListOffset(0); - auto endVarListOffset = varListColumnChunk->getListOffset(columnChunk->getNumValues()); - auto numElements = endVarListOffset - startVarListOffset + 1; - varListColumnChunk->resizeDataColumnChunk(std::bit_ceil(numElements)); - dataColumn->scan(transaction, nodeGroupIdx, varListColumnChunk->getDataColumnChunk(), - startVarListOffset, endVarListOffset); - } -} - -void VarListColumn::scanInternal( - Transaction* transaction, ValueVector* nodeIDVector, ValueVector* resultVector) { - resultVector->resetAuxiliaryBuffer(); - auto startNodeOffset = nodeIDVector->readNodeOffset(0); - auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(startNodeOffset); - auto startNodeOffsetInGroup = - startNodeOffset - StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); - auto listOffsetInfoInStorage = - getListOffsetInfoInStorage(transaction, nodeGroupIdx, startNodeOffsetInGroup, - startNodeOffsetInGroup + nodeIDVector->state->getOriginalSize(), resultVector->state); - if (resultVector->state->selVector->isUnfiltered()) { - scanUnfiltered(transaction, nodeGroupIdx, resultVector, listOffsetInfoInStorage); - } else { - scanFiltered(transaction, nodeGroupIdx, resultVector, listOffsetInfoInStorage); - } -} - -void VarListColumn::lookupValue(Transaction* transaction, offset_t nodeOffset, - ValueVector* resultVector, uint32_t posInVector) { - auto nodeGroupIdx = StorageUtils::getNodeGroupIdx(nodeOffset); - auto nodeOffsetInGroup = nodeOffset - StorageUtils::getStartOffsetOfNodeGroup(nodeGroupIdx); - auto listOffset = readListOffsetInStorage(transaction, nodeGroupIdx, nodeOffsetInGroup); - auto length = readListOffsetInStorage(transaction, nodeGroupIdx, nodeOffsetInGroup + 1) - - readListOffsetInStorage(transaction, nodeGroupIdx, nodeOffsetInGroup); - auto offsetInVector = posInVector == 0 ? 0 : resultVector->getValue(posInVector - 1); - resultVector->setValue(posInVector, list_entry_t{offsetInVector, length}); - ListVector::resizeDataVector(resultVector, offsetInVector + length); - dataColumn->scan(transaction, StorageUtils::getNodeGroupIdx(nodeOffset), listOffset, - listOffset + length, ListVector::getDataVector(resultVector), offsetInVector); -} - -void VarListColumn::append(ColumnChunk* columnChunk, uint64_t nodeGroupIdx) { - KU_ASSERT(columnChunk->getDataType().getPhysicalType() == dataType.getPhysicalType()); - Column::append(columnChunk, nodeGroupIdx); - auto dataColumnChunk = - ku_dynamic_cast(columnChunk)->getDataColumnChunk(); - dataColumn->append(dataColumnChunk, nodeGroupIdx); -} - -void VarListColumn::scanUnfiltered(Transaction* transaction, node_group_idx_t nodeGroupIdx, - ValueVector* resultVector, const ListOffsetInfoInStorage& listOffsetInfoInStorage) { - auto numValuesToScan = resultVector->state->selVector->selectedSize; - offset_t offsetInVector = 0; - for (auto i = 0u; i < numValuesToScan; i++) { - auto listLen = listOffsetInfoInStorage.getListLength(i); - resultVector->setValue(i, list_entry_t{offsetInVector, listLen}); - offsetInVector += listLen; - } - ListVector::resizeDataVector(resultVector, offsetInVector); - auto startListOffsetInStorage = listOffsetInfoInStorage.getListOffset(0); - auto endListOffsetInStorage = listOffsetInfoInStorage.getListOffset(numValuesToScan); - dataColumn->scan(transaction, nodeGroupIdx, startListOffsetInStorage, endListOffsetInStorage, - ListVector::getDataVector(resultVector), 0 /* offsetInVector */); -} - -void VarListColumn::scanFiltered(Transaction* transaction, node_group_idx_t nodeGroupIdx, - ValueVector* resultVector, const ListOffsetInfoInStorage& listOffsetInfoInStorage) { - offset_t listOffset = 0; - for (auto i = 0u; i < resultVector->state->selVector->selectedSize; i++) { - auto pos = resultVector->state->selVector->selectedPositions[i]; - auto listLen = listOffsetInfoInStorage.getListLength(pos); - resultVector->setValue(pos, list_entry_t{(offset_t)listOffset, (uint64_t)listLen}); - listOffset += listLen; - } - ListVector::resizeDataVector(resultVector, listOffset); - listOffset = 0; - for (auto i = 0u; i < resultVector->state->selVector->selectedSize; i++) { - auto pos = resultVector->state->selVector->selectedPositions[i]; - auto startOffsetInStorageToScan = listOffsetInfoInStorage.getListOffset(pos); - auto endOffsetInStorageToScan = listOffsetInfoInStorage.getListOffset(pos + 1); - dataColumn->scan(transaction, nodeGroupIdx, startOffsetInStorageToScan, - endOffsetInStorageToScan, ListVector::getDataVector(resultVector), listOffset); - listOffset += resultVector->getValue(pos).size; - } -} - -void VarListColumn::checkpointInMemory() { - Column::checkpointInMemory(); - dataColumn->checkpointInMemory(); -} - -void VarListColumn::rollbackInMemory() { - Column::rollbackInMemory(); - dataColumn->rollbackInMemory(); -} - -offset_t VarListColumn::readOffset( - Transaction* transaction, node_group_idx_t nodeGroupIdx, offset_t offsetInNodeGroup) { - auto chunkMeta = metadataDA->get(nodeGroupIdx, transaction->getType()); - auto pageCursor = PageUtils::getPageCursorForPos(offsetInNodeGroup, - chunkMeta.compMeta.numValues(BufferPoolConstants::PAGE_4KB_SIZE, dataType)); - pageCursor.pageIdx += chunkMeta.pageIdx; - offset_t value; - readFromPage(transaction, pageCursor.pageIdx, [&](uint8_t* frame) -> void { - readToPageFunc(frame, pageCursor, (uint8_t*)&value, 0 /* posInVector */, - 1 /* numValuesToRead */, chunkMeta.compMeta); - }); - return value; -} - -ListOffsetInfoInStorage VarListColumn::getListOffsetInfoInStorage(Transaction* transaction, - node_group_idx_t nodeGroupIdx, offset_t startOffsetInNodeGroup, offset_t endOffsetInNodeGroup, - const std::shared_ptr& state) { - auto numOffsetsToRead = endOffsetInNodeGroup - startOffsetInNodeGroup; - auto numOffsetVectors = numOffsetsToRead / DEFAULT_VECTOR_CAPACITY + - (numOffsetsToRead % DEFAULT_VECTOR_CAPACITY ? 1 : 0); - std::vector> offsetVectors; - offsetVectors.reserve(numOffsetVectors); - uint64_t numOffsetsRead = 0; - for (auto i = 0u; i < numOffsetVectors; i++) { - auto offsetVector = std::make_unique(LogicalTypeID::INT64); - auto numOffsetsToReadInCurBatch = - std::min(numOffsetsToRead - numOffsetsRead, DEFAULT_VECTOR_CAPACITY); - offsetVector->setState(state); - Column::scan(transaction, nodeGroupIdx, startOffsetInNodeGroup + numOffsetsRead, - startOffsetInNodeGroup + numOffsetsRead + numOffsetsToReadInCurBatch, - offsetVector.get(), 0 /* offsetInVector */); - offsetVectors.push_back(std::move(offsetVector)); - numOffsetsRead += numOffsetsToReadInCurBatch; - } - auto prevNodeListOffsetInStorage = - readListOffsetInStorage(transaction, nodeGroupIdx, startOffsetInNodeGroup); - return {prevNodeListOffsetInStorage, std::move(offsetVectors)}; -} - -} // namespace storage -} // namespace kuzu diff --git a/src/storage/store/var_list_column_chunk.cpp b/src/storage/store/var_list_column_chunk.cpp deleted file mode 100644 index 1865181ea65..00000000000 --- a/src/storage/store/var_list_column_chunk.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#include "storage/store/var_list_column_chunk.h" - -#include "common/cast.h" -#include "common/types/value/value.h" - -using namespace kuzu::common; - -namespace kuzu { -namespace storage { - -void VarListDataColumnChunk::reset() const { - dataColumnChunk->resetToEmpty(); -} - -void VarListDataColumnChunk::resizeBuffer(uint64_t numValues) { - if (numValues <= capacity) { - return; - } - capacity = capacity == 0 ? 1 : capacity; - while (capacity < numValues) { - capacity *= CHUNK_RESIZE_RATIO; - } - dataColumnChunk->resize(capacity); -} - -VarListColumnChunk::VarListColumnChunk( - LogicalType dataType, uint64_t capacity, bool enableCompression) - : ColumnChunk{std::move(dataType), capacity, enableCompression, true /* hasNullChunk */}, - needFinalize{false} { - varListDataColumnChunk = std::make_unique( - ColumnChunkFactory::createColumnChunk(*VarListType::getChildType(&this->dataType)->copy(), - enableCompression, 0 /* capacity */)); - KU_ASSERT(this->dataType.getPhysicalType() == PhysicalTypeID::VAR_LIST); -} - -void VarListColumnChunk::append( - ColumnChunk* other, offset_t startPosInOtherChunk, uint32_t numValuesToAppend) { - nullChunk->append(other->getNullChunk(), startPosInOtherChunk, numValuesToAppend); - auto otherListChunk = ku_dynamic_cast(other); - auto offsetInDataChunkToAppend = varListDataColumnChunk->getNumValues(); - KU_ASSERT(numValues + numValuesToAppend <= capacity); - for (auto i = 0u; i < numValuesToAppend; i++) { - offsetInDataChunkToAppend += otherListChunk->getListLen(startPosInOtherChunk + i); - setValue(offsetInDataChunkToAppend, numValues); - } - auto startOffset = otherListChunk->getListOffset(startPosInOtherChunk); - auto endOffset = otherListChunk->getListOffset(startPosInOtherChunk + numValuesToAppend); - KU_ASSERT(endOffset >= startOffset); - varListDataColumnChunk->resizeBuffer(offsetInDataChunkToAppend); - varListDataColumnChunk->dataColumnChunk->append( - otherListChunk->varListDataColumnChunk->dataColumnChunk.get(), startOffset, - endOffset - startOffset); -} - -void VarListColumnChunk::resetToEmpty() { - ColumnChunk::resetToEmpty(); - varListDataColumnChunk = std::make_unique( - ColumnChunkFactory::createColumnChunk(*VarListType::getChildType(&this->dataType)->copy(), - enableCompression, 0 /* capacity */)); -} - -void VarListColumnChunk::append(ValueVector* vector) { - auto numToAppend = vector->state->selVector->selectedSize; - auto newCapacity = capacity; - while (numValues + numToAppend >= newCapacity) { - newCapacity *= 1.5; - } - if (capacity != newCapacity) { - resize(newCapacity); - } - auto nextListOffsetInChunk = getListOffset(numValues); - auto offsetBufferToWrite = (offset_t*)(buffer.get()); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - auto pos = vector->state->selVector->selectedPositions[i]; - uint64_t listLen = vector->isNull(pos) ? 0 : vector->getValue(pos).size; - nullChunk->setNull(numValues + i, vector->isNull(pos)); - nextListOffsetInChunk += listLen; - offsetBufferToWrite[numValues + i] = nextListOffsetInChunk; - } - varListDataColumnChunk->resizeBuffer(nextListOffsetInChunk); - auto dataVector = ListVector::getDataVector(vector); - dataVector->setState(std::make_unique()); - dataVector->state->selVector->resetSelectorToValuePosBuffer(); - for (auto i = 0u; i < vector->state->selVector->selectedSize; i++) { - auto pos = vector->state->selVector->selectedPositions[i]; - if (vector->isNull(pos)) { - continue; - } - copyListValues(vector->getValue(pos), dataVector); - } - numValues += vector->state->selVector->selectedSize; -} - -void VarListColumnChunk::appendNullList() { - auto nextListOffsetInChunk = getListOffset(numValues); - auto offsetBufferToWrite = (offset_t*)(buffer.get()); - offsetBufferToWrite[numValues] = nextListOffsetInChunk; - nullChunk->setNull(numValues, true); - numValues++; -} - -void VarListColumnChunk::write( - ValueVector* valueVector, ValueVector* offsetInChunkVector, bool /*isCSR*/) { - needFinalize = true; - if (!indicesColumnChunk) { - initializeIndices(); - } - KU_ASSERT(valueVector->dataType.getPhysicalType() == dataType.getPhysicalType() && - offsetInChunkVector->dataType.getPhysicalType() == PhysicalTypeID::INT64 && - valueVector->state->selVector->selectedSize == - offsetInChunkVector->state->selVector->selectedSize); - auto currentIndex = numValues; - append(valueVector); - for (auto i = 0u; i < offsetInChunkVector->state->selVector->selectedSize; i++) { - auto posInChunk = offsetInChunkVector->getValue( - offsetInChunkVector->state->selVector->selectedPositions[i]); - KU_ASSERT(posInChunk < capacity); - indicesColumnChunk->setValue(currentIndex++, posInChunk); - indicesColumnChunk->getNullChunk()->setNull(posInChunk, false); - if (indicesColumnChunk->getNumValues() <= posInChunk) { - indicesColumnChunk->setNumValues(posInChunk + 1); - } - } - KU_ASSERT(currentIndex == numValues && - indicesColumnChunk->getNumValues() <= indicesColumnChunk->getCapacity()); -} - -void VarListColumnChunk::write( - ValueVector* vector, offset_t offsetInVector, offset_t offsetInChunk) { - needFinalize = true; - if (!indicesColumnChunk) { - initializeIndices(); - } - auto currentIndex = numValues; - append(vector); - KU_ASSERT(offsetInChunk < capacity); - indicesColumnChunk->setValue(currentIndex, offsetInChunk); - indicesColumnChunk->getNullChunk()->setNull(offsetInChunk, vector->isNull(offsetInVector)); - if (indicesColumnChunk->getNumValues() <= offsetInChunk) { - indicesColumnChunk->setNumValues(offsetInChunk + 1); - } -} - -void VarListColumnChunk::write(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, - offset_t dstOffsetInChunk, offset_t numValuesToCopy) { - KU_ASSERT(srcChunk->getDataType().getPhysicalType() == PhysicalTypeID::VAR_LIST); - needFinalize = true; - if (!indicesColumnChunk) { - initializeIndices(); - } - nullChunk->write(srcChunk->getNullChunk(), srcOffsetInChunk, dstOffsetInChunk, numValuesToCopy); - auto srcListChunk = ku_dynamic_cast(srcChunk); - auto offsetInDataChunkToAppend = varListDataColumnChunk->getNumValues(); - auto currentIndex = numValues; - for (auto i = 0u; i < numValuesToCopy; i++) { - offsetInDataChunkToAppend += srcListChunk->getListLen(srcOffsetInChunk + i); - setValue(offsetInDataChunkToAppend, currentIndex + i); - indicesColumnChunk->setValue(currentIndex + i, dstOffsetInChunk + i); - indicesColumnChunk->getNullChunk()->setNull(dstOffsetInChunk + i, false); - } - varListDataColumnChunk->resizeBuffer(offsetInDataChunkToAppend); - auto startOffsetInSrcChunk = srcListChunk->getListOffset(srcOffsetInChunk); - auto endOffsetInSrcChunk = srcListChunk->getListOffset(srcOffsetInChunk + numValuesToCopy); - varListDataColumnChunk->dataColumnChunk->append( - srcListChunk->varListDataColumnChunk->dataColumnChunk.get(), startOffsetInSrcChunk, - endOffsetInSrcChunk - startOffsetInSrcChunk); - if (indicesColumnChunk->getNumValues() < dstOffsetInChunk + numValuesToCopy) { - indicesColumnChunk->setNumValues(dstOffsetInChunk + numValuesToCopy + 1); - } -} - -void VarListColumnChunk::copy(ColumnChunk* srcChunk, offset_t srcOffsetInChunk, - offset_t dstOffsetInChunk, offset_t numValuesToCopy) { - KU_ASSERT(srcChunk->getDataType().getPhysicalType() == PhysicalTypeID::VAR_LIST); - KU_ASSERT(dstOffsetInChunk >= numValues); - while (numValues < dstOffsetInChunk) { - appendNullList(); - } - append(srcChunk, srcOffsetInChunk, numValuesToCopy); -} - -void VarListColumnChunk::copyListValues(const list_entry_t& entry, ValueVector* dataVector) { - auto numListValuesToCopy = entry.size; - auto numListValuesCopied = 0u; - while (numListValuesCopied < numListValuesToCopy) { - auto numListValuesToCopyInBatch = - std::min(numListValuesToCopy - numListValuesCopied, DEFAULT_VECTOR_CAPACITY); - dataVector->state->selVector->selectedSize = numListValuesToCopyInBatch; - for (auto j = 0u; j < numListValuesToCopyInBatch; j++) { - dataVector->state->selVector->selectedPositions[j] = - entry.offset + numListValuesCopied + j; - } - varListDataColumnChunk->append(dataVector); - numListValuesCopied += numListValuesToCopyInBatch; - } -} - -void VarListColumnChunk::finalize() { - if (!needFinalize) { - return; - } - auto newColumnChunk = ColumnChunkFactory::createColumnChunk( - std::move(*dataType.copy()), enableCompression, capacity); - auto totalListLen = getListOffset(numValues) + 1; - auto newVarListChunk = ku_dynamic_cast(newColumnChunk.get()); - newVarListChunk->getDataColumnChunk()->resize(totalListLen); - for (auto i = 0u; i < indicesColumnChunk->getNumValues(); i++) { - if (indicesColumnChunk->getNullChunk()->isNull(i)) { - newVarListChunk->appendNullList(); - } else { - auto index = indicesColumnChunk->getValue(i); - newColumnChunk->append(this, index, 1); - } - } - // Move offsets, null, data from newVarListChunk to this column chunk. And release indices. - resetFromOtherChunk(newVarListChunk); -} - -void VarListColumnChunk::resetFromOtherChunk(VarListColumnChunk* other) { - buffer = std::move(other->buffer); - nullChunk = std::move(other->nullChunk); - varListDataColumnChunk = std::move(other->varListDataColumnChunk); - numValues = other->numValues; - // Reset indices and needFinalize. - indicesColumnChunk.reset(); - needFinalize = false; -} - -} // namespace storage -} // namespace kuzu diff --git a/src/storage/wal/wal.cpp b/src/storage/wal/wal.cpp index 29255101d61..6fe10b73bed 100644 --- a/src/storage/wal/wal.cpp +++ b/src/storage/wal/wal.cpp @@ -2,8 +2,6 @@ #include "common/exception/runtime.h" #include "common/file_system/virtual_file_system.h" -#include "common/utils.h" -#include "spdlog/spdlog.h" // IWYU pragma: keep: public interface to spdlog. #include "storage/storage_utils.h" using namespace kuzu::common; @@ -13,8 +11,7 @@ namespace storage { WAL::WAL(const std::string& directory, bool readOnly, BufferManager& bufferManager, VirtualFileSystem* vfs) - : logger{LoggerUtils::getLogger(LoggerConstants::LoggerEnum::WAL)}, directory{directory}, - bufferManager{bufferManager}, isLastLoggedRecordCommit_{false} { + : directory{directory}, bufferManager{bufferManager}, isLastLoggedRecordCommit_{false} { fileHandle = bufferManager.getBMFileHandle( vfs->joinPath(directory, std::string(StorageConstants::WAL_FILE_SUFFIX)), readOnly ? FileHandle::O_PERSISTENT_FILE_READ_ONLY : @@ -63,32 +60,19 @@ void WAL::logCatalogRecord() { addNewWALRecordNoLock(walRecord); } -void WAL::logCreateNodeTableRecord(table_id_t tableID) { +void WAL::logCreateTableRecord(table_id_t tableID, TableType tableType) { lock_t lck{mtx}; - WALRecord walRecord = WALRecord::newCreateTableRecord(tableID, TableType::NODE); + KU_ASSERT(tableType == TableType::NODE || tableType == TableType::REL); + WALRecord walRecord = WALRecord::newCreateTableRecord(tableID, tableType); addToUpdatedTables(tableID); addNewWALRecordNoLock(walRecord); } -void WAL::logCreateRelTableRecord(table_id_t tableID) { - lock_t lck{mtx}; - WALRecord walRecord = WALRecord::newCreateTableRecord(tableID, TableType::REL); - addToUpdatedTables(tableID); - addNewWALRecordNoLock(walRecord); -} - -void WAL::logRdfGraphRecord(table_id_t rdfGraphID, table_id_t resourceTableID, +void WAL::logCreateRdfGraphRecord(table_id_t rdfGraphID, table_id_t resourceTableID, table_id_t literalTableID, table_id_t resourceTripleTableID, table_id_t literalTripleTableID) { lock_t lck{mtx}; - WALRecord walRecord = WALRecord::newRdfGraphRecord( - rdfGraphID, resourceTableID, literalTableID, resourceTripleTableID, literalTripleTableID); - addNewWALRecordNoLock(walRecord); -} - -void WAL::logOverflowFileNextBytePosRecord(DBFileID dbFileID, uint64_t prevNextByteToWriteTo) { - lock_t lck{mtx}; - WALRecord walRecord = - WALRecord::newOverflowFileNextBytePosRecord(dbFileID, prevNextByteToWriteTo); + WALRecord walRecord = WALRecord::newRdfGraphRecord(rdfGraphID, resourceTableID, literalTableID, + resourceTripleTableID, literalTripleTableID); addNewWALRecordNoLock(walRecord); } @@ -167,10 +151,9 @@ void WAL::addNewWALRecordNoLock(WALRecord& walRecord) { void WAL::setIsLastRecordCommit() { WALIterator walIterator(fileHandle, mtx); WALRecord walRecord; + KU_ASSERT(walIterator.hasNextRecord()); if (!walIterator.hasNextRecord()) { - logger->info( - "Opening an existing WAL file but the file is empty. This should never happen. file: " + - fileHandle->getFileInfo()->path); + // Opening an existing WAL file but the file is empty. This should never happen. return; } while (walIterator.hasNextRecord()) { @@ -185,8 +168,8 @@ WALIterator::WALIterator(std::shared_ptr fileHandle, std::mutex& m : BaseWALAndWALIterator{std::move(fileHandle)}, mtx{mtx} { resetCurrentHeaderPagePrefix(); if (this->fileHandle->getNumPages() > 0) { - this->fileHandle->readPage( - currentHeaderPageBuffer.get(), 0 /* first header page is at pageIdx 0 */); + this->fileHandle->readPage(currentHeaderPageBuffer.get(), + 0 /* first header page is at pageIdx 0 */); } numRecordsReadInCurrentHeaderPage = 0; } @@ -196,8 +179,8 @@ void WALIterator::getNextRecord(WALRecord& retVal) { if (!hasNextRecordNoLock()) { throw RuntimeException("WALIterator cannot read more log records from the WAL."); } - WALRecord::constructWALRecordFromBytes( - retVal, currentHeaderPageBuffer.get(), offsetInCurrentHeaderPage); + WALRecord::constructWALRecordFromBytes(retVal, currentHeaderPageBuffer.get(), + offsetInCurrentHeaderPage); numRecordsReadInCurrentHeaderPage++; if ((numRecordsReadInCurrentHeaderPage == getNumRecordsInCurrentHeaderPage()) && (getNextHeaderPageOfCurrentHeaderPage() != UINT32_MAX)) { diff --git a/src/storage/wal/wal_record.cpp b/src/storage/wal/wal_record.cpp index 54879e79117..f584a5fe0d7 100644 --- a/src/storage/wal/wal_record.cpp +++ b/src/storage/wal/wal_record.cpp @@ -60,9 +60,6 @@ bool WALRecord::operator==(const WALRecord& rhs) const { case WALRecordType::CREATE_RDF_GRAPH_RECORD: { return rdfGraphRecord == rhs.rdfGraphRecord; } - case WALRecordType::OVERFLOW_FILE_NEXT_BYTE_POS_RECORD: { - return diskOverflowFileNextBytePosRecord == rhs.diskOverflowFileNextBytePosRecord; - } case WALRecordType::COPY_TABLE_RECORD: { return copyTableRecord == rhs.copyTableRecord; } @@ -104,9 +101,6 @@ std::string walRecordTypeToString(WALRecordType walRecordType) { case WALRecordType::CREATE_RDF_GRAPH_RECORD: { return "CREATE_RDF_GRAPH_RECORD"; } - case WALRecordType::OVERFLOW_FILE_NEXT_BYTE_POS_RECORD: { - return "OVERFLOW_FILE_NEXT_BYTE_POS_RECORD"; - } case WALRecordType::COPY_TABLE_RECORD: { return "COPY_TABLE_RECORD"; } @@ -125,8 +119,8 @@ std::string walRecordTypeToString(WALRecordType walRecordType) { } } -WALRecord WALRecord::newPageInsertOrUpdateRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL, bool isInsert) { +WALRecord WALRecord::newPageInsertOrUpdateRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL, bool isInsert) { WALRecord retVal; retVal.recordType = WALRecordType::PAGE_UPDATE_OR_INSERT_RECORD; retVal.pageInsertOrUpdateRecord = @@ -134,16 +128,16 @@ WALRecord WALRecord::newPageInsertOrUpdateRecord( return retVal; } -WALRecord WALRecord::newPageUpdateRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL) { - return WALRecord::newPageInsertOrUpdateRecord( - dbFileID, pageIdxInOriginalFile, pageIdxInWAL, false /* is update */); +WALRecord WALRecord::newPageUpdateRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL) { + return WALRecord::newPageInsertOrUpdateRecord(dbFileID, pageIdxInOriginalFile, pageIdxInWAL, + false /* is update */); } -WALRecord WALRecord::newPageInsertRecord( - DBFileID dbFileID, uint64_t pageIdxInOriginalFile, uint64_t pageIdxInWAL) { - return WALRecord::newPageInsertOrUpdateRecord( - dbFileID, pageIdxInOriginalFile, pageIdxInWAL, true /* is insert */); +WALRecord WALRecord::newPageInsertRecord(DBFileID dbFileID, uint64_t pageIdxInOriginalFile, + uint64_t pageIdxInWAL) { + return WALRecord::newPageInsertOrUpdateRecord(dbFileID, pageIdxInOriginalFile, pageIdxInWAL, + true /* is insert */); } WALRecord WALRecord::newCommitRecord(uint64_t transactionID) { @@ -185,15 +179,6 @@ WALRecord WALRecord::newRdfGraphRecord(table_id_t rdfGraphID, table_id_t resourc return retVal; } -WALRecord WALRecord::newOverflowFileNextBytePosRecord( - DBFileID dbFileID_, uint64_t prevNextByteToWriteTo_) { - WALRecord retVal; - retVal.recordType = WALRecordType::OVERFLOW_FILE_NEXT_BYTE_POS_RECORD; - retVal.diskOverflowFileNextBytePosRecord = - DiskOverflowFileNextBytePosRecord(dbFileID_, prevNextByteToWriteTo_); - return retVal; -} - WALRecord WALRecord::newCopyTableRecord(table_id_t tableID) { WALRecord retVal; retVal.recordType = WALRecordType::COPY_TABLE_RECORD; diff --git a/src/storage/wal_replayer.cpp b/src/storage/wal_replayer.cpp index 011eaa868ba..61abc53a55b 100644 --- a/src/storage/wal_replayer.cpp +++ b/src/storage/wal_replayer.cpp @@ -1,9 +1,14 @@ #include "storage/wal_replayer.h" +#include + #include "catalog/catalog_entry/node_table_catalog_entry.h" #include "common/exception/storage.h" +#include "common/file_system/file_info.h" #include "storage/storage_manager.h" #include "storage/storage_utils.h" +#include "storage/store/node_table.h" +#include "storage/wal/wal_record.h" #include "storage/wal_replayer_utils.h" #include "transaction/transaction.h" @@ -41,9 +46,10 @@ void WALReplayer::replay() { if (!wal->isEmptyWAL()) { auto walIterator = wal->getIterator(); WALRecord walRecord; + std::unordered_map> fileCache; while (walIterator->hasNextRecord()) { walIterator->getNextRecord(walRecord); - replayWALRecord(walRecord); + replayWALRecord(walRecord, fileCache); } } // We next perform an in-memory checkpointing or rolling back of node/relTables. @@ -56,10 +62,11 @@ void WALReplayer::replay() { } } -void WALReplayer::replayWALRecord(WALRecord& walRecord) { +void WALReplayer::replayWALRecord(WALRecord& walRecord, + std::unordered_map>& fileCache) { switch (walRecord.recordType) { case WALRecordType::PAGE_UPDATE_OR_INSERT_RECORD: { - replayPageUpdateOrInsertRecord(walRecord); + replayPageUpdateOrInsertRecord(walRecord, fileCache); } break; case WALRecordType::TABLE_STATISTICS_RECORD: { replayTableStatisticsRecord(walRecord); @@ -75,9 +82,6 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { case WALRecordType::CREATE_RDF_GRAPH_RECORD: { replayRdfGraphRecord(walRecord); } break; - case WALRecordType::OVERFLOW_FILE_NEXT_BYTE_POS_RECORD: { - replayOverflowFileNextBytePosRecord(walRecord); - } break; case WALRecordType::COPY_TABLE_RECORD: { replayCopyTableRecord(walRecord); } break; @@ -97,12 +101,18 @@ void WALReplayer::replayWALRecord(WALRecord& walRecord) { } } -void WALReplayer::replayPageUpdateOrInsertRecord(const kuzu::storage::WALRecord& walRecord) { +void WALReplayer::replayPageUpdateOrInsertRecord(const WALRecord& walRecord, + std::unordered_map>& fileCache) { // 1. As the first step we copy over the page on disk, regardless of if we are recovering // (and checkpointing) or checkpointing while during regular execution. auto dbFileID = walRecord.pageInsertOrUpdateRecord.dbFileID; - std::unique_ptr fileInfoOfDBFile = - StorageUtils::getFileInfoForReadWrite(wal->getDirectory(), dbFileID, vfs); + auto entry = fileCache.find(dbFileID); + if (entry == fileCache.end()) { + fileCache.insert(std::make_pair(dbFileID, + StorageUtils::getFileInfoForReadWrite(wal->getDirectory(), dbFileID, vfs))); + entry = fileCache.find(dbFileID); + } + auto& fileInfoOfDBFile = entry->second; if (isCheckpoint) { if (!wal->isLastLoggedRecordCommit()) { // Nothing to undo. @@ -122,22 +132,22 @@ void WALReplayer::replayPageUpdateOrInsertRecord(const kuzu::storage::WALRecord& } } -void WALReplayer::replayTableStatisticsRecord(const kuzu::storage::WALRecord& walRecord) { +void WALReplayer::replayTableStatisticsRecord(const WALRecord& walRecord) { if (isCheckpoint) { if (walRecord.tableStatisticsRecord.isNodeTable) { - auto walFilePath = StorageUtils::getNodesStatisticsAndDeletedIDsFilePath( - vfs, wal->getDirectory(), common::FileVersionType::WAL_VERSION); - auto originalFilePath = StorageUtils::getNodesStatisticsAndDeletedIDsFilePath( - vfs, wal->getDirectory(), common::FileVersionType::ORIGINAL); + auto walFilePath = StorageUtils::getNodesStatisticsAndDeletedIDsFilePath(vfs, + wal->getDirectory(), common::FileVersionType::WAL_VERSION); + auto originalFilePath = StorageUtils::getNodesStatisticsAndDeletedIDsFilePath(vfs, + wal->getDirectory(), common::FileVersionType::ORIGINAL); vfs->overwriteFile(walFilePath, originalFilePath); if (!isRecovering) { storageManager->getNodesStatisticsAndDeletedIDs()->checkpointInMemoryIfNecessary(); } } else { - auto walFilePath = StorageUtils::getRelsStatisticsFilePath( - vfs, wal->getDirectory(), common::FileVersionType::WAL_VERSION); - auto originalFilePath = StorageUtils::getRelsStatisticsFilePath( - vfs, wal->getDirectory(), common::FileVersionType::ORIGINAL); + auto walFilePath = StorageUtils::getRelsStatisticsFilePath(vfs, wal->getDirectory(), + common::FileVersionType::WAL_VERSION); + auto originalFilePath = StorageUtils::getRelsStatisticsFilePath(vfs, + wal->getDirectory(), common::FileVersionType::ORIGINAL); vfs->overwriteFile(walFilePath, originalFilePath); if (!isRecovering) { storageManager->getRelsStatistics()->checkpointInMemoryIfNecessary(); @@ -154,10 +164,10 @@ void WALReplayer::replayTableStatisticsRecord(const kuzu::storage::WALRecord& wa void WALReplayer::replayCatalogRecord() { if (isCheckpoint) { - auto walFile = StorageUtils::getCatalogFilePath( - vfs, wal->getDirectory(), common::FileVersionType::WAL_VERSION); - auto originalFile = StorageUtils::getCatalogFilePath( - vfs, wal->getDirectory(), common::FileVersionType::ORIGINAL); + auto walFile = StorageUtils::getCatalogFilePath(vfs, wal->getDirectory(), + common::FileVersionType::WAL_VERSION); + auto originalFile = StorageUtils::getCatalogFilePath(vfs, wal->getDirectory(), + common::FileVersionType::ORIGINAL); vfs->overwriteFile(walFile, originalFile); if (!isRecovering) { catalog->checkpointInMemory(); @@ -190,36 +200,7 @@ void WALReplayer::replayRdfGraphRecord(const WALRecord& walRecord) { replayCreateTableRecord(literalTripleTableWALRecord); } -void WALReplayer::replayOverflowFileNextBytePosRecord(const WALRecord& walRecord) { - // If we are recovering we do not replay OVERFLOW_FILE_NEXT_BYTE_POS_RECORD because - // this record is intended for rolling back a transaction to ensure that we can - // recover the overflow space allocated for the write transaction by calling - // DiskOverflowFile::resetNextBytePosToWriteTo(...). However during recovery, storageManager - // is null, so we cannot construct this value. - if (isRecovering) { - return; - } - KU_ASSERT(walRecord.diskOverflowFileNextBytePosRecord.dbFileID.isOverflow); - auto dbFileID = walRecord.diskOverflowFileNextBytePosRecord.dbFileID; - DiskOverflowFile* diskOverflowFile; - switch (dbFileID.dbFileType) { - case DBFileType::NODE_INDEX: { - auto index = storageManager->getPKIndex(dbFileID.nodeIndexID.tableID); - diskOverflowFile = index->getDiskOverflowFile(); - } break; - default: - throw RuntimeException("Unsupported dbFileID " + dbFileTypeToString(dbFileID.dbFileType) + - " for OVERFLOW_FILE_NEXT_BYTE_POS_RECORD."); - } - // Reset NextBytePosToWriteTo if we are rolling back. - if (!isCheckpoint) { - diskOverflowFile->resetNextBytePosToWriteTo( - walRecord.diskOverflowFileNextBytePosRecord.prevNextBytePosToWriteTo); - } - diskOverflowFile->resetLoggedNewOverflowFileNextBytePosRecord(); -} - -void WALReplayer::replayCopyTableRecord(const kuzu::storage::WALRecord& walRecord) { +void WALReplayer::replayCopyTableRecord(const WALRecord& walRecord) { auto tableID = walRecord.copyTableRecord.tableID; if (isCheckpoint) { if (!isRecovering) { @@ -233,8 +214,9 @@ void WALReplayer::replayCopyTableRecord(const kuzu::storage::WALRecord& walRecor if (catalogEntry->getType() == CatalogEntryType::NODE_TABLE_ENTRY) { auto nodeTableEntry = ku_dynamic_cast(catalogEntry); - storageManager->getNodeTable(tableID)->initializePKIndex( - nodeTableEntry, false /* readOnly */, vfs); + auto nodeTable = + ku_dynamic_cast(storageManager->getTable(tableID)); + nodeTable->initializePKIndex(nodeTableEntry, false /* readOnly */, vfs); } } else { // RECOVERY. @@ -249,7 +231,7 @@ void WALReplayer::replayCopyTableRecord(const kuzu::storage::WALRecord& walRecor } } -void WALReplayer::replayDropTableRecord(const kuzu::storage::WALRecord& walRecord) { +void WALReplayer::replayDropTableRecord(const WALRecord& walRecord) { if (isCheckpoint) { auto tableID = walRecord.dropTableRecord.tableID; if (!isRecovering) { @@ -298,27 +280,14 @@ void WALReplayer::replayDropTableRecord(const kuzu::storage::WALRecord& walRecor } } -void WALReplayer::replayDropPropertyRecord(const kuzu::storage::WALRecord& walRecord) { +void WALReplayer::replayDropPropertyRecord(const WALRecord& walRecord) { if (isCheckpoint) { auto tableID = walRecord.dropPropertyRecord.tableID; auto propertyID = walRecord.dropPropertyRecord.propertyID; if (!isRecovering) { auto tableEntry = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID); - switch (tableEntry->getTableType()) { - case TableType::NODE: { - storageManager->getNodeTable(tableID)->dropColumn( - tableEntry->getColumnID(propertyID)); - // TODO(Guodong): Do nothing for now. Should remove metaDA and reclaim free pages. - } break; - case TableType::REL: { - storageManager->getRelTable(tableID)->dropColumn( - tableEntry->getColumnID(propertyID)); - // TODO(Guodong): Do nothing for now. Should remove metaDA and reclaim free pages. - } break; - default: { - KU_UNREACHABLE; - } - } + storageManager->getTable(tableID)->dropColumn(tableEntry->getColumnID(propertyID)); + // TODO(Guodong): Do nothing for now. Should remove metaDA and reclaim free pages. } else { if (!wal->isLastLoggedRecordCommit()) { // Nothing to undo. @@ -331,27 +300,17 @@ void WALReplayer::replayDropPropertyRecord(const kuzu::storage::WALRecord& walRe } } -void WALReplayer::replayAddPropertyRecord(const kuzu::storage::WALRecord& walRecord) { +void WALReplayer::replayAddPropertyRecord(const WALRecord& walRecord) { auto tableID = walRecord.addPropertyRecord.tableID; auto propertyID = walRecord.addPropertyRecord.propertyID; if (!isCheckpoint) { auto tableEntry = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID); - switch (tableEntry->getTableType()) { - case TableType::NODE: { - storageManager->getNodeTable(tableID)->dropColumn(tableEntry->getColumnID(propertyID)); - } break; - case TableType::REL: { - storageManager->getRelTable(tableID)->dropColumn(tableEntry->getColumnID(propertyID)); - } break; - default: { - KU_UNREACHABLE; - } - } + storageManager->getTable(tableID)->dropColumn(tableEntry->getColumnID(propertyID)); } } -void WALReplayer::truncateFileIfInsertion( - BMFileHandle* fileHandle, const PageUpdateOrInsertRecord& pageInsertOrUpdateRecord) { +void WALReplayer::truncateFileIfInsertion(BMFileHandle* fileHandle, + const PageUpdateOrInsertRecord& pageInsertOrUpdateRecord) { if (pageInsertOrUpdateRecord.isInsert) { // If we are rolling back and this is a page insertion we truncate the fileHandle's // data structures that hold locks for pageIdxs. @@ -398,7 +357,7 @@ BMFileHandle* WALReplayer::getVersionedFileHandleIfWALVersionAndBMShouldBeCleare } case DBFileType::NODE_INDEX: { auto index = storageManager->getPKIndex(dbFileID.nodeIndexID.tableID); - return dbFileID.isOverflow ? index->getDiskOverflowFile()->getFileHandle() : + return dbFileID.isOverflow ? index->getOverflowFile()->getBMFileHandle() : index->getFileHandle(); } default: { diff --git a/src/storage/wal_replayer_utils.cpp b/src/storage/wal_replayer_utils.cpp index 259c9b4c86f..51ab6cd8ba8 100644 --- a/src/storage/wal_replayer_utils.cpp +++ b/src/storage/wal_replayer_utils.cpp @@ -9,8 +9,8 @@ using namespace kuzu::common; namespace kuzu { namespace storage { -void WALReplayerUtils::removeHashIndexFile( - common::VirtualFileSystem* vfs, table_id_t tableID, const std::string& directory) { +void WALReplayerUtils::removeHashIndexFile(common::VirtualFileSystem* vfs, table_id_t tableID, + const std::string& directory) { vfs->removeFileIfExists( StorageUtils::getNodeIndexFName(vfs, directory, tableID, FileVersionType::ORIGINAL)); } @@ -21,8 +21,8 @@ void WALReplayerUtils::createEmptyHashIndexFiles(catalog::NodeTableCatalogEntry* auto dt = pk->getDataType(); if (dt->getLogicalTypeID() != LogicalTypeID::SERIAL) { auto pkIndex = make_unique( - StorageUtils::getNodeIndexFName( - vfs, directory, nodeTableEntry->getTableID(), FileVersionType::ORIGINAL), + StorageUtils::getNodeIndexFName(vfs, directory, nodeTableEntry->getTableID(), + FileVersionType::ORIGINAL), pk->getDataType()->getPhysicalType(), vfs); pkIndex->bulkReserve(0 /* numNodes */); pkIndex->flush(); diff --git a/src/transaction/transaction_context.cpp b/src/transaction/transaction_context.cpp index 395496c4f5c..b88cac40ae1 100644 --- a/src/transaction/transaction_context.cpp +++ b/src/transaction/transaction_context.cpp @@ -2,6 +2,7 @@ #include "common/exception/connection.h" #include "common/exception/transaction_manager.h" +#include "main/client_context.h" #include "main/database.h" #include "transaction/transaction_manager.h" @@ -10,12 +11,12 @@ using namespace kuzu::common; namespace kuzu { namespace transaction { -TransactionContext::TransactionContext(main::Database* database) - : database{database}, mode{TransactionMode::AUTO} {} +TransactionContext::TransactionContext(main::ClientContext& clientContext) + : clientContext{clientContext}, mode{TransactionMode::AUTO} {} TransactionContext::~TransactionContext() { if (activeTransaction) { - database->transactionManager->rollback(activeTransaction.get()); + clientContext.getDatabase()->transactionManager->rollback(activeTransaction.get()); } } @@ -39,8 +40,8 @@ void TransactionContext::beginAutoTransaction(bool readOnlyStatement) { readOnlyStatement ? TransactionType::READ_ONLY : TransactionType::WRITE); } -void TransactionContext::validateManualTransaction( - bool allowActiveTransaction, bool readOnlyStatement) { +void TransactionContext::validateManualTransaction(bool allowActiveTransaction, + bool readOnlyStatement) { KU_ASSERT(hasActiveTransaction()); if (activeTransaction->isReadOnly() && !readOnlyStatement) { throw ConnectionException("Can't execute a write query inside a read-only transaction."); @@ -73,7 +74,7 @@ void TransactionContext::commitInternal(bool skipCheckPointing) { if (!hasActiveTransaction()) { return; } - database->commit(activeTransaction.get(), skipCheckPointing); + clientContext.getDatabase()->commit(activeTransaction.get(), skipCheckPointing); activeTransaction.reset(); mode = TransactionMode::AUTO; } @@ -82,7 +83,7 @@ void TransactionContext::rollbackInternal(bool skipCheckPointing) { if (!hasActiveTransaction()) { return; } - database->rollback(activeTransaction.get(), skipCheckPointing); + clientContext.getDatabase()->rollback(activeTransaction.get(), skipCheckPointing); activeTransaction.reset(); mode = TransactionMode::AUTO; } @@ -97,10 +98,13 @@ void TransactionContext::beginTransactionInternal(TransactionType transactionTyp } switch (transactionType) { case TransactionType::READ_ONLY: { - activeTransaction = database->transactionManager->beginReadOnlyTransaction(); + activeTransaction = + clientContext.getDatabase()->transactionManager->beginReadOnlyTransaction( + clientContext); } break; case TransactionType::WRITE: { - activeTransaction = database->transactionManager->beginWriteTransaction(); + activeTransaction = + clientContext.getDatabase()->transactionManager->beginWriteTransaction(clientContext); } break; default: KU_UNREACHABLE; diff --git a/src/transaction/transaction_manager.cpp b/src/transaction/transaction_manager.cpp index f4306a3f1ab..11daaba5799 100644 --- a/src/transaction/transaction_manager.cpp +++ b/src/transaction/transaction_manager.cpp @@ -9,7 +9,8 @@ using namespace kuzu::common; namespace kuzu { namespace transaction { -std::unique_ptr TransactionManager::beginWriteTransaction() { +std::unique_ptr TransactionManager::beginWriteTransaction( + main::ClientContext& clientContext) { // We obtain the lock for starting new transactions. In case this cannot be obtained this // ensures calls to other public functions is not restricted. lock_t newTransactionLck{mtxForStartingNewTransactions}; @@ -20,18 +21,19 @@ std::unique_ptr TransactionManager::beginWriteTransaction() { "time is allowed in the system."); } auto transaction = - std::make_unique(TransactionType::WRITE, ++lastTransactionID, mm); + std::make_unique(clientContext, TransactionType::WRITE, ++lastTransactionID); activeWriteTransactionID = lastTransactionID; return transaction; } -std::unique_ptr TransactionManager::beginReadOnlyTransaction() { +std::unique_ptr TransactionManager::beginReadOnlyTransaction( + main::ClientContext& clientContext) { // We obtain the lock for starting new transactions. In case this cannot be obtained this // ensures calls to other public functions is not restricted. lock_t newTransactionLck{mtxForStartingNewTransactions}; lock_t publicFunctionLck{mtxForSerializingPublicFunctionCalls}; - auto transaction = - std::make_unique(TransactionType::READ_ONLY, ++lastTransactionID, mm); + auto transaction = std::make_unique(clientContext, TransactionType::READ_ONLY, + ++lastTransactionID); activeReadOnlyTransactionIDs.insert(transaction->getID()); return transaction; } diff --git a/test/c_api/connection_test.cpp b/test/c_api/connection_test.cpp index c3989dc2ac6..3acd8c647f8 100644 --- a/test/c_api/connection_test.cpp +++ b/test/c_api/connection_test.cpp @@ -101,8 +101,8 @@ TEST_F(CApiConnectionTest, Execute) { TEST_F(CApiConnectionTest, QueryTimeout) { auto connection = getConnection(); kuzu_connection_set_query_timeout(connection, 1); - auto result = kuzu_connection_query( - connection, "MATCH (a:person)-[:knows*1..28]->(b:person) RETURN COUNT(*);"); + auto result = kuzu_connection_query(connection, + "MATCH (a:person)-[:knows*1..28]->(b:person) RETURN COUNT(*);"); ASSERT_NE(result, nullptr); ASSERT_NE(result->_query_result, nullptr); auto resultCpp = static_cast(result->_query_result); @@ -124,8 +124,8 @@ TEST_F(CApiConnectionTest, Interrupt) { kuzu_connection_interrupt(connection); } while (!finished); }); - auto result = kuzu_connection_query( - connection, "MATCH (a:person)-[:knows*1..28]->(b:person) RETURN COUNT(*);"); + auto result = kuzu_connection_query(connection, + "MATCH (a:person)-[:knows*1..28]->(b:person) RETURN COUNT(*);"); finished = true; ASSERT_NE(result, nullptr); ASSERT_NE(result->_query_result, nullptr); diff --git a/test/c_api/data_type_test.cpp b/test/c_api/data_type_test.cpp index 6708927d36f..70c3faf75c6 100644 --- a/test/c_api/data_type_test.cpp +++ b/test/c_api/data_type_test.cpp @@ -10,18 +10,18 @@ TEST(CApiDataTypeTest, Create) { auto dataTypeCpp = (LogicalType*)dataType->_data_type; ASSERT_EQ(dataTypeCpp->getLogicalTypeID(), LogicalTypeID::INT64); - auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_VAR_LIST, dataType, 0); + auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_LIST, dataType, 0); ASSERT_NE(dataType2, nullptr); auto dataTypeCpp2 = (LogicalType*)dataType2->_data_type; - ASSERT_EQ(dataTypeCpp2->getLogicalTypeID(), LogicalTypeID::VAR_LIST); + ASSERT_EQ(dataTypeCpp2->getLogicalTypeID(), LogicalTypeID::LIST); // ASSERT_EQ(dataTypeCpp2->getChildType()->getLogicalTypeID(), LogicalTypeID::INT64); - auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_FIXED_LIST, dataType, 100); + auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_ARRAY, dataType, 100); ASSERT_NE(dataType3, nullptr); auto dataTypeCpp3 = (LogicalType*)dataType3->_data_type; - ASSERT_EQ(dataTypeCpp3->getLogicalTypeID(), LogicalTypeID::FIXED_LIST); + ASSERT_EQ(dataTypeCpp3->getLogicalTypeID(), LogicalTypeID::ARRAY); // ASSERT_EQ(dataTypeCpp3->getChildType()->getLogicalTypeID(), LogicalTypeID::INT64); - ASSERT_EQ(FixedListType::getNumValuesInList(dataTypeCpp3), 100); + ASSERT_EQ(ArrayType::getNumElements(dataTypeCpp3), 100); // Since child type is copied, we should be able to destroy the original type without an error. kuzu_data_type_destroy(dataType); @@ -38,7 +38,7 @@ TEST(CApiDataTypeTest, Clone) { auto dataTypeCloneCpp = (LogicalType*)dataTypeClone->_data_type; ASSERT_TRUE(*dataTypeCpp == *dataTypeCloneCpp); - auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_VAR_LIST, dataType, 0); + auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_LIST, dataType, 0); ASSERT_NE(dataType2, nullptr); auto dataTypeClone2 = kuzu_data_type_clone(dataType2); ASSERT_NE(dataTypeClone2, nullptr); @@ -46,7 +46,7 @@ TEST(CApiDataTypeTest, Clone) { auto dataTypeCloneCpp2 = (LogicalType*)dataTypeClone2->_data_type; ASSERT_TRUE(*dataTypeCpp2 == *dataTypeCloneCpp2); - auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_FIXED_LIST, dataType, 100); + auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_ARRAY, dataType, 100); ASSERT_NE(dataType3, nullptr); auto dataTypeClone3 = kuzu_data_type_clone(dataType3); ASSERT_NE(dataTypeClone3, nullptr); @@ -69,13 +69,13 @@ TEST(CApiDataTypeTest, Eqauls) { ASSERT_NE(dataTypeClone, nullptr); ASSERT_TRUE(kuzu_data_type_equals(dataType, dataTypeClone)); - auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_VAR_LIST, dataType, 0); + auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_LIST, dataType, 0); ASSERT_NE(dataType2, nullptr); auto dataTypeClone2 = kuzu_data_type_clone(dataType2); ASSERT_NE(dataTypeClone2, nullptr); ASSERT_TRUE(kuzu_data_type_equals(dataType2, dataTypeClone2)); - auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_FIXED_LIST, dataType, 100); + auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_ARRAY, dataType, 100); ASSERT_NE(dataType3, nullptr); auto dataTypeClone3 = kuzu_data_type_clone(dataType3); ASSERT_NE(dataTypeClone3, nullptr); @@ -98,13 +98,13 @@ TEST(CApiDataTypeTest, GetID) { ASSERT_NE(dataType, nullptr); ASSERT_EQ(kuzu_data_type_get_id(dataType), kuzu_data_type_id::KUZU_INT64); - auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_VAR_LIST, dataType, 0); + auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_LIST, dataType, 0); ASSERT_NE(dataType2, nullptr); - ASSERT_EQ(kuzu_data_type_get_id(dataType2), kuzu_data_type_id::KUZU_VAR_LIST); + ASSERT_EQ(kuzu_data_type_get_id(dataType2), kuzu_data_type_id::KUZU_LIST); - auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_FIXED_LIST, dataType, 100); + auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_ARRAY, dataType, 100); ASSERT_NE(dataType3, nullptr); - ASSERT_EQ(kuzu_data_type_get_id(dataType3), kuzu_data_type_id::KUZU_FIXED_LIST); + ASSERT_EQ(kuzu_data_type_get_id(dataType3), kuzu_data_type_id::KUZU_ARRAY); kuzu_data_type_destroy(dataType); kuzu_data_type_destroy(dataType2); @@ -118,7 +118,7 @@ TEST(CApiDataTypeTest, GetID) { // ASSERT_NE(dataType, nullptr); // ASSERT_EQ(kuzu_data_type_get_child_type(dataType), nullptr); // -// auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_VAR_LIST, dataType, 0); +// auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_LIST, dataType, 0); // ASSERT_NE(dataType2, nullptr); // auto childType2 = kuzu_data_type_get_child_type(dataType2); // ASSERT_NE(childType2, nullptr); @@ -126,7 +126,7 @@ TEST(CApiDataTypeTest, GetID) { // kuzu_data_type_destroy(childType2); // kuzu_data_type_destroy(dataType2); // -// auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_FIXED_LIST, dataType, 100); +// auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_ARRAY, dataType, 100); // ASSERT_NE(dataType3, nullptr); // auto childType3 = kuzu_data_type_get_child_type(dataType3); // kuzu_data_type_destroy(dataType3); @@ -141,15 +141,15 @@ TEST(CApiDataTypeTest, GetID) { TEST(CApiDataTypeTest, GetFixedNumElementsInList) { auto dataType = kuzu_data_type_create(kuzu_data_type_id::KUZU_INT64, nullptr, 0); ASSERT_NE(dataType, nullptr); - ASSERT_EQ(kuzu_data_type_get_fixed_num_elements_in_list(dataType), 0); + ASSERT_EQ(kuzu_data_type_get_num_elements_in_array(dataType), 0); - auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_VAR_LIST, dataType, 0); + auto dataType2 = kuzu_data_type_create(kuzu_data_type_id::KUZU_LIST, dataType, 0); ASSERT_NE(dataType2, nullptr); - ASSERT_EQ(kuzu_data_type_get_fixed_num_elements_in_list(dataType2), 0); + ASSERT_EQ(kuzu_data_type_get_num_elements_in_array(dataType2), 0); - auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_FIXED_LIST, dataType, 100); + auto dataType3 = kuzu_data_type_create(kuzu_data_type_id::KUZU_ARRAY, dataType, 100); ASSERT_NE(dataType3, nullptr); - ASSERT_EQ(kuzu_data_type_get_fixed_num_elements_in_list(dataType3), 100); + ASSERT_EQ(kuzu_data_type_get_num_elements_in_array(dataType3), 100); kuzu_data_type_destroy(dataType); kuzu_data_type_destroy(dataType2); diff --git a/test/c_api/database_test.cpp b/test/c_api/database_test.cpp index 5424e03fdaf..805a384b736 100644 --- a/test/c_api/database_test.cpp +++ b/test/c_api/database_test.cpp @@ -58,3 +58,10 @@ TEST_F(CApiDatabaseTest, CreationInvalidPath) { auto database = kuzu_database_init(databasePathCStr, kuzu_default_system_config()); ASSERT_EQ(database, nullptr); } + +TEST_F(CApiDatabaseTest, CreationHomeDir) { + auto databasePathCStr = (char*)"~/ku_test.db"; + auto database = kuzu_database_init(databasePathCStr, kuzu_default_system_config()); + ASSERT_NE(database, nullptr); + kuzu_database_destroy(database); +} diff --git a/test/c_api/flat_tuple_test.cpp b/test/c_api/flat_tuple_test.cpp index bdc7c48ab82..c5c00c9c937 100644 --- a/test/c_api/flat_tuple_test.cpp +++ b/test/c_api/flat_tuple_test.cpp @@ -13,8 +13,8 @@ class CApiFlatTupleTest : public CApiTest { TEST_F(CApiFlatTupleTest, GetValue) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, "MATCH (a:person) RETURN a.fName, a.age, a.height ORDER BY a.fName LIMIT 1"); + auto result = kuzu_connection_query(connection, + "MATCH (a:person) RETURN a.fName, a.age, a.height ORDER BY a.fName LIMIT 1"); ASSERT_TRUE(kuzu_query_result_is_success(result)); auto flatTuple = kuzu_query_result_get_next(result); ASSERT_NE(flatTuple, nullptr); @@ -47,8 +47,8 @@ TEST_F(CApiFlatTupleTest, GetValue) { TEST_F(CApiFlatTupleTest, ToString) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, "MATCH (a:person) RETURN a.fName, a.age, a.height ORDER BY a.fName LIMIT 1"); + auto result = kuzu_connection_query(connection, + "MATCH (a:person) RETURN a.fName, a.age, a.height ORDER BY a.fName LIMIT 1"); ASSERT_TRUE(kuzu_query_result_is_success(result)); auto flatTuple = kuzu_query_result_get_next(result); ASSERT_NE(flatTuple, nullptr); diff --git a/test/c_api/query_result_test.cpp b/test/c_api/query_result_test.cpp index 48dd7be9f24..c2f811bf49e 100644 --- a/test/c_api/query_result_test.cpp +++ b/test/c_api/query_result_test.cpp @@ -125,8 +125,8 @@ TEST_F(CApiQueryResultTest, GetQuerySummary) { TEST_F(CApiQueryResultTest, GetNext) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, "MATCH (a:person) RETURN a.fName, a.age ORDER BY a.fName"); + auto result = kuzu_connection_query(connection, + "MATCH (a:person) RETURN a.fName, a.age ORDER BY a.fName"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); @@ -151,8 +151,8 @@ TEST_F(CApiQueryResultTest, GetNext) { TEST_F(CApiQueryResultTest, ResetIterator) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, "MATCH (a:person) RETURN a.fName, a.age ORDER BY a.fName"); + auto result = kuzu_connection_query(connection, + "MATCH (a:person) RETURN a.fName, a.age ORDER BY a.fName"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); @@ -176,3 +176,30 @@ TEST_F(CApiQueryResultTest, ResetIterator) { kuzu_query_result_destroy(result); } + +TEST_F(CApiQueryResultTest, MultipleQuery) { + auto connection = getConnection(); + auto result = kuzu_connection_query(connection, "return 1; return 2; return 3;"); + ASSERT_TRUE(kuzu_query_result_is_success(result)); + + auto str = kuzu_query_result_to_string(result); + ASSERT_EQ(std::string(str), "1\n1\n"); + kuzu_destroy_string(str); + + ASSERT_TRUE(kuzu_query_result_has_next_query_result(result)); + auto next_query_result = kuzu_query_result_get_next_query_result(result); + ASSERT_TRUE(kuzu_query_result_is_success(next_query_result)); + str = kuzu_query_result_to_string(next_query_result); + ASSERT_EQ(std::string(str), "2\n2\n"); + kuzu_destroy_string(str); + kuzu_query_result_destroy(next_query_result); + + next_query_result = kuzu_query_result_get_next_query_result(result); + ASSERT_TRUE(kuzu_query_result_is_success(next_query_result)); + str = kuzu_query_result_to_string(next_query_result); + ASSERT_EQ(std::string(str), "3\n3\n"); + kuzu_destroy_string(str); + kuzu_query_result_destroy(next_query_result); + + kuzu_query_result_destroy(result); +} diff --git a/test/c_api/value_test.cpp b/test/c_api/value_test.cpp index 3063298da48..345582f5f61 100644 --- a/test/c_api/value_test.cpp +++ b/test/c_api/value_test.cpp @@ -310,8 +310,8 @@ TEST(CApiValueTestEmptyDB, Copy) { TEST_F(CApiValueTest, GetListSize) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.workedHours ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.workedHours ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -326,8 +326,8 @@ TEST_F(CApiValueTest, GetListSize) { TEST_F(CApiValueTest, GetListElement) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.workedHours ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.workedHours ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -356,8 +356,8 @@ TEST_F(CApiValueTest, GetListElement) { TEST_F(CApiValueTest, GetStructNumFields) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -371,8 +371,8 @@ TEST_F(CApiValueTest, GetStructNumFields) { TEST_F(CApiValueTest, GetStructFieldName) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -420,8 +420,8 @@ TEST_F(CApiValueTest, GetStructFieldName) { TEST_F(CApiValueTest, GetStructFieldValue) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (m:movies) WHERE m.name=\"Roma\" RETURN m.description"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -501,8 +501,8 @@ TEST_F(CApiValueTest, GetStructFieldValue) { TEST_F(CApiValueTest, GetDataType) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.fName, a.isStudent, a.workedHours"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.fName, a.isStudent, a.workedHours"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -520,7 +520,7 @@ TEST_F(CApiValueTest, GetDataType) { value = kuzu_flat_tuple_get_value(flatTuple, 2); dataType = kuzu_value_get_data_type(value); - ASSERT_EQ(kuzu_data_type_get_id(dataType), KUZU_VAR_LIST); + ASSERT_EQ(kuzu_data_type_get_id(dataType), KUZU_LIST); kuzu_data_type_destroy(dataType); kuzu_value_destroy(value); @@ -530,8 +530,8 @@ TEST_F(CApiValueTest, GetDataType) { TEST_F(CApiValueTest, GetBool) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.isStudent ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.isStudent ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -578,8 +578,8 @@ TEST_F(CApiValueTest, GetInt16) { TEST_F(CApiValueTest, GetInt32) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (m:movies) RETURN m.length ORDER BY m.name"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (m:movies) RETURN m.length ORDER BY m.name"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -723,8 +723,8 @@ TEST_F(CApiValueTest, GetFloat) { TEST_F(CApiValueTest, GetDouble) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.eyeSight ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.eyeSight ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -758,8 +758,8 @@ TEST_F(CApiValueTest, GetInternalID) { TEST_F(CApiValueTest, GetRelVal) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) -[r:knows]-> (b:person) RETURN r ORDER BY a.ID, b.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) -[r:knows]-> (b:person) RETURN r ORDER BY a.ID, b.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -789,8 +789,8 @@ TEST_F(CApiValueTest, GetRelVal) { TEST_F(CApiValueTest, GetDate) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.birthdate ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.birthdate ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -805,8 +805,8 @@ TEST_F(CApiValueTest, GetDate) { TEST_F(CApiValueTest, GetTimestamp) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.registerTime ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.registerTime ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -821,8 +821,8 @@ TEST_F(CApiValueTest, GetTimestamp) { TEST_F(CApiValueTest, GetInterval) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)"MATCH (a:person) RETURN a.lastJobDuration ORDER BY a.ID"); + auto result = kuzu_connection_query(connection, + (char*)"MATCH (a:person) RETURN a.lastJobDuration ORDER BY a.ID"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); @@ -879,8 +879,8 @@ TEST_F(CApiValueTest, GetBlob) { TEST_F(CApiValueTest, GetUUID) { auto connection = getConnection(); - auto result = kuzu_connection_query( - connection, (char*)R"(RETURN UUID("A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11");)"); + auto result = kuzu_connection_query(connection, + (char*)R"(RETURN UUID("A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11");)"); ASSERT_TRUE(kuzu_query_result_is_success(result)); ASSERT_TRUE(kuzu_query_result_has_next(result)); auto flatTuple = kuzu_query_result_get_next(result); diff --git a/test/common/interval_test.cpp b/test/common/interval_test.cpp index ea6137c13ed..7bd548a92ff 100644 --- a/test/common/interval_test.cpp +++ b/test/common/interval_test.cpp @@ -12,8 +12,8 @@ TEST(IntervalTests, FromCString) { EXPECT_EQ(result.months, 28); EXPECT_EQ(result.days, 21); EXPECT_EQ(result.micros, 11040000028); - result = Interval::fromCString( - "32 days 48 hours 12 minutes 280 us", strlen("32 days 48 hours 12 minutes 280 us")); + result = Interval::fromCString("32 days 48 hours 12 minutes 280 us", + strlen("32 days 48 hours 12 minutes 280 us")); EXPECT_EQ(result.months, 0); EXPECT_EQ(result.days, 32); EXPECT_EQ(result.micros, 173520000280); @@ -29,8 +29,8 @@ TEST(IntervalTests, FromCString) { EXPECT_EQ(result.months, 28); EXPECT_EQ(result.days, 21); EXPECT_EQ(result.micros, 11040000028); - result = Interval::fromCString( - "2 years 4 months 21 days 03:04:00", strlen("2 years 4 months 21 days 03:04:00")); + result = Interval::fromCString("2 years 4 months 21 days 03:04:00", + strlen("2 years 4 months 21 days 03:04:00")); EXPECT_EQ(result.months, 28); EXPECT_EQ(result.days, 21); EXPECT_EQ(result.micros, 11040000000); diff --git a/test/common/null_mask_test.cpp b/test/common/null_mask_test.cpp index 5898d58e7a2..983c4e7b93b 100644 --- a/test/common/null_mask_test.cpp +++ b/test/common/null_mask_test.cpp @@ -16,8 +16,8 @@ TEST(NullMaskTests, TestRangeSingleEntry) { } TEST(NullMaskTests, TestRangeMultipleEntries) { - std::vector data{ - NullMask::ALL_NULL_ENTRY, NullMask::ALL_NULL_ENTRY, NullMask::ALL_NULL_ENTRY}; + std::vector data{NullMask::ALL_NULL_ENTRY, NullMask::ALL_NULL_ENTRY, + NullMask::ALL_NULL_ENTRY}; NullMask::setNullRange(data.data(), 5, 150, false); ASSERT_EQ(data[0], 0b11111); ASSERT_EQ(data[1], 0); @@ -85,10 +85,10 @@ TEST(NullMaskTests, CopyNullMaskReturnValue) { std::vector source(10, ~0ull); std::vector dest(10); ASSERT_EQ(NullMask::copyNullMask(source.data(), 0, dest.data(), 0, 64, false /*invert*/), true); - ASSERT_EQ( - NullMask::copyNullMask(emptySource.data(), 0, dest.data(), 0, 64, false /*invert*/), false); + ASSERT_EQ(NullMask::copyNullMask(emptySource.data(), 0, dest.data(), 0, 64, false /*invert*/), + false); ASSERT_EQ(NullMask::copyNullMask(source.data(), 0, dest.data(), 0, 64, true /*invert*/), false); - ASSERT_EQ( - NullMask::copyNullMask(emptySource.data(), 0, dest.data(), 0, 64, true /*invert*/), true); + ASSERT_EQ(NullMask::copyNullMask(emptySource.data(), 0, dest.data(), 0, 64, true /*invert*/), + true); } diff --git a/test/common/time_test.cpp b/test/common/time_test.cpp index 276b3fc4acc..01d1830310b 100644 --- a/test/common/time_test.cpp +++ b/test/common/time_test.cpp @@ -10,36 +10,44 @@ TEST(TimeTests, FromTime) { Time::fromTime(25, 24, 32, 231321); FAIL(); } catch (ConversionException& e) { - ASSERT_STREQ( - e.what(), "Conversion exception: Time field value out of range: 25:24:32[.231321]."); - } catch (std::exception& e) { FAIL(); } + ASSERT_STREQ(e.what(), + "Conversion exception: Time field value out of range: 25:24:32[.231321]."); + } catch (std::exception& e) { + FAIL(); + } // Minute out of range try { Time::fromTime(21, 60, 22, 212322); FAIL(); } catch (ConversionException& e) { - ASSERT_STREQ( - e.what(), "Conversion exception: Time field value out of range: 21:60:22[.212322]."); - } catch (std::exception& e) { FAIL(); } + ASSERT_STREQ(e.what(), + "Conversion exception: Time field value out of range: 21:60:22[.212322]."); + } catch (std::exception& e) { + FAIL(); + } // Second out of range try { Time::fromTime(14, 22, 61); FAIL(); } catch (ConversionException& e) { - ASSERT_STREQ( - e.what(), "Conversion exception: Time field value out of range: 14:22:61[.0]."); - } catch (std::exception& e) { FAIL(); } + ASSERT_STREQ(e.what(), + "Conversion exception: Time field value out of range: 14:22:61[.0]."); + } catch (std::exception& e) { + FAIL(); + } // Microsecond out of range try { Time::fromTime(14, 22, 42, 1000001); FAIL(); } catch (ConversionException& e) { - ASSERT_STREQ( - e.what(), "Conversion exception: Time field value out of range: 14:22:42[.1000001]."); - } catch (std::exception& e) { FAIL(); } + ASSERT_STREQ(e.what(), + "Conversion exception: Time field value out of range: 14:22:42[.1000001]."); + } catch (std::exception& e) { + FAIL(); + } EXPECT_EQ(80052000000, Time::fromTime(22, 14, 12).micros); EXPECT_EQ(58991000024, Time::fromTime(16, 23, 11, 24).micros); @@ -53,7 +61,9 @@ TEST(TimeTests, FromCString) { } catch (ConversionException& e) { ASSERT_STREQ(e.what(), "Conversion exception: Error occurred during parsing time. Given: " "\"25:12:00\". Expected format: (hh:mm:ss[.zzzzzz])."); - } catch (std::exception& e) { FAIL(); } + } catch (std::exception& e) { + FAIL(); + } // Hour out of range try { @@ -62,7 +72,9 @@ TEST(TimeTests, FromCString) { } catch (ConversionException& e) { ASSERT_STREQ(e.what(), "Conversion exception: Error occurred during parsing time. Given: " "\"24:00:00\". Expected format: (hh:mm:ss[.zzzzzz])."); - } catch (std::exception& e) { FAIL(); } + } catch (std::exception& e) { + FAIL(); + } EXPECT_EQ(83531000000, Time::fromCString("23:12:11", strlen("23:12:11")).micros); EXPECT_EQ(46792122311, Time::fromCString("12:59:52.122311", strlen("12:59:52.122311")).micros); diff --git a/test/common/timestamp_test.cpp b/test/common/timestamp_test.cpp index 2d3e19106cb..bd8e2fc37eb 100644 --- a/test/common/timestamp_test.cpp +++ b/test/common/timestamp_test.cpp @@ -12,7 +12,9 @@ TEST(TimestampTests, FromDatetime) { FAIL(); } catch (ConversionException& e) { ASSERT_STREQ(e.what(), "Conversion exception: Date out of range: 1968-12-42."); - } catch (std::exception& e) { FAIL(); } + } catch (std::exception& e) { + FAIL(); + } // 2021 is not a leap year, February only has 28 days. try { @@ -20,16 +22,20 @@ TEST(TimestampTests, FromDatetime) { FAIL(); } catch (ConversionException& e) { ASSERT_STREQ(e.what(), "Conversion exception: Date out of range: 2021-2-29."); - } catch (std::exception& e) { FAIL(); } + } catch (std::exception& e) { + FAIL(); + } // hour is out of range try { Timestamp::fromDateTime(Date::fromDate(1968, 12, 22), Time::fromTime(25, 32, 51)); FAIL(); } catch (ConversionException& e) { - ASSERT_STREQ( - e.what(), "Conversion exception: Time field value out of range: 25:32:51[.0]."); - } catch (std::exception& e) { FAIL(); } + ASSERT_STREQ(e.what(), + "Conversion exception: Time field value out of range: 25:32:51[.0]."); + } catch (std::exception& e) { + FAIL(); + } // second is out of range try { @@ -37,16 +43,20 @@ TEST(TimestampTests, FromDatetime) { FAIL(); } catch (ConversionException& e) { ASSERT_STREQ(e.what(), "Conversion exception: Time field value out of range: 5:52:70[.0]."); - } catch (std::exception& e) { FAIL(); } + } catch (std::exception& e) { + FAIL(); + } // microsecond is out of rarnge try { Timestamp::fromDateTime(Date::fromDate(2021, 2, 28), Time::fromTime(5, 52, 42, 1000002)); FAIL(); } catch (ConversionException& e) { - ASSERT_STREQ( - e.what(), "Conversion exception: Time field value out of range: 5:52:42[.1000002]."); - } catch (std::exception& e) { FAIL(); } + ASSERT_STREQ(e.what(), + "Conversion exception: Time field value out of range: 5:52:42[.1000002]."); + } catch (std::exception& e) { + FAIL(); + } EXPECT_EQ( Timestamp::fromDateTime(Date::fromDate(2020, 10, 22), Time::fromTime(21, 32, 51)).value, @@ -85,12 +95,12 @@ TEST(TimestampTests, FromCString) { Timestamp::fromCString("2112-08-21 08:21:23.005612Z", strlen("2112-08-21 08:21:23.005612Z")) .value, 4501210883005612); - EXPECT_EQ(Timestamp::fromCString( - "2112-08-21 08:21:23.005612Z+00:00", strlen("2112-08-21 08:21:23.005612Z+00:00")) + EXPECT_EQ(Timestamp::fromCString("2112-08-21 08:21:23.005612Z+00:00", + strlen("2112-08-21 08:21:23.005612Z+00:00")) .value, 4501210883005612); - EXPECT_EQ(Timestamp::fromCString( - "2112-08-21 08:21:23.005612Z+02:00", strlen("2112-08-21 08:21:23.005612Z+02:00")) + EXPECT_EQ(Timestamp::fromCString("2112-08-21 08:21:23.005612Z+02:00", + strlen("2112-08-21 08:21:23.005612Z+02:00")) .value, 4501203683005612); EXPECT_EQ( @@ -100,8 +110,8 @@ TEST(TimestampTests, FromCString) { EXPECT_EQ( Timestamp::fromCString("1992-04-28T09:22:56-09", strlen("1992-04-28T09:22:56-09")).value, 704485376000000); - EXPECT_EQ(Timestamp::fromCString( - "1992-04-28T09:22:56-09:00 ", strlen("1992-04-28T09:22:56-09:00 ")) + EXPECT_EQ(Timestamp::fromCString("1992-04-28T09:22:56-09:00 ", + strlen("1992-04-28T09:22:56-09:00 ")) .value, 704485376000000); EXPECT_EQ( diff --git a/test/copy/e2e_copy_transaction_test.cpp b/test/copy/e2e_copy_transaction_test.cpp index 7510cef2662..34a286ffd93 100644 --- a/test/copy/e2e_copy_transaction_test.cpp +++ b/test/copy/e2e_copy_transaction_test.cpp @@ -1,9 +1,11 @@ #include #include "binder/bound_statement_result.h" +#include "catalog/catalog.h" #include "graph_test/graph_test.h" #include "processor/plan_mapper.h" #include "processor/processor.h" +#include "storage/storage_manager.h" #include "transaction/transaction.h" using namespace kuzu::catalog; @@ -64,12 +66,11 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { void copyNodeCSVCommitAndRecoveryTest(TransactionTestType transactionTestType) { conn->query(createPersonTableCMD); - auto preparedStatement = conn->prepare(copyPersonTableCMD); + auto preparedStatement = conn->getClientContext()->prepareTest(copyPersonTableCMD); if (!preparedStatement->success) { ASSERT_TRUE(false) << preparedStatement->errMsg; } - auto mapper = PlanMapper(*getStorageManager(*database), getMemoryManager(*database), - getCatalog(*database), conn->getClientContext()); + auto mapper = PlanMapper(conn->getClientContext()); auto physicalPlan = mapper.mapLogicalPlanToPhysical(preparedStatement->logicalPlans[0].get(), preparedStatement->statementResult->getColumns()); @@ -91,20 +92,12 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { void validateTinysnbKnowsDateProperty() { std::multiset> expectedResult = { - Date::fromCString("1905-12-12", strlen("1905-12-12")), - Date::fromCString("1905-12-12", strlen("1905-12-12")), - Date::fromCString("1950-05-14", strlen("1950-05-14")), - Date::fromCString("1950-05-14", strlen("1950-05-14")), - Date::fromCString("1950-05-14", strlen("1950-05-14")), - Date::fromCString("1950-05-14", strlen("1950-05-14")), - Date::fromCString("2000-01-01", strlen("2000-01-01")), - Date::fromCString("2000-01-01", strlen("2000-01-01")), - Date::fromCString("2021-06-30", strlen("2021-06-30")), Date::fromCString("2021-06-30", strlen("2021-06-30")), Date::fromCString("2021-06-30", strlen("2021-06-30")), Date::fromCString("2021-06-30", strlen("2021-06-30")), Date::fromCString("2021-06-30", strlen("2021-06-30")), - Date::fromCString("2021-06-30", strlen("2021-06-30"))}; + Date::fromCString("1950-05-14", strlen("1950-05-14")), + Date::fromCString("1950-05-14", strlen("1950-05-14"))}; std::multiset> actualResult; auto queryResult = conn->query("match (:person)-[e:knows]->(:person) return e.date"); while (queryResult->hasNext()) { @@ -118,28 +111,27 @@ class TinySnbCopyCSVTransactionTest : public EmptyDBTest { auto dummyWriteTrx = transaction::Transaction::getDummyWriteTrx(); ASSERT_EQ(getStorageManager(*database)->getRelsStatistics()->getNextRelOffset( dummyWriteTrx.get(), tableID), - 14); + 6); } void validateDatabaseStateAfterCheckPointCopyRel(table_id_t knowsTableID) { validateTinysnbKnowsDateProperty(); auto relsStatistics = getStorageManager(*database)->getRelsStatistics(); auto dummyWriteTrx = transaction::Transaction::getDummyWriteTrx(); - ASSERT_EQ(relsStatistics->getNextRelOffset(dummyWriteTrx.get(), knowsTableID), 14); + ASSERT_EQ(relsStatistics->getNextRelOffset(dummyWriteTrx.get(), knowsTableID), 6); ASSERT_EQ(relsStatistics->getReadOnlyVersion()->tableStatisticPerTable.size(), 1); auto knowsRelStatistics = (RelTableStats*)relsStatistics->getReadOnlyVersion() ->tableStatisticPerTable.at(knowsTableID) .get(); - ASSERT_EQ(knowsRelStatistics->getNumTuples(), 14); + ASSERT_EQ(knowsRelStatistics->getNumTuples(), 6); } void copyRelCSVCommitAndRecoveryTest(TransactionTestType transactionTestType) { conn->query(createPersonTableCMD); conn->query(copyPersonTableCMD); conn->query(createKnowsTableCMD); - auto preparedStatement = conn->prepare(copyKnowsTableCMD); - auto mapper = PlanMapper(*getStorageManager(*database), getMemoryManager(*database), - getCatalog(*database), conn->getClientContext()); + auto preparedStatement = conn->getClientContext()->prepareTest(copyKnowsTableCMD); + auto mapper = PlanMapper(conn->getClientContext()); auto physicalPlan = mapper.mapLogicalPlanToPhysical(preparedStatement->logicalPlans[0].get(), preparedStatement->statementResult->getColumns()); diff --git a/test/ddl/e2e_ddl_test.cpp b/test/ddl/e2e_ddl_test.cpp index 1372b57bc3a..ce756460da6 100644 --- a/test/ddl/e2e_ddl_test.cpp +++ b/test/ddl/e2e_ddl_test.cpp @@ -1,8 +1,10 @@ #include "binder/bound_statement_result.h" +#include "catalog/catalog.h" #include "common/string_format.h" #include "graph_test/graph_test.h" #include "processor/plan_mapper.h" #include "processor/processor.h" +#include "storage/storage_manager.h" using namespace kuzu::catalog; using namespace kuzu::common; @@ -105,8 +107,8 @@ class TinySnbDDLTest : public DBTest { "Binder exception: Nodes a and b are not connected through rel e."); } - void dropTableCommitAndRecoveryTest( - std::string tableName, TransactionTestType transactionTestType) { + void dropTableCommitAndRecoveryTest(std::string tableName, + TransactionTestType transactionTestType) { auto tableID = catalog->getTableID(&DUMMY_READ_TRANSACTION, tableName); auto tableSchema = catalog->getTableCatalogEntry(&DUMMY_READ_TRANSACTION, tableID)->copy(); executeQueryWithoutCommit(stringFormat("DROP TABLE {}", tableName)); @@ -167,9 +169,8 @@ class TinySnbDDLTest : public DBTest { } void executeQueryWithoutCommit(std::string query) { - auto preparedStatement = conn->prepare(query); - auto mapper = PlanMapper(*getStorageManager(*database), getMemoryManager(*database), - getCatalog(*database), conn->getClientContext()); + auto preparedStatement = conn->getClientContext()->prepareTest(query); + auto mapper = PlanMapper(conn->getClientContext()); auto physicalPlan = mapper.mapLogicalPlanToPhysical(preparedStatement->logicalPlans[0].get(), preparedStatement->statementResult->getColumns()); @@ -177,8 +178,8 @@ class TinySnbDDLTest : public DBTest { getQueryProcessor(*database)->execute(physicalPlan.get(), executionContext.get()); } - void addPropertyToPersonTableWithoutDefaultValue( - std::string propertyType, TransactionTestType transactionTestType) { + void addPropertyToPersonTableWithoutDefaultValue(std::string propertyType, + TransactionTestType transactionTestType) { executeQueryWithoutCommit(stringFormat("ALTER TABLE person ADD random {}", propertyType)); if (transactionTestType == TransactionTestType::RECOVERY) { conn->query("COMMIT_SKIP_CHECKPOINT"); @@ -200,8 +201,8 @@ class TinySnbDDLTest : public DBTest { // The convertResultToString function will remove the single quote around the result // std::string, so we should also remove the single quote in the expected result. defaultVal.erase(remove(defaultVal.begin(), defaultVal.end(), '\''), defaultVal.end()); - std::vector expectedResult( - 8 /* numOfNodesInPesron */, expectedVal.empty() ? defaultVal : expectedVal); + std::vector expectedResult(8 /* numOfNodesInPesron */, + expectedVal.empty() ? defaultVal : expectedVal); if (transactionTestType == TransactionTestType::RECOVERY) { conn->query("COMMIT_SKIP_CHECKPOINT"); initWithoutLoadingGraph(); @@ -213,8 +214,8 @@ class TinySnbDDLTest : public DBTest { expectedResult); } - void addPropertyToStudyAtTableWithoutDefaultValue( - std::string propertyType, TransactionTestType transactionTestType) { + void addPropertyToStudyAtTableWithoutDefaultValue(std::string propertyType, + TransactionTestType transactionTestType) { executeQueryWithoutCommit(stringFormat("ALTER TABLE studyAt ADD random {}", propertyType)); if (transactionTestType == TransactionTestType::RECOVERY) { conn->query("COMMIT_SKIP_CHECKPOINT"); @@ -229,8 +230,8 @@ class TinySnbDDLTest : public DBTest { } } - void addPropertyToStudyAtTableWithDefaultValue( - std::string propertyType, std::string defaultVal, TransactionTestType transactionTestType) { + void addPropertyToStudyAtTableWithDefaultValue(std::string propertyType, std::string defaultVal, + TransactionTestType transactionTestType) { executeQueryWithoutCommit( stringFormat("ALTER TABLE studyAt ADD random {} DEFAULT {}", propertyType, defaultVal)); defaultVal.erase(remove(defaultVal.begin(), defaultVal.end(), '\''), defaultVal.end()); @@ -329,28 +330,28 @@ TEST_F(TinySnbDDLTest, DropRelTablePropertyRecovery) { } TEST_F(TinySnbDDLTest, AddInt64PropertyToPersonTableWithoutDefaultValueRecovery) { - addPropertyToPersonTableWithoutDefaultValue( - "INT64" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToPersonTableWithoutDefaultValue("INT64" /* propertyType */, + TransactionTestType::RECOVERY); } -TEST_F(TinySnbDDLTest, AddFixedListPropertyToPersonTableWithoutDefaultValueRecovery) { - addPropertyToPersonTableWithoutDefaultValue( - "DOUBLE[5]" /* propertyType */, TransactionTestType::RECOVERY); +TEST_F(TinySnbDDLTest, AddArrayPropertyToPersonTableWithoutDefaultValueRecovery) { + addPropertyToPersonTableWithoutDefaultValue("DOUBLE[5]" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddStringPropertyToPersonTableWithoutDefaultValueRecovery) { - addPropertyToPersonTableWithoutDefaultValue( - "STRING" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToPersonTableWithoutDefaultValue("STRING" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddListOfInt64PropertyToPersonTableWithoutDefaultValueRecovery) { - addPropertyToPersonTableWithoutDefaultValue( - "INT64[]" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToPersonTableWithoutDefaultValue("INT64[]" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddListOfStringPropertyToPersonTableWithoutDefaultValueRecovery) { - addPropertyToPersonTableWithoutDefaultValue( - "STRING[]" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToPersonTableWithoutDefaultValue("STRING[]" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddListOfStructPropertyToPersonTableWithoutDefaultValueRecovery) { @@ -359,8 +360,8 @@ TEST_F(TinySnbDDLTest, AddListOfStructPropertyToPersonTableWithoutDefaultValueRe } TEST_F(TinySnbDDLTest, AddMapPropertyToPersonTableWithoutDefaultValueRecovery) { - addPropertyToPersonTableWithoutDefaultValue( - "MAP(STRING, INT64)" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToPersonTableWithoutDefaultValue("MAP(STRING, INT64)" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddStructPropertyToPersonTableWithoutDefaultValueRecovery) { @@ -369,8 +370,8 @@ TEST_F(TinySnbDDLTest, AddStructPropertyToPersonTableWithoutDefaultValueRecovery } TEST_F(TinySnbDDLTest, AddInt64PropertyToPersonTableWithDefaultValueRecovery) { - addPropertyToPersonTableWithDefaultValue( - "INT64" /* propertyType */, "21" /* defaultVal */, TransactionTestType::RECOVERY); + addPropertyToPersonTableWithDefaultValue("INT64" /* propertyType */, "21" /* defaultVal */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddStringPropertyToPersonTableWithDefaultValueRecovery) { @@ -416,28 +417,28 @@ TEST_F(TinySnbDDLTest, AddStructPropertyToPersonTableWithDefaultValueRecovery) { } TEST_F(TinySnbDDLTest, AddInt64PropertyToStudyAtTableWithoutDefaultValueRecovery) { - addPropertyToStudyAtTableWithoutDefaultValue( - "INT64" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToStudyAtTableWithoutDefaultValue("INT64" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddStringPropertyToStudyAtTableWithoutDefaultValueRecovery) { - addPropertyToStudyAtTableWithoutDefaultValue( - "STRING" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToStudyAtTableWithoutDefaultValue("STRING" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddListOfInt64PropertyToStudyAtTableWithoutDefaultValueRecovery) { - addPropertyToStudyAtTableWithoutDefaultValue( - "INT64[]" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToStudyAtTableWithoutDefaultValue("INT64[]" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddListOfStringPropertyToStudyAtTableWithoutDefaultValueRecovery) { - addPropertyToStudyAtTableWithoutDefaultValue( - "STRING[]" /* propertyType */, TransactionTestType::RECOVERY); + addPropertyToStudyAtTableWithoutDefaultValue("STRING[]" /* propertyType */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddInt64PropertyToStudyAtTableWithDefaultValueRecovery) { - addPropertyToStudyAtTableWithDefaultValue( - "INT64" /* propertyType */, "42" /* defaultVal */, TransactionTestType::RECOVERY); + addPropertyToStudyAtTableWithDefaultValue("INT64" /* propertyType */, "42" /* defaultVal */, + TransactionTestType::RECOVERY); } TEST_F(TinySnbDDLTest, AddStringPropertyToStudyAtTableWithDefaultValueRecovery) { diff --git a/test/graph_test/base_graph_test.cpp b/test/graph_test/base_graph_test.cpp index e77b0b18903..0f8817fbd24 100644 --- a/test/graph_test/base_graph_test.cpp +++ b/test/graph_test/base_graph_test.cpp @@ -11,8 +11,8 @@ using namespace kuzu::main; namespace kuzu { namespace testing { -void BaseGraphTest::commitOrRollbackConnectionAndInitDBIfNecessary( - bool isCommit, TransactionTestType transactionTestType) { +void BaseGraphTest::commitOrRollbackConnectionAndInitDBIfNecessary(bool isCommit, + TransactionTestType transactionTestType) { commitOrRollbackConnection(isCommit, transactionTestType); if (transactionTestType == TransactionTestType::RECOVERY) { // This creates a new database/conn/readConn and should run the recovery algorithm. @@ -68,8 +68,8 @@ void TestHelper::executeScript(const std::string& cypherScript, Connection& conn auto result = conn.query(line); std::cout << "Executed query: " << line << std::endl; if (!result->isSuccess()) { - throw Exception(stringFormat( - "Failed to execute statement: {}.\nError: {}", line, result->getErrorMessage())); + throw Exception(stringFormat("Failed to execute statement: {}.\nError: {}", line, + result->getErrorMessage())); } } } @@ -110,15 +110,15 @@ void BaseGraphTest::initGraph() { TestHelper::executeScript(getInputDir() + TestHelper::COPY_FILE_NAME, *conn); } else { // choose a conn from connMap - TestHelper::executeScript( - getInputDir() + TestHelper::SCHEMA_FILE_NAME, *(connMap.begin()->second)); - TestHelper::executeScript( - getInputDir() + TestHelper::COPY_FILE_NAME, *(connMap.begin()->second)); + TestHelper::executeScript(getInputDir() + TestHelper::SCHEMA_FILE_NAME, + *(connMap.begin()->second)); + TestHelper::executeScript(getInputDir() + TestHelper::COPY_FILE_NAME, + *(connMap.begin()->second)); } } -void BaseGraphTest::commitOrRollbackConnection( - bool isCommit, TransactionTestType transactionTestType) const { +void BaseGraphTest::commitOrRollbackConnection(bool isCommit, + TransactionTestType transactionTestType) const { if (transactionTestType == TransactionTestType::NORMAL_EXECUTION) { if (isCommit) { conn->query("COMMIT"); diff --git a/test/graph_test/graph_test.cpp b/test/graph_test/graph_test.cpp index c2c26fbc415..9834615deb0 100644 --- a/test/graph_test/graph_test.cpp +++ b/test/graph_test/graph_test.cpp @@ -19,17 +19,13 @@ using namespace kuzu::transaction; namespace kuzu { namespace testing { -void PrivateGraphTest::validateQueryBestPlanJoinOrder( - std::string query, std::string expectedJoinOrder) { - auto catalog = getCatalog(*database); +void PrivateGraphTest::validateQueryBestPlanJoinOrder(std::string query, + std::string expectedJoinOrder) { auto statement = parser::Parser::parseQuery(query); ASSERT_EQ(statement.size(), 1); auto parsedQuery = (parser::RegularQuery*)statement[0].get(); - auto boundQuery = - Binder(*catalog, database->memoryManager.get(), database->storageManager.get(), - database->vfs.get(), conn->clientContext.get(), database->extensionOptions.get()) - .bind(*parsedQuery); - auto planner = Planner(catalog, getStorageManager(*database)); + auto boundQuery = Binder(conn->clientContext.get()).bind(*parsedQuery); + auto planner = Planner(conn->clientContext.get()); auto plan = planner.getBestPlan(*boundQuery); ASSERT_STREQ(LogicalPlanUtil::encodeJoin(*plan).c_str(), expectedJoinOrder.c_str()); } diff --git a/test/hammer.test b/test/hammer.test deleted file mode 100644 index bca248b8504..00000000000 --- a/test/hammer.test +++ /dev/null @@ -1,4415 +0,0 @@ --GROUP [hammer] --DATASET CSV empty --- - --CASE hammer --STATEMENT CREATE NODE TABLE Person(id SERIAL, prop1 INT64, prop2 STRING, PRIMARY KEY(id)); ----- ok --STATEMENT CREATE REL TABLE knows(FROM Person TO Person, prop1 INT64); ----- ok --STATEMENT CREATE (p:Person {prop1: 142215, prop2: 'Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 878242, prop2: 'GO4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 836516, prop2: '7R2MJD25G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 206382, prop2: 'X137NINSSS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 120923, prop2: 'TVB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 876432, prop2: 'YIKU910'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 38863, prop2: 'MZVHYJ0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 927513, prop2: '80QOC1HMG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 371524, prop2: 'V2J1HETGK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 550015, prop2: 'MPZWQC5SW7A'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 487871, prop2: 'EHVFGX86N5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 595954, prop2: 'B185J2K'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 122737, prop2: '5RK9HBF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 985147, prop2: 'TEGKHN5LIDU77P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 824973, prop2: 'EJCDDAYLXH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 565022, prop2: 'ZIHY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 583825, prop2: 'NC9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 685363, prop2: 'RH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 958294, prop2: 'YLENEN4NQ1A'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 284652, prop2: 'UQNYSKI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 210888, prop2: 'LGWV7OIMJ0O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 281745, prop2: 'NH4WXFWO7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 280189, prop2: 'FDPBGGH5I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 269537, prop2: 'BO5JAX62ZHEW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 734377, prop2: 'DAWIYOLU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 152454, prop2: 'WGF0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 848083, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 639375, prop2: '42WN66XP9C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 110955, prop2: 'N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 103714, prop2: 'A78TOD4HMSHPX3N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 180357, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 955977, prop2: 'N8NZGFAT3WC6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 561795, prop2: 'TJEPGIKWOB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 775568, prop2: 'Z6JA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 446328, prop2: 'ZN732JW8V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 357881, prop2: '2XDI1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 651829, prop2: 'TSFSRD9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 533241, prop2: 'JYIU65HS7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 526516, prop2: 'WF3T6TYE0S0G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 172117, prop2: '0CGK01OP7I3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 842075, prop2: '78Z6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 476616, prop2: '3R7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 198061, prop2: 'NWA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 578273, prop2: 'Z2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 502321, prop2: 'WVML0NE65859MT3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 869561, prop2: 'P74KOQS4DQ5E'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 313493, prop2: 'QI5CYSQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 774511, prop2: 'UTV79CVE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 272775, prop2: 'A0P8GWYI829K'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 903471, prop2: '8T1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 759878, prop2: 'R21SJGEJY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 321168, prop2: 'VG3IGJ8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 260765, prop2: 'CQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 734470, prop2: 'VC4IHNL2ECR02C6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 83448, prop2: 'OMYU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 432067, prop2: 'COZ8Q7GCOJNG0H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 726038, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 4987, prop2: 'UXBR1066RBUN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 682142, prop2: 'NWH9L0M9S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 193306, prop2: 'N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 576741, prop2: 'EQJ8PAMCHKFO37'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 319178, prop2: 'HTYJP1XGUC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 475596, prop2: 'LWB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 410752, prop2: '8RMZOWD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 497200, prop2: 'OADFC0K7OOS62FV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 729981, prop2: '36TNCVK1I3R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 263975, prop2: '4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 577758, prop2: 'C9NG9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 246488, prop2: 'HTZ1QS1AJ12WN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 521264, prop2: '24BI1SFKVJNV1K2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 400001, prop2: '1Y20'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 685249, prop2: 'O8U7PDMV8WSQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 977470, prop2: 'DAGYKA2074OVM6M'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 267925, prop2: 'JD3HLW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 814093, prop2: 'H8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 248280, prop2: 'UW8SYG1GFMTNQZU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 186303, prop2: '8N5P72QGNM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 202328, prop2: 'V7T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 267629, prop2: '3NKG5IBZN6C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 442319, prop2: 'WOBU124ROR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 918851, prop2: 'Z42RM4W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 489975, prop2: '62U2M0WBVEY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 765461, prop2: '65TAGXYIS2L3NH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 925161, prop2: 'C4E35H4JGKZE6Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 43575, prop2: 'UI9XTE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 699449, prop2: 'SW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 264126, prop2: 'WT34RHLW44'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 473492, prop2: 'IH2AJUMI7NU89'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 350244, prop2: 'RBCKIS1SJN0BHW5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 282497, prop2: 'O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 194572, prop2: '25O1CMU6KW3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 499424, prop2: '9ZJ5KPDV313F1T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 124516, prop2: '9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 480616, prop2: 'N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 886471, prop2: 'J'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 652691, prop2: 'WD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 652602, prop2: 'L8N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 203657, prop2: 'EW7HF91NJX5HD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 364764, prop2: '031DV0SG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 160943, prop2: 'X0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 423712, prop2: 'OTRCXTBAT85H7L0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 856546, prop2: 'E8M1UGJNSB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 72737, prop2: '39APMZWXQKR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 538681, prop2: 'GVWT9UTHBFBW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 104942, prop2: 'K0S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 118091, prop2: 'HCV6J0Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 472091, prop2: '779RUF27I8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 481565, prop2: '5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 919296, prop2: 'KKNFCXMEBG23ZY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 103019, prop2: 'HMNW2R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 20762, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 879748, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 828648, prop2: 'OY1HH6I1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 884177, prop2: 'A8W46I6P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 47315, prop2: 'AKE9AZ9WHP73R17'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 253408, prop2: '4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 302335, prop2: '2ETE8NY0EBVT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 150650, prop2: '7AANX6F2JXQDJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 530197, prop2: 'C8EK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 674541, prop2: 'MHM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 837944, prop2: '384'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 194173, prop2: '8BGI8SFJ7CEYV9I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 361779, prop2: 'MC0FATBIL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 203176, prop2: 'RH5VQM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 133891, prop2: '0P17N0TVK8WRTKP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 957099, prop2: 'DG9CRR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 103250, prop2: 'VU3L18HW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 750558, prop2: 'RCJJJ9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 414057, prop2: 'EGVD5L5ZA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 885326, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 364776, prop2: 'K4KYXRJ63502LQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 483675, prop2: 'N0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 122272, prop2: 'MKXTIOVD3NX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 15043, prop2: 'O7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 997850, prop2: 'FM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 985927, prop2: '8X3HL63JBUFLYH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 199424, prop2: 'EZ7XBN89AK90OZS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 955757, prop2: 'R0ALKQ56'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 364172, prop2: 'OMF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 930597, prop2: 'RRC8C4Y0MME4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 592133, prop2: 'QMC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 608173, prop2: '5UENR7GFVJ7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 516501, prop2: 'JF4HBC86'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 957693, prop2: '4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 497660, prop2: 'LNE4JNVCJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 394920, prop2: '0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 922644, prop2: 'VG2B7R0QVBZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 44759, prop2: 'Z42F32BTNW9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 685034, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 539925, prop2: 'JJKDKHDPJ9ID'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 502806, prop2: 'QZUKTYUT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 114969, prop2: 'YDJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 40658, prop2: 'UZB2XHWX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 390989, prop2: '27EZ2QZYQUIDYXV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 440884, prop2: 'MRIW9R9PKFXXWG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 734377, prop2: 'Z5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 630481, prop2: 'C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 191992, prop2: 'XKYHIL3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 820384, prop2: 'FULAR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 244510, prop2: 'D56Z4SF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 494734, prop2: 'TAQV3MLYJD047'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 629927, prop2: '3OXTLP40GR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 369165, prop2: 'GK43TN45WFLE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 235024, prop2: 'HTU2I171DURL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 880112, prop2: 'VRV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 844206, prop2: 'WNDKLU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 462068, prop2: 'N6U4PC7ARY2K5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 534866, prop2: '5O68667TI4V3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 903326, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 453947, prop2: 'VVL3UYYXJN2TM6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 271343, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 871109, prop2: 'I8Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 454952, prop2: '4D5B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 222941, prop2: 'CT3B18OGZMKI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 833976, prop2: 'XI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 135018, prop2: 'EVXBF4QE5A'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 782324, prop2: 'T6ZJ61AGYQN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 905482, prop2: '1EB2LXZ434YX0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 223428, prop2: 'I4I7142'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 594296, prop2: 'PZ8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 544426, prop2: 'T5FOKNCL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 125393, prop2: 'F'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 8255, prop2: '8Z3AXZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 37142, prop2: 'X99BSKTORMME'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 225633, prop2: 'HE087WORS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 34079, prop2: 'H3CC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 676606, prop2: 'H6W1G3BWBDH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 6388, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 962040, prop2: '2Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 198524, prop2: '6KF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 152006, prop2: 'IAW4PL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 292753, prop2: 'NICR8O53PC0773'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 662167, prop2: '8R4PXTB9QQDW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 572552, prop2: 'R5P9UFF2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 811113, prop2: 'RYE380ZFNFJF7F'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 327384, prop2: 'ONK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 405724, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 871561, prop2: '5LSZ2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 674045, prop2: '1W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 395645, prop2: 'QGCTLTPF4I4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 462174, prop2: 'XS8P433Q5KX1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 88425, prop2: 'ZTCR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 288861, prop2: 'ZM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 116402, prop2: 'VHTOLATS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 887562, prop2: '3I7TU23O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 224737, prop2: 'PZ7139GGK7A8V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 268841, prop2: 'USNYAC4H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 621933, prop2: '22X4D1Q1Z4VV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 520613, prop2: 'ESEVKUUK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 280407, prop2: 'HZIE6KE1HNY2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 844790, prop2: '4TLE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 83970, prop2: 'ZV1RY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 296349, prop2: 'H0S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 757312, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 853698, prop2: 'VTTMM403Q7JVJBN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 410925, prop2: 'J'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 310419, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 679786, prop2: 'RZVS3SOZAAF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 975262, prop2: '19M6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 289821, prop2: 'EEH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 662388, prop2: 'FWB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 436588, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 324746, prop2: '9YRP0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 699161, prop2: 'I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 735853, prop2: '1FBRLJ03ZY73'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 479085, prop2: 'T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 655291, prop2: 'ZSUKW33F2W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 835867, prop2: '4QQIF5NT86AJD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 986275, prop2: '3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 294049, prop2: 'YPMT6G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 413538, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 177809, prop2: '6DDN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 738289, prop2: '9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 10660, prop2: 'K8ZVWEU84IZF4PM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 427506, prop2: 'GNYE87'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 762513, prop2: 'AD5K204TJPQNL6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 260983, prop2: 'ZMDQ44'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 454747, prop2: 'GE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 232801, prop2: '8OYH4B9JXY40VW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 786186, prop2: 'S5B7HLFC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 27236, prop2: 'DVPMJ9YN1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 171890, prop2: 'OSX2Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 472746, prop2: '9OLJ6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 391483, prop2: 'MK0P1WX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 585953, prop2: '8LYB9R0MN53S7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 329419, prop2: '73YVFHQTXH5HP2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 660510, prop2: '8R6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 562727, prop2: 'EXXIZT79'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 990153, prop2: 'ZLW8PXB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 485008, prop2: '7S2SAY6R8L2ADLB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 717787, prop2: '6K6KZS1GTMTBJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 914875, prop2: 'B6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 760785, prop2: '0B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 285781, prop2: 'BJGN5IAH6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 910763, prop2: '25Z8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 747230, prop2: 'K3KCN87U4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 954294, prop2: '3G7KIU4ZSELC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 709840, prop2: 'WJHE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 739379, prop2: '6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 321387, prop2: 'DWBLCZP0V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 126667, prop2: 'Z81NLTM36D'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 402383, prop2: 'IMLYNJNRWK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 265875, prop2: 'K2CJXVP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 421157, prop2: 'FEXY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 915608, prop2: 'HSO8T88'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 95350, prop2: 'I99MGI9B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 523169, prop2: 'G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 216252, prop2: 'ZRGOTFGJZ30'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 350858, prop2: 'IFTBFU6XZ3SZE5Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 716103, prop2: 'D2RHVZ6CGCGR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 330884, prop2: '4VENCV9ASBGBKRF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 363796, prop2: 'BZ5VGH3L'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 222647, prop2: 'ISIYYM8S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 241754, prop2: '8PW9OL67KWJK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 946564, prop2: 'AJ4FSMRBO1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 613257, prop2: 'EH1PD7VY6MY9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 931154, prop2: '60O57'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 656112, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 281344, prop2: 'SK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 288437, prop2: 'ATJ1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 949633, prop2: 'L0G4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 533941, prop2: 'N6VP2MSI7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 688596, prop2: 'UD28YW7HM2FG2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 636589, prop2: '2AZ5E1SP1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 843812, prop2: 'W6HETKVO4Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 641012, prop2: 'FFNFE8G2E'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 425626, prop2: 'K1HHKRW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 383051, prop2: 'Q70Z2OK1HK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 85241, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 653641, prop2: '050PD4867'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 880159, prop2: '6YNDB4ZPX3UGX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 163818, prop2: 'YMLM0T7AD15Y6R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 560946, prop2: 'HPVZT23KBN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 323105, prop2: 'MIJYZGXSBDQEXOY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 922551, prop2: 'TQF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 637013, prop2: 'I9F5IXS1WX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 537762, prop2: 'QBUV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 709409, prop2: 'FSMSLA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 219421, prop2: 'GKI0TZ9HL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 575534, prop2: 'I8A3I8MBJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 495790, prop2: 'AV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 164280, prop2: 'Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 857553, prop2: 'GRAY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 415602, prop2: '56S3X6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 533701, prop2: '9SH7M'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 478174, prop2: 'ZR9W8M3K072IM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 560184, prop2: 'F83RTG6W67Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 321642, prop2: '0LUB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 987544, prop2: 'R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 411604, prop2: 'YNIQ8G5YQUEJ2YT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 213349, prop2: 'V9WOPK7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 213199, prop2: 'BSMUAGT304ZPIEV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 905451, prop2: 'AECJU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 43274, prop2: 'YX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 153063, prop2: '8GTC5VGPL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 606314, prop2: '41LNY2VHY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 85485, prop2: '0I5Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 70561, prop2: 'DWHOL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 713046, prop2: 'YQCNAP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 224919, prop2: '5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 701011, prop2: 'FQ2VVR9RYW63Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 792846, prop2: '7663'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 118194, prop2: 'U418GML21BGEEHB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 930111, prop2: 'K2SU82PKS8WO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 199833, prop2: '3A2J9631SVEK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 94525, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 644504, prop2: '2X526TX7P8ZT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 610924, prop2: 'P851BZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 105592, prop2: '72DWX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 118673, prop2: 'MYEBIHF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 572728, prop2: 'FD6JV5567SC5KF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 832154, prop2: 'B3N1RE74KJ3KJ8T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 783792, prop2: 'I8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 148611, prop2: 'S0RISRHI2J48'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 66527, prop2: 'QFQDG74FX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 522321, prop2: 'OSVT8KROBU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 66936, prop2: 'WL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 497847, prop2: 'W8JESP55'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 845447, prop2: '15'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 781343, prop2: 'ZUPJZT8R2B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 343180, prop2: '7T8ZRKK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 4929, prop2: 'I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 132902, prop2: 'WW5BQU9I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 488509, prop2: 'NWCEPS9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 64694, prop2: 'WZLMTWZF6VN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 449132, prop2: '2AA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 575889, prop2: '1EPB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 45215, prop2: '35AGD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 970030, prop2: 'IZZAOMTYQYRB7C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 453223, prop2: 'JO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 821793, prop2: '749'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 950571, prop2: 'PT872H5XUCND'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 720321, prop2: '7V32124OHYV3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 300987, prop2: 'K20OEM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 646710, prop2: '8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 253539, prop2: '1462BK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 589840, prop2: 'P2JH87'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 954218, prop2: 'EONNEYOL5M'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 571588, prop2: 'I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 601747, prop2: '8XWJQCXDF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 946023, prop2: 'KSYFF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 969232, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 64081, prop2: 'S9EZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 13235, prop2: 'IRIKZDTB4NA6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 236342, prop2: '76OK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 634885, prop2: '5U2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 754049, prop2: 'IDALDMDWD5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 164282, prop2: 'J1C8PAHHMG560R6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 807608, prop2: 'GHY9TBY5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 68780, prop2: '5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 383042, prop2: 'YJ39H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 393704, prop2: 'WC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 86061, prop2: 'PVRSRRY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 226238, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 237693, prop2: 'B44Z2N5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 90989, prop2: 'SVA8TW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 529059, prop2: 'HWZ0EW3S8LE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 818095, prop2: 'N0IABNDE8E'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 397368, prop2: 'O2WSIO2C13NAKEV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 553393, prop2: 'T9S495'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 625516, prop2: '1Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 428584, prop2: 'T8NWM5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 416608, prop2: 'VAUTHZ8L643PILR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 193979, prop2: 'K0C26'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 494700, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 852823, prop2: 'XLX6GZYV3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 756538, prop2: 'RF09STO9GXAH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 375593, prop2: 'FXBVL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 96835, prop2: 'YQNQ6CR7PZ8PCV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 282885, prop2: 'CZ5SJTJJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 543548, prop2: 'AQXQS0X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 181154, prop2: '1G23VRGK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 581131, prop2: '5MORMGN4MDBYHDX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 619480, prop2: 'NX0603XXVG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 68792, prop2: 'WH0ML0CPF30W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 890917, prop2: 'ZRH97846THGJYA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 838728, prop2: '5OPIFB4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 222606, prop2: '3LFLEZSP6V1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 982116, prop2: '3EEQ8PHR94'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 652161, prop2: 'I2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 841569, prop2: 'HDEH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 469186, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 837495, prop2: '3MTEN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 990988, prop2: 'UJ9E76I4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 563304, prop2: 'R5RD9I0TGN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 709357, prop2: 'ZH7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 725595, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 461587, prop2: '8XE86H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 910053, prop2: 'VFOGTA8G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 640945, prop2: '15WRM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 11896, prop2: 'ID0HO2P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 657625, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 369481, prop2: '9J5I68P7C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 222590, prop2: 'ZJPE6BYJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 406345, prop2: 'SIDMHLYHV1CYOM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 136029, prop2: 'GT1W95QRQUL0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 825143, prop2: 'F11TGV03WKLVP9P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 61786, prop2: 'QBWC1I4CRT86'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 121359, prop2: 'Y1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 367725, prop2: 'R9O2LMU07X5VRA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 799769, prop2: 'DGP5JR2Z9G7YBSR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 424369, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 585278, prop2: '97SZV220E2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 621193, prop2: 'UF3OXRB255G3KN6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 192294, prop2: 'F11C5QQNYL9GH5T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 830061, prop2: 'SC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 134664, prop2: 'IWIYF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 563700, prop2: '6AZMUI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 225744, prop2: 'KIRN82R9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 605610, prop2: '7LXYASFTZ87'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 660732, prop2: 'J5XHCN8Y0O2SN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 712624, prop2: 'BWCUWHPA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 76271, prop2: 'KRL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 488397, prop2: 'H6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 894742, prop2: '9ZXT131U'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 219610, prop2: '3F6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 378634, prop2: '2DF96PZWKXKH3YW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 912271, prop2: 'Q9HFT6KID13'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 642330, prop2: '7B7Y13K1QLFYF4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 883818, prop2: 'IVKVZ2WN2E4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 835557, prop2: '9ZUWLR0EWR8JD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 442343, prop2: 'PB4MBY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 548113, prop2: 'P6B6X5F4E5BA3C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 778766, prop2: '6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 289452, prop2: 'AV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 144038, prop2: 'WLHVZBR9KZEL7BJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 653104, prop2: 'XXP8NI5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 404822, prop2: '133CV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 828039, prop2: '8N1886SD24USMZQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 403379, prop2: 'JNOE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 717466, prop2: 'B4RAZMNT8Z5S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 449924, prop2: '1ST6HF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 489710, prop2: 'XPJX33ETX42'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 98965, prop2: 'V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 115763, prop2: 'W2Y3MNB1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 503334, prop2: '6GE0SL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 597859, prop2: '3Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 225392, prop2: 'OOLH1OPJSPK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 563599, prop2: 'YUBK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 900299, prop2: '25UGKX5R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 424854, prop2: '6F1DAMQ9SZYU0W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 638528, prop2: 'NL6LIJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 632686, prop2: 'FC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 68530, prop2: '12N4SP7IW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 785331, prop2: 'JPN0PY1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 68059, prop2: 'B7HLXLW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 535239, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 406003, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 641669, prop2: '3O32B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 35085, prop2: 'H5WKMOILX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 47273, prop2: 'V7B7N3TO12C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 516061, prop2: 'PLH4C8L0SB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 128641, prop2: '6URM3JRKZC8Y3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 869031, prop2: '2PIS8WG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 700621, prop2: '4HHVS2B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 324756, prop2: 'PTXUW7M3UW7Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 975496, prop2: 'DEI52'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 994319, prop2: '5VO05WF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 981110, prop2: 'N1OA7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 20975, prop2: 'NFSWQ0W2SH5PNI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 931809, prop2: 'TH34C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 236777, prop2: 'Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 315448, prop2: '5SP6A1GAU40OV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 436839, prop2: 'RILQTTXCWP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 628785, prop2: 'RWAX8E15MF2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 123556, prop2: 'ZFZRJCSIGCWV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 753004, prop2: 'CVS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 68915, prop2: '7NZW1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 555336, prop2: 'YDW2RMNL89B4AVJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 15184, prop2: '82KPS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 217076, prop2: 'AVAV6KTYRF4DV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 990918, prop2: '0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 563927, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 714762, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 852314, prop2: 'A7IOTWZF22X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 991143, prop2: 'X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 292869, prop2: 'ZW5O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 150418, prop2: 'KFVOKYL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 229997, prop2: 'YFPR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 133597, prop2: 'T24OVAXVIH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 53404, prop2: 'S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 418334, prop2: 'FZ7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 226074, prop2: '4PPFZJ0XESA9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 727958, prop2: '7DHNIC4YP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 602431, prop2: '2AEPENBXJU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 699135, prop2: 'B0G4XEOOIX0XD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 895374, prop2: '3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 366928, prop2: 'BEW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 42270, prop2: 'L84TJ4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 337799, prop2: 'KF2Z2TMP4C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 844128, prop2: '1A'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 863723, prop2: 'SF9R0X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 511907, prop2: 'SSU4B4QRI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 72152, prop2: 'JI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 57401, prop2: '9U50RC2BH02Q0HF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 514742, prop2: 'CYCSB4E9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 497558, prop2: 'OGCG12102XH4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 274782, prop2: 'XZ3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 722327, prop2: 'WAZU63KHG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 344167, prop2: 'H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 902029, prop2: 'Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 986051, prop2: 'MGF1GC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 815225, prop2: 'SONKJO6I743S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 494448, prop2: 'OLY8ZVS5BKO1Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 496098, prop2: 'NMI5ZCBE9ING5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 842833, prop2: 'T4SLZR4FDWN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 101869, prop2: '8U7KM3H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 653393, prop2: 'LRIUFSPLIO8WQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 477532, prop2: '0IZJVS05'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 663846, prop2: '2EC6OUV8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 922713, prop2: 'ZDSL9VXS34'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 631594, prop2: 'DS3Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 937700, prop2: '84'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 620805, prop2: 'N5PB2U3C9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 463913, prop2: 'N9JBO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 128550, prop2: 'FMPYX3S8KV1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 998761, prop2: 'PCG7NBEAGP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 857187, prop2: '1VS7T8CNRCS7E6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 660784, prop2: 'EY5B8115'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 820509, prop2: 'BV2G7L07'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 619458, prop2: '1Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 677393, prop2: 'Y0SPGCXE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 566910, prop2: '2PJ7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 933745, prop2: '6WV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 553248, prop2: 'Z1S7RRCZLU2PJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 833433, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 619663, prop2: 'I7RO7TBG48BC4P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 610750, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 909571, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 124612, prop2: 'S7TM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 832897, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 582155, prop2: 'QVUK4X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 220115, prop2: 'INBKQYFQHBCB6T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 485790, prop2: 'HF2E6VMA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 208123, prop2: 'N4Q3Y9PME'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 975960, prop2: 'EKDPDG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 504318, prop2: 'UQY0ZHJ5PR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 484098, prop2: 'FT0L'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 361180, prop2: 'P480OEE4RPHZ3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 332664, prop2: 'CFMNQ3TBJE8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 655321, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 252209, prop2: 'JRWXXPN4661IL0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 880708, prop2: '01T4X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 137845, prop2: 'VIGJB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 689023, prop2: 'JQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 575955, prop2: 'ML9RT2M69'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 401573, prop2: '825EZML676'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 880218, prop2: 'IWX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 204365, prop2: 'DS065PZR4T13'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 22674, prop2: 'CYIR6IK6XQ89AYV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 529449, prop2: '7IBMU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 61851, prop2: '7CK4Z0S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 901263, prop2: 'P1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 269222, prop2: 'QXVM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 28913, prop2: 'TKWBLZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 308949, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 805751, prop2: 'ZUX3UB3GAHV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 662326, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 60534, prop2: 'KWC7BCC3CY0MX2X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 663639, prop2: 'M7SGYXM9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 836997, prop2: '9J5RQBK6CIM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 55787, prop2: 'JJ9E4YK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 12736, prop2: 'WH9POV76K'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 280894, prop2: '70'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 53401, prop2: '1YYZG796'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 725580, prop2: 'CAGKGMTLL4ETTRL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 119203, prop2: 'DW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 959312, prop2: '30GS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 612281, prop2: '2G169WGPZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 765461, prop2: 'ECT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 527992, prop2: 'Z5JVXK9FNS1KJFP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 647029, prop2: 'AKO8XFUJUPP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 971718, prop2: 'L'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 451068, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 334532, prop2: 'ZC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 463682, prop2: 'ICKZ2GT7KL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 163354, prop2: '5ESUHXG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 716176, prop2: '1Y0999NI1T0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 340071, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 122409, prop2: '3MV7NVBJ89M4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 397932, prop2: '7VDFR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 77409, prop2: 'UVYCPTLY9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 963479, prop2: 'NW915DJJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 982421, prop2: '9JDZBJ1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 230894, prop2: '1S1NQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 527145, prop2: '22'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 649454, prop2: 'ST58KRS2WN99BBK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 658253, prop2: 'FHINK5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 608344, prop2: '63U1CTZ6OPZ6HKK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 165208, prop2: '7YWQVQA4V2RA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 211633, prop2: 'OXMQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 521526, prop2: '0GGKBW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 908564, prop2: '493'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 320421, prop2: 'HGP97BUI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 580404, prop2: 'K7PFY1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 722606, prop2: 'K0LL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 993752, prop2: 'LAQOTOS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 814532, prop2: 'DBM1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 406833, prop2: '8EQ1CGMX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 307266, prop2: 'O4HV7YJOKNNFYP3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 314958, prop2: 'KCZYBLQKMSO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 770077, prop2: 'S0U1NBE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 139021, prop2: '5IJ7SOR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 821201, prop2: '7CWKCSZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 423647, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 457356, prop2: 'SBYNTJ0UVFXNV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 180780, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 485065, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 7308, prop2: 'MYX5RJAEPDYQZNG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 585439, prop2: '66G53'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 17910, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 689917, prop2: 'GJFQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 975195, prop2: 'NS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 912502, prop2: 'TX97CFNMYE7B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 861767, prop2: 'A7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 367691, prop2: 'OE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 471435, prop2: 'A1JFTND37GL7IK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 65853, prop2: 'GM56G0192WGN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 389375, prop2: 'LP7L'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 940337, prop2: 'Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 971565, prop2: 'H7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 424219, prop2: 'VQG5ZP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 897483, prop2: 'WYJZFZ688HZ7QD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 399273, prop2: 'T8OMDAS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 478465, prop2: 'HRJA2GPX34'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 344932, prop2: 'QM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 81415, prop2: 'X4FGRVTF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 35230, prop2: 'U038'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 940752, prop2: 'BVFEBR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 172534, prop2: 'SR0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 801151, prop2: 'KERHFWKZFQWAAR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 834460, prop2: '60LFTI4Z0LNLY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 762961, prop2: 'HTFM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 776237, prop2: '6X9Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 742897, prop2: '2FDV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 2174, prop2: 'W6C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 40288, prop2: '3QSTXEP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 30684, prop2: 'EQT4DCM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 270774, prop2: 'GP5IWG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 558542, prop2: 'LANC6U58N2HVSIN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 98623, prop2: 'Y120ZAP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 491834, prop2: 'UBV52THSIP05OC9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 825245, prop2: 'BLJIHD5MZ5Y2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 457272, prop2: '4O2WT8LQOSUGNY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 31823, prop2: '1U1FX7K4N8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 988155, prop2: 'P3CRGKRK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 818499, prop2: 'PTFYH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 619420, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 743588, prop2: '3CSE0HN41B5D'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 335215, prop2: 'B3HRGRFXX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 787690, prop2: 'ZP1VTQ128MQ8A'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 787275, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 114886, prop2: 'X7IQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 394847, prop2: 'E89D84I2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 657583, prop2: 'WA2MH4OTH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 259098, prop2: '5L793QHG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 188432, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 381417, prop2: 'XDI1TKBEU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 423183, prop2: 'PC5PB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 105617, prop2: 'O1U5BYAFAV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 383693, prop2: '02FRWM6P4MZT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 701756, prop2: 'I1Y5KU6KIO7YF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 66313, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 506104, prop2: 'YRWTBOOPZUTO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 183315, prop2: '3AMSRMY7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 810041, prop2: 'LG3XT9Z42DPFV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 509411, prop2: 'I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 206801, prop2: 'Q5TVG48DM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 516108, prop2: 'TYRYS5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 340200, prop2: 'QG40WYKOHV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 757478, prop2: '0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 997613, prop2: '24'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 305381, prop2: 'M0V2BG5Z8O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 516977, prop2: '5KODUN64LG23'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 477132, prop2: 'SASYKXPAT3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 778825, prop2: 'KEECSWCXQOZY97'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 475913, prop2: '9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 60440, prop2: 'UCTOT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 538176, prop2: 'GZMHPCM511D'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 731985, prop2: 'Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 83616, prop2: 'SDRMJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 441868, prop2: 'S2EZIQDC9YJ88Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 783981, prop2: 'T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 963209, prop2: '5U6UTNIT4JVKECN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 382539, prop2: 'AP3ZTXR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 421761, prop2: '69OQP3NPB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 562314, prop2: 'MLI9UBE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 871817, prop2: 'SA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 538969, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 883489, prop2: '1JPZYJJBUWNBE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 799813, prop2: 'NJ6REVV7FXCWOK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 358179, prop2: '0TUJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 494492, prop2: 'M'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 123951, prop2: '7XGSN9PDQQQCV1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 376909, prop2: '53996RZBN0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 203367, prop2: 'YNAFB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 563140, prop2: 'WZFNJJDSIMOL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 460495, prop2: 'PEVIH0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 480257, prop2: 'LR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 351826, prop2: 'CQZEHWJXR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 502891, prop2: 'BNO8NE9M9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 368942, prop2: 'VHR7IQ3OM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 792731, prop2: '3V1V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 597183, prop2: 'WEYRG35FJVKSRO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 982499, prop2: 'RKJK2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 252729, prop2: 'CG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 172742, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 318335, prop2: '770VQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 707951, prop2: 'PJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 84909, prop2: '0YR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 826711, prop2: 'BU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 918444, prop2: 'O63QJ1042YOR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 519158, prop2: 'UFVTJ6X1YB4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 587717, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 69086, prop2: 'ZD0SAYZTX3KF82'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 258411, prop2: '4V07M2B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 202523, prop2: 'RHTX2DYN35P18'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 593572, prop2: 'P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 81462, prop2: 'M9ORT50BZCHZEOE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 640022, prop2: '02E0EVRN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 999673, prop2: 'EOV9CEDYTL8TX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 398833, prop2: 'JFCOCIMKW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 213771, prop2: 'FFYNXG3HTZO0S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 275074, prop2: 'K70WBHQ4UQJ8SV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 665203, prop2: 'A47EUVRXLY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 554943, prop2: 'NMI9GGKK0E'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 186041, prop2: 'TO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 451983, prop2: '01OVWIN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 657035, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 381292, prop2: 'K7W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 49671, prop2: 'QFSNCLRCL04LR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 886106, prop2: '7GII677G3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 641157, prop2: 'G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 996771, prop2: 'OLSWHSDL19QT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 69267, prop2: 'L4Z8T64AT84V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 933245, prop2: 'G855ASOEI4G00X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 376822, prop2: 'L8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 711668, prop2: '5H3OE4B6B2TILX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 611004, prop2: 'JC64YI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 746144, prop2: 'G4UHD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 288194, prop2: 'KMRVJC2S0DS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 220689, prop2: 'W63'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 420641, prop2: 'K7C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 86384, prop2: 'CL0SZFB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 92112, prop2: 'F1BTQ5Q5EP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 601052, prop2: 'NSCXOF9DTH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 297671, prop2: 'R6KOXN2QH5RV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 306986, prop2: 'UKRCTXT431D22MK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 118651, prop2: 'AZ9QS18BIW6E1SZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 387713, prop2: '3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 698874, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 596451, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 954553, prop2: '37WG2GFM8L8FHH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 846094, prop2: 'C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 40265, prop2: '5B05UFXMG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 500960, prop2: '41Y2ZTOCWXPD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 777913, prop2: '9AHJUTDVR0L6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 340617, prop2: '1CLE8V88'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 424418, prop2: 'GEVJFCPBVD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 980271, prop2: 'F9MWWQPKV63'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 26548, prop2: 'XS9E'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 128345, prop2: 'AGAA4T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 479646, prop2: 'BWX5F9I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 712445, prop2: 'YS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 142387, prop2: 'V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 13253, prop2: 'FIJ7PCOULO1AN0J'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 943609, prop2: '19WGIAQ0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 535048, prop2: 'B0N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 86106, prop2: '4DLQGYR6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 142878, prop2: '0BOR4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 516507, prop2: 'K3XGN2JSZRO9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 598999, prop2: 'BDBPGQ1U7Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 224533, prop2: 'RBGRZW5EEH9FDP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 800314, prop2: '7DX8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 349555, prop2: 'G85UM9PA2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 878647, prop2: '1F09F74A332W'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 244396, prop2: '8429C3T3U4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 65403, prop2: 'CMM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 548098, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 303757, prop2: 'CU21BVEUQQFB1O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 921695, prop2: 'SA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 563745, prop2: '8HUO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 552974, prop2: 'IL11BB3T7V6IUNH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 2186, prop2: 'OTPWGZTWIMBN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 51293, prop2: 'AACC1ZBLM2L19F'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 700205, prop2: 'T0LRDX9S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 511169, prop2: '5F99T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 529986, prop2: '1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 654160, prop2: '9DRVVZE906'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 931149, prop2: '78P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 309101, prop2: '51'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 555070, prop2: 'U1HFT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 600385, prop2: 'QX6U31M1QMYPUPA'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 701572, prop2: 'UX30OLTU1659'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 838526, prop2: 'GSNTP8M2AJ85R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 129752, prop2: '0N1S1DGB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 621945, prop2: 'NQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 740537, prop2: '44AZ9NSFZ9TPPK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 736123, prop2: 'TTSVN7Z1ISXFH0'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 357503, prop2: '02HT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 424125, prop2: 'BHO9NBW9TWP5YXD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 244340, prop2: '97VKPEO2FRFV'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 226752, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 134643, prop2: 'D'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 783729, prop2: 'SGUF4LX1QLMWI0V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 896228, prop2: 'SJ6XEQJJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 537378, prop2: '37QQU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 737328, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 178385, prop2: 'OVEJISHGIS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 225648, prop2: 'Z44N4C37WIM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 969182, prop2: '35U716IRE3ZI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 57539, prop2: 'RUM9CZ8C9T'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 362577, prop2: '8AL9O6V9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 850019, prop2: 'U4ISQ2M'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 366493, prop2: 'GJTG1090'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 664823, prop2: '27QARXGXWD7U'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 816428, prop2: 'D3ZLWVYU2M'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 791917, prop2: 'KAWX07'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 871307, prop2: 'O93B37PUR1W6V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 19798, prop2: 'E57DS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 993995, prop2: 'H06X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 108359, prop2: 'MCYVTOO27IXHI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 750748, prop2: '11N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 848806, prop2: '9KBWJF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 656421, prop2: '2PUJ8E1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 605980, prop2: '3HJNFYX69TB7T92'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 455177, prop2: 'OFJ6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 569235, prop2: '4VXI43OWKQI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 986151, prop2: '9ME'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 154108, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 512450, prop2: '3P4FQMR4EAZT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 209608, prop2: 'FD3D1HDCO5Y'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 960608, prop2: '6WDRM82HWPALMHT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 129314, prop2: 'EWGY5114QT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 500752, prop2: 'PG90R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 24402, prop2: 'AXWARMMRP2K399'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 702032, prop2: 'K13IC25'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 914596, prop2: '4N81T98Q93Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 975164, prop2: 'E54Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 854602, prop2: '5GWIJXQ14K09J'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 523133, prop2: 'WAYR5E9'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 926343, prop2: 'MJQUO4PLZIYNJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 890503, prop2: '7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 995293, prop2: 'QT87C106F'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 785377, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 756958, prop2: '5A'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 684842, prop2: 'H70W6O5JCX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 426304, prop2: 'Y7ZW5K'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 780935, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 508374, prop2: 'VTEB8Q18WH7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 996890, prop2: 'W91T3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 8478, prop2: 'M5B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 609868, prop2: 'ZN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 965508, prop2: 'XBG3BA9K0UR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 671190, prop2: 'AOF7ISB86H'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 386538, prop2: 'TC5W5WRB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 116460, prop2: 'X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 323899, prop2: 'X32'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 620732, prop2: 'JNY4JDOZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 562987, prop2: '1OVOY7AQEAYZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 191373, prop2: 'ME'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 747843, prop2: 'TVO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 501433, prop2: '5D9H97ZAOB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 88673, prop2: 'JFCBF3A4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 843877, prop2: 'GS7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 642427, prop2: '9LPS2P6N'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 428839, prop2: 'YMT2WYIJ24'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 497354, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 456975, prop2: 'O6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 783910, prop2: 'I'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 465047, prop2: 'S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 380378, prop2: 'A5YRTK8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 101821, prop2: 'E55WLB9DI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 310362, prop2: 'CAGO0U6X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 301984, prop2: '45JNC9OS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 940856, prop2: 'MG3AQP5IVN'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 521565, prop2: '21H2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 404063, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 631401, prop2: 'YBW366'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 126126, prop2: '43'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 99716, prop2: '3YGUAG3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 422743, prop2: '34IHAC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 601542, prop2: 'PKBXCR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 360555, prop2: '0ITJBWCPJQS6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 898384, prop2: 'AQ9RB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 267187, prop2: '7ODNS'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 528232, prop2: 'ZXVUIN0UCQ8NEV7'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 826422, prop2: 'Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 972155, prop2: '5CGRS1FWDSCJ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 840127, prop2: 'MN7JX'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 846332, prop2: 'QSIAE8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 881706, prop2: 'B3881X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 427532, prop2: 'GB7Q2V60'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 784307, prop2: '5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 372206, prop2: 'D'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 339800, prop2: 'S6JK3EF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 363202, prop2: 'U'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 267686, prop2: 'FYF88E4U0B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 201851, prop2: 'JE7XOI29FQM09L'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 480833, prop2: 'N83DEQVTIKZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 756133, prop2: 'JLO1Q7LGE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 649633, prop2: 'DKTNO1VX8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 655840, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 656130, prop2: 'NAGHE9JAOMDC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 644337, prop2: 'W8DD5BUHVIOFKP5'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 831648, prop2: 'UW'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 519354, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 616041, prop2: 'J'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 857213, prop2: 'X'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 572213, prop2: 'C8C9OAPYKTG5W0O'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 778226, prop2: 'Q2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 462618, prop2: '7RDWAPXYCQYYCPB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 735572, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 218169, prop2: 'P14JQLDK'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 62947, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 239560, prop2: 'MQMK9O9CVCT70BI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 65970, prop2: 'V02ZC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 356524, prop2: '1VJKUYDZNSM6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 971643, prop2: 'FPSE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 507539, prop2: '8V3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 179675, prop2: '0RK2GBPR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 718372, prop2: 'IAERU8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 758098, prop2: 'TCO7QJG'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 604562, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 982789, prop2: 'QW1NCJXVI9C4R7U'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 207852, prop2: 'LQD1'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 878586, prop2: 'HG4Z3YVTT0C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 350952, prop2: 'OOU4AXKG556'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 73189, prop2: 'U'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 929891, prop2: '59CW2ZB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 963585, prop2: 'I7T6RBX6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 243195, prop2: 'G'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 591486, prop2: 'XV9D165HP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 203722, prop2: '02'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 226465, prop2: '3C6'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 656275, prop2: 'LKMXV9O8K16S'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 785509, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 613976, prop2: '2B'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 972995, prop2: '3R7GN0QJRC'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 982973, prop2: 'C'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 6846, prop2: 'XI07C4FBY5JZ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 219163, prop2: 'VCLB'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 410246, prop2: '5GL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 667818, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 181234, prop2: '4JD27PRH7TAS4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 226227, prop2: 'G3MRK548P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 578961, prop2: 'V4E8'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 730591, prop2: 'MFBJGE1EQA4'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 530830, prop2: '287'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 573394, prop2: 'XVLQR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 696688, prop2: 'GSNC8NECI'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 399414, prop2: 'B2OXLY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 496931, prop2: 'X4GWEK2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 85364, prop2: 'CVTRC9KE3DO5R'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 133669, prop2: 'W5SC58VFVJY'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 760240, prop2: '9ESG02FEMMVA9Q'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 781824, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 700768, prop2: 'TL'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 884081, prop2: '2Z8MXJRFF2GRSQ'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 992748, prop2: 'I8VVND4BR'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 941454, prop2: '1IHFOVBVE'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 323230, prop2: '6N2'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 569611, prop2: 'NMQTDO'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 333298, prop2: 'T1MQEIRH'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 890940, prop2: 'RYIHT385J'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 244687, prop2: '7B6LAD'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 175180, prop2: '07P'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 523195, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 214723, prop2: 'A9KVESQ587U'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 891945, prop2: 'Y3L307KPRDJ4WR3'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 550035, prop2: 'L7X67G4QY4V'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 424124, prop2: '1OF523OWP'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 104646, prop2: ''}); ----- ok --STATEMENT CREATE (p:Person {prop1: 765752, prop2: 'PSU21N9YV5KT'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 649873, prop2: 'I1PEA8K'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 959449, prop2: 'ZAUL7LERRJU'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 752360, prop2: 'WJF'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 661157, prop2: 'FAUWJ055ZSM'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 708876, prop2: 'M4UGSLZLSQ257Z'}); ----- ok --STATEMENT CREATE (p:Person {prop1: 375732, prop2: '84'}); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=221 AND p2.id=684 CREATE (p1)-[e:knows {prop1: 187438}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=12 AND p2.id=411 CREATE (p1)-[e:knows {prop1: 347757}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=314 AND p2.id=737 CREATE (p1)-[e:knows {prop1: 648070}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=464 AND p2.id=803 CREATE (p1)-[e:knows {prop1: 254041}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=190 AND p2.id=208 CREATE (p1)-[e:knows {prop1: 864300}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=826 AND p2.id=205 CREATE (p1)-[e:knows {prop1: 661907}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=748 AND p2.id=24 CREATE (p1)-[e:knows {prop1: 960069}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=953 AND p2.id=173 CREATE (p1)-[e:knows {prop1: 598856}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=947 AND p2.id=568 CREATE (p1)-[e:knows {prop1: 353656}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=288 AND p2.id=363 CREATE (p1)-[e:knows {prop1: 436642}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=327 AND p2.id=66 CREATE (p1)-[e:knows {prop1: 872512}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=628 AND p2.id=881 CREATE (p1)-[e:knows {prop1: 398202}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=736 AND p2.id=270 CREATE (p1)-[e:knows {prop1: 559624}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=394 AND p2.id=606 CREATE (p1)-[e:knows {prop1: 714122}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=568 AND p2.id=290 CREATE (p1)-[e:knows {prop1: 457840}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=637 AND p2.id=680 CREATE (p1)-[e:knows {prop1: 340454}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=632 AND p2.id=604 CREATE (p1)-[e:knows {prop1: 522070}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=615 AND p2.id=237 CREATE (p1)-[e:knows {prop1: 937204}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=865 AND p2.id=434 CREATE (p1)-[e:knows {prop1: 595093}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=927 AND p2.id=760 CREATE (p1)-[e:knows {prop1: 306874}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=127 AND p2.id=952 CREATE (p1)-[e:knows {prop1: 337563}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=410 AND p2.id=783 CREATE (p1)-[e:knows {prop1: 320975}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=788 AND p2.id=937 CREATE (p1)-[e:knows {prop1: 77654}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=72 AND p2.id=329 CREATE (p1)-[e:knows {prop1: 240520}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=359 AND p2.id=20 CREATE (p1)-[e:knows {prop1: 793412}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=594 AND p2.id=895 CREATE (p1)-[e:knows {prop1: 534205}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=739 AND p2.id=322 CREATE (p1)-[e:knows {prop1: 408644}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=870 AND p2.id=507 CREATE (p1)-[e:knows {prop1: 259464}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=14 AND p2.id=27 CREATE (p1)-[e:knows {prop1: 881527}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=509 AND p2.id=808 CREATE (p1)-[e:knows {prop1: 684129}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=535 AND p2.id=156 CREATE (p1)-[e:knows {prop1: 763319}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=438 AND p2.id=329 CREATE (p1)-[e:knows {prop1: 680292}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=947 AND p2.id=440 CREATE (p1)-[e:knows {prop1: 955132}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=75 AND p2.id=970 CREATE (p1)-[e:knows {prop1: 539073}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=523 AND p2.id=639 CREATE (p1)-[e:knows {prop1: 840683}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=64 AND p2.id=682 CREATE (p1)-[e:knows {prop1: 411664}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=22 AND p2.id=156 CREATE (p1)-[e:knows {prop1: 981174}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=480 AND p2.id=678 CREATE (p1)-[e:knows {prop1: 624107}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=158 AND p2.id=485 CREATE (p1)-[e:knows {prop1: 424967}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=131 AND p2.id=241 CREATE (p1)-[e:knows {prop1: 414736}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=214 AND p2.id=958 CREATE (p1)-[e:knows {prop1: 505276}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=271 AND p2.id=867 CREATE (p1)-[e:knows {prop1: 808145}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=363 AND p2.id=968 CREATE (p1)-[e:knows {prop1: 478478}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=429 AND p2.id=391 CREATE (p1)-[e:knows {prop1: 926749}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=132 AND p2.id=174 CREATE (p1)-[e:knows {prop1: 868681}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=759 AND p2.id=156 CREATE (p1)-[e:knows {prop1: 541832}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=941 AND p2.id=729 CREATE (p1)-[e:knows {prop1: 52253}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=858 AND p2.id=785 CREATE (p1)-[e:knows {prop1: 653724}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=547 AND p2.id=712 CREATE (p1)-[e:knows {prop1: 850017}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=500 AND p2.id=33 CREATE (p1)-[e:knows {prop1: 77445}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=126 AND p2.id=442 CREATE (p1)-[e:knows {prop1: 813124}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=345 AND p2.id=194 CREATE (p1)-[e:knows {prop1: 460423}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=197 AND p2.id=628 CREATE (p1)-[e:knows {prop1: 601291}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=138 AND p2.id=549 CREATE (p1)-[e:knows {prop1: 995588}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=153 AND p2.id=129 CREATE (p1)-[e:knows {prop1: 894599}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=51 AND p2.id=794 CREATE (p1)-[e:knows {prop1: 921834}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=953 AND p2.id=70 CREATE (p1)-[e:knows {prop1: 857345}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=175 AND p2.id=76 CREATE (p1)-[e:knows {prop1: 846226}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=76 AND p2.id=763 CREATE (p1)-[e:knows {prop1: 301400}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=99 AND p2.id=909 CREATE (p1)-[e:knows {prop1: 483705}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=368 AND p2.id=952 CREATE (p1)-[e:knows {prop1: 128799}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=252 AND p2.id=438 CREATE (p1)-[e:knows {prop1: 205126}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=869 AND p2.id=778 CREATE (p1)-[e:knows {prop1: 954850}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=142 AND p2.id=665 CREATE (p1)-[e:knows {prop1: 504341}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=341 AND p2.id=746 CREATE (p1)-[e:knows {prop1: 923368}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=910 AND p2.id=226 CREATE (p1)-[e:knows {prop1: 12935}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=73 AND p2.id=120 CREATE (p1)-[e:knows {prop1: 963673}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=13 AND p2.id=133 CREATE (p1)-[e:knows {prop1: 493026}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=536 AND p2.id=295 CREATE (p1)-[e:knows {prop1: 213245}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=968 AND p2.id=217 CREATE (p1)-[e:knows {prop1: 248463}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=736 AND p2.id=774 CREATE (p1)-[e:knows {prop1: 827694}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=46 AND p2.id=784 CREATE (p1)-[e:knows {prop1: 174688}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=141 AND p2.id=363 CREATE (p1)-[e:knows {prop1: 663636}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=607 AND p2.id=906 CREATE (p1)-[e:knows {prop1: 365437}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=681 AND p2.id=659 CREATE (p1)-[e:knows {prop1: 701020}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=326 AND p2.id=881 CREATE (p1)-[e:knows {prop1: 67425}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=699 AND p2.id=693 CREATE (p1)-[e:knows {prop1: 769695}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=136 AND p2.id=388 CREATE (p1)-[e:knows {prop1: 625616}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=85 AND p2.id=987 CREATE (p1)-[e:knows {prop1: 842083}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=382 AND p2.id=135 CREATE (p1)-[e:knows {prop1: 890433}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=357 AND p2.id=488 CREATE (p1)-[e:knows {prop1: 574862}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=706 AND p2.id=240 CREATE (p1)-[e:knows {prop1: 118672}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=177 AND p2.id=574 CREATE (p1)-[e:knows {prop1: 528880}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=428 AND p2.id=65 CREATE (p1)-[e:knows {prop1: 645328}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=524 AND p2.id=8 CREATE (p1)-[e:knows {prop1: 663415}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=479 AND p2.id=307 CREATE (p1)-[e:knows {prop1: 407395}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=630 AND p2.id=326 CREATE (p1)-[e:knows {prop1: 69066}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=313 AND p2.id=557 CREATE (p1)-[e:knows {prop1: 981291}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=614 AND p2.id=430 CREATE (p1)-[e:knows {prop1: 961153}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=436 AND p2.id=857 CREATE (p1)-[e:knows {prop1: 909400}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=295 AND p2.id=623 CREATE (p1)-[e:knows {prop1: 893432}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=477 AND p2.id=999 CREATE (p1)-[e:knows {prop1: 749738}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=901 AND p2.id=106 CREATE (p1)-[e:knows {prop1: 321588}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=478 AND p2.id=885 CREATE (p1)-[e:knows {prop1: 730897}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=739 AND p2.id=761 CREATE (p1)-[e:knows {prop1: 387158}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=729 AND p2.id=543 CREATE (p1)-[e:knows {prop1: 270683}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=350 AND p2.id=634 CREATE (p1)-[e:knows {prop1: 189728}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=94 AND p2.id=856 CREATE (p1)-[e:knows {prop1: 158671}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=909 AND p2.id=366 CREATE (p1)-[e:knows {prop1: 221017}]->(p2); ----- ok --STATEMENT MATCH (p1:Person), (p2:Person) WHERE p1.id=771 AND p2.id=135 CREATE (p1)-[e:knows {prop1: 518103}]->(p2); ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=221 AND p2.id=684 AND e.prop1=187438 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=12 AND p2.id=411 AND e.prop1=347757 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=314 AND p2.id=737 AND e.prop1=648070 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=464 AND p2.id=803 AND e.prop1=254041 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=190 AND p2.id=208 AND e.prop1=864300 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=826 AND p2.id=205 AND e.prop1=661907 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=748 AND p2.id=24 AND e.prop1=960069 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=953 AND p2.id=173 AND e.prop1=598856 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=947 AND p2.id=568 AND e.prop1=353656 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=288 AND p2.id=363 AND e.prop1=436642 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=327 AND p2.id=66 AND e.prop1=872512 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=628 AND p2.id=881 AND e.prop1=398202 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=736 AND p2.id=270 AND e.prop1=559624 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=394 AND p2.id=606 AND e.prop1=714122 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=568 AND p2.id=290 AND e.prop1=457840 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=637 AND p2.id=680 AND e.prop1=340454 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=632 AND p2.id=604 AND e.prop1=522070 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=615 AND p2.id=237 AND e.prop1=937204 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=865 AND p2.id=434 AND e.prop1=595093 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=927 AND p2.id=760 AND e.prop1=306874 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=127 AND p2.id=952 AND e.prop1=337563 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=410 AND p2.id=783 AND e.prop1=320975 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=788 AND p2.id=937 AND e.prop1=77654 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=72 AND p2.id=329 AND e.prop1=240520 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=359 AND p2.id=20 AND e.prop1=793412 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=594 AND p2.id=895 AND e.prop1=534205 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=739 AND p2.id=322 AND e.prop1=408644 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=870 AND p2.id=507 AND e.prop1=259464 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=14 AND p2.id=27 AND e.prop1=881527 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=509 AND p2.id=808 AND e.prop1=684129 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=535 AND p2.id=156 AND e.prop1=763319 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=438 AND p2.id=329 AND e.prop1=680292 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=947 AND p2.id=440 AND e.prop1=955132 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=75 AND p2.id=970 AND e.prop1=539073 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=523 AND p2.id=639 AND e.prop1=840683 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=64 AND p2.id=682 AND e.prop1=411664 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=22 AND p2.id=156 AND e.prop1=981174 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=480 AND p2.id=678 AND e.prop1=624107 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=158 AND p2.id=485 AND e.prop1=424967 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=131 AND p2.id=241 AND e.prop1=414736 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=214 AND p2.id=958 AND e.prop1=505276 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=271 AND p2.id=867 AND e.prop1=808145 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=363 AND p2.id=968 AND e.prop1=478478 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=429 AND p2.id=391 AND e.prop1=926749 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=132 AND p2.id=174 AND e.prop1=868681 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=759 AND p2.id=156 AND e.prop1=541832 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=941 AND p2.id=729 AND e.prop1=52253 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=858 AND p2.id=785 AND e.prop1=653724 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=547 AND p2.id=712 AND e.prop1=850017 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=500 AND p2.id=33 AND e.prop1=77445 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=126 AND p2.id=442 AND e.prop1=813124 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=345 AND p2.id=194 AND e.prop1=460423 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=197 AND p2.id=628 AND e.prop1=601291 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=138 AND p2.id=549 AND e.prop1=995588 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=153 AND p2.id=129 AND e.prop1=894599 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=51 AND p2.id=794 AND e.prop1=921834 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=953 AND p2.id=70 AND e.prop1=857345 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=175 AND p2.id=76 AND e.prop1=846226 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=76 AND p2.id=763 AND e.prop1=301400 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=99 AND p2.id=909 AND e.prop1=483705 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=368 AND p2.id=952 AND e.prop1=128799 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=252 AND p2.id=438 AND e.prop1=205126 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=869 AND p2.id=778 AND e.prop1=954850 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=142 AND p2.id=665 AND e.prop1=504341 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=341 AND p2.id=746 AND e.prop1=923368 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=910 AND p2.id=226 AND e.prop1=12935 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=73 AND p2.id=120 AND e.prop1=963673 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=13 AND p2.id=133 AND e.prop1=493026 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=536 AND p2.id=295 AND e.prop1=213245 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=968 AND p2.id=217 AND e.prop1=248463 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=736 AND p2.id=774 AND e.prop1=827694 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=46 AND p2.id=784 AND e.prop1=174688 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=141 AND p2.id=363 AND e.prop1=663636 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=607 AND p2.id=906 AND e.prop1=365437 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=681 AND p2.id=659 AND e.prop1=701020 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=326 AND p2.id=881 AND e.prop1=67425 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=699 AND p2.id=693 AND e.prop1=769695 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=136 AND p2.id=388 AND e.prop1=625616 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=85 AND p2.id=987 AND e.prop1=842083 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=382 AND p2.id=135 AND e.prop1=890433 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=357 AND p2.id=488 AND e.prop1=574862 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=706 AND p2.id=240 AND e.prop1=118672 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=177 AND p2.id=574 AND e.prop1=528880 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=428 AND p2.id=65 AND e.prop1=645328 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=524 AND p2.id=8 AND e.prop1=663415 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=479 AND p2.id=307 AND e.prop1=407395 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=630 AND p2.id=326 AND e.prop1=69066 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=313 AND p2.id=557 AND e.prop1=981291 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=614 AND p2.id=430 AND e.prop1=961153 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=436 AND p2.id=857 AND e.prop1=909400 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=295 AND p2.id=623 AND e.prop1=893432 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=477 AND p2.id=999 AND e.prop1=749738 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=901 AND p2.id=106 AND e.prop1=321588 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=478 AND p2.id=885 AND e.prop1=730897 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=739 AND p2.id=761 AND e.prop1=387158 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=729 AND p2.id=543 AND e.prop1=270683 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=350 AND p2.id=634 AND e.prop1=189728 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=94 AND p2.id=856 AND e.prop1=158671 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=909 AND p2.id=366 AND e.prop1=221017 DELETE e; ----- ok --STATEMENT MATCH (p1:Person)-[e:knows]->(p2:Person) WHERE p1.id=771 AND p2.id=135 AND e.prop1=518103 DELETE e; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=0 AND p.prop1=142215 AND p.prop2='Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=1 AND p.prop1=878242 AND p.prop2='GO4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=2 AND p.prop1=836516 AND p.prop2='7R2MJD25G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=3 AND p.prop1=206382 AND p.prop2='X137NINSSS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=4 AND p.prop1=120923 AND p.prop2='TVB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=5 AND p.prop1=876432 AND p.prop2='YIKU910' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=6 AND p.prop1=38863 AND p.prop2='MZVHYJ0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=7 AND p.prop1=927513 AND p.prop2='80QOC1HMG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=8 AND p.prop1=371524 AND p.prop2='V2J1HETGK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=9 AND p.prop1=550015 AND p.prop2='MPZWQC5SW7A' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=10 AND p.prop1=487871 AND p.prop2='EHVFGX86N5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=11 AND p.prop1=595954 AND p.prop2='B185J2K' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=12 AND p.prop1=122737 AND p.prop2='5RK9HBF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=13 AND p.prop1=985147 AND p.prop2='TEGKHN5LIDU77P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=14 AND p.prop1=824973 AND p.prop2='EJCDDAYLXH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=15 AND p.prop1=565022 AND p.prop2='ZIHY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=16 AND p.prop1=583825 AND p.prop2='NC9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=17 AND p.prop1=685363 AND p.prop2='RH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=18 AND p.prop1=958294 AND p.prop2='YLENEN4NQ1A' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=19 AND p.prop1=284652 AND p.prop2='UQNYSKI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=20 AND p.prop1=210888 AND p.prop2='LGWV7OIMJ0O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=21 AND p.prop1=281745 AND p.prop2='NH4WXFWO7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=22 AND p.prop1=280189 AND p.prop2='FDPBGGH5I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=23 AND p.prop1=269537 AND p.prop2='BO5JAX62ZHEW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=24 AND p.prop1=734377 AND p.prop2='DAWIYOLU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=25 AND p.prop1=152454 AND p.prop2='WGF0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=26 AND p.prop1=848083 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=27 AND p.prop1=639375 AND p.prop2='42WN66XP9C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=28 AND p.prop1=110955 AND p.prop2='N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=29 AND p.prop1=103714 AND p.prop2='A78TOD4HMSHPX3N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=30 AND p.prop1=180357 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=31 AND p.prop1=955977 AND p.prop2='N8NZGFAT3WC6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=32 AND p.prop1=561795 AND p.prop2='TJEPGIKWOB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=33 AND p.prop1=775568 AND p.prop2='Z6JA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=34 AND p.prop1=446328 AND p.prop2='ZN732JW8V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=35 AND p.prop1=357881 AND p.prop2='2XDI1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=36 AND p.prop1=651829 AND p.prop2='TSFSRD9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=37 AND p.prop1=533241 AND p.prop2='JYIU65HS7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=38 AND p.prop1=526516 AND p.prop2='WF3T6TYE0S0G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=39 AND p.prop1=172117 AND p.prop2='0CGK01OP7I3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=40 AND p.prop1=842075 AND p.prop2='78Z6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=41 AND p.prop1=476616 AND p.prop2='3R7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=42 AND p.prop1=198061 AND p.prop2='NWA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=43 AND p.prop1=578273 AND p.prop2='Z2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=44 AND p.prop1=502321 AND p.prop2='WVML0NE65859MT3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=45 AND p.prop1=869561 AND p.prop2='P74KOQS4DQ5E' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=46 AND p.prop1=313493 AND p.prop2='QI5CYSQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=47 AND p.prop1=774511 AND p.prop2='UTV79CVE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=48 AND p.prop1=272775 AND p.prop2='A0P8GWYI829K' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=49 AND p.prop1=903471 AND p.prop2='8T1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=50 AND p.prop1=759878 AND p.prop2='R21SJGEJY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=51 AND p.prop1=321168 AND p.prop2='VG3IGJ8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=52 AND p.prop1=260765 AND p.prop2='CQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=53 AND p.prop1=734470 AND p.prop2='VC4IHNL2ECR02C6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=54 AND p.prop1=83448 AND p.prop2='OMYU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=55 AND p.prop1=432067 AND p.prop2='COZ8Q7GCOJNG0H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=56 AND p.prop1=726038 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=57 AND p.prop1=4987 AND p.prop2='UXBR1066RBUN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=58 AND p.prop1=682142 AND p.prop2='NWH9L0M9S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=59 AND p.prop1=193306 AND p.prop2='N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=60 AND p.prop1=576741 AND p.prop2='EQJ8PAMCHKFO37' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=61 AND p.prop1=319178 AND p.prop2='HTYJP1XGUC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=62 AND p.prop1=475596 AND p.prop2='LWB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=63 AND p.prop1=410752 AND p.prop2='8RMZOWD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=64 AND p.prop1=497200 AND p.prop2='OADFC0K7OOS62FV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=65 AND p.prop1=729981 AND p.prop2='36TNCVK1I3R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=66 AND p.prop1=263975 AND p.prop2='4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=67 AND p.prop1=577758 AND p.prop2='C9NG9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=68 AND p.prop1=246488 AND p.prop2='HTZ1QS1AJ12WN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=69 AND p.prop1=521264 AND p.prop2='24BI1SFKVJNV1K2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=70 AND p.prop1=400001 AND p.prop2='1Y20' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=71 AND p.prop1=685249 AND p.prop2='O8U7PDMV8WSQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=72 AND p.prop1=977470 AND p.prop2='DAGYKA2074OVM6M' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=73 AND p.prop1=267925 AND p.prop2='JD3HLW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=74 AND p.prop1=814093 AND p.prop2='H8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=75 AND p.prop1=248280 AND p.prop2='UW8SYG1GFMTNQZU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=76 AND p.prop1=186303 AND p.prop2='8N5P72QGNM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=77 AND p.prop1=202328 AND p.prop2='V7T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=78 AND p.prop1=267629 AND p.prop2='3NKG5IBZN6C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=79 AND p.prop1=442319 AND p.prop2='WOBU124ROR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=80 AND p.prop1=918851 AND p.prop2='Z42RM4W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=81 AND p.prop1=489975 AND p.prop2='62U2M0WBVEY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=82 AND p.prop1=765461 AND p.prop2='65TAGXYIS2L3NH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=83 AND p.prop1=925161 AND p.prop2='C4E35H4JGKZE6Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=84 AND p.prop1=43575 AND p.prop2='UI9XTE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=85 AND p.prop1=699449 AND p.prop2='SW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=86 AND p.prop1=264126 AND p.prop2='WT34RHLW44' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=87 AND p.prop1=473492 AND p.prop2='IH2AJUMI7NU89' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=88 AND p.prop1=350244 AND p.prop2='RBCKIS1SJN0BHW5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=89 AND p.prop1=282497 AND p.prop2='O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=90 AND p.prop1=194572 AND p.prop2='25O1CMU6KW3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=91 AND p.prop1=499424 AND p.prop2='9ZJ5KPDV313F1T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=92 AND p.prop1=124516 AND p.prop2='9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=93 AND p.prop1=480616 AND p.prop2='N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=94 AND p.prop1=886471 AND p.prop2='J' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=95 AND p.prop1=652691 AND p.prop2='WD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=96 AND p.prop1=652602 AND p.prop2='L8N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=97 AND p.prop1=203657 AND p.prop2='EW7HF91NJX5HD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=98 AND p.prop1=364764 AND p.prop2='031DV0SG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=99 AND p.prop1=160943 AND p.prop2='X0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=100 AND p.prop1=423712 AND p.prop2='OTRCXTBAT85H7L0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=101 AND p.prop1=856546 AND p.prop2='E8M1UGJNSB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=102 AND p.prop1=72737 AND p.prop2='39APMZWXQKR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=103 AND p.prop1=538681 AND p.prop2='GVWT9UTHBFBW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=104 AND p.prop1=104942 AND p.prop2='K0S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=105 AND p.prop1=118091 AND p.prop2='HCV6J0Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=106 AND p.prop1=472091 AND p.prop2='779RUF27I8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=107 AND p.prop1=481565 AND p.prop2='5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=108 AND p.prop1=919296 AND p.prop2='KKNFCXMEBG23ZY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=109 AND p.prop1=103019 AND p.prop2='HMNW2R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=110 AND p.prop1=20762 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=111 AND p.prop1=879748 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=112 AND p.prop1=828648 AND p.prop2='OY1HH6I1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=113 AND p.prop1=884177 AND p.prop2='A8W46I6P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=114 AND p.prop1=47315 AND p.prop2='AKE9AZ9WHP73R17' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=115 AND p.prop1=253408 AND p.prop2='4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=116 AND p.prop1=302335 AND p.prop2='2ETE8NY0EBVT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=117 AND p.prop1=150650 AND p.prop2='7AANX6F2JXQDJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=118 AND p.prop1=530197 AND p.prop2='C8EK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=119 AND p.prop1=674541 AND p.prop2='MHM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=120 AND p.prop1=837944 AND p.prop2='384' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=121 AND p.prop1=194173 AND p.prop2='8BGI8SFJ7CEYV9I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=122 AND p.prop1=361779 AND p.prop2='MC0FATBIL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=123 AND p.prop1=203176 AND p.prop2='RH5VQM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=124 AND p.prop1=133891 AND p.prop2='0P17N0TVK8WRTKP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=125 AND p.prop1=957099 AND p.prop2='DG9CRR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=126 AND p.prop1=103250 AND p.prop2='VU3L18HW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=127 AND p.prop1=750558 AND p.prop2='RCJJJ9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=128 AND p.prop1=414057 AND p.prop2='EGVD5L5ZA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=129 AND p.prop1=885326 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=130 AND p.prop1=364776 AND p.prop2='K4KYXRJ63502LQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=131 AND p.prop1=483675 AND p.prop2='N0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=132 AND p.prop1=122272 AND p.prop2='MKXTIOVD3NX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=133 AND p.prop1=15043 AND p.prop2='O7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=134 AND p.prop1=997850 AND p.prop2='FM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=135 AND p.prop1=985927 AND p.prop2='8X3HL63JBUFLYH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=136 AND p.prop1=199424 AND p.prop2='EZ7XBN89AK90OZS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=137 AND p.prop1=955757 AND p.prop2='R0ALKQ56' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=138 AND p.prop1=364172 AND p.prop2='OMF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=139 AND p.prop1=930597 AND p.prop2='RRC8C4Y0MME4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=140 AND p.prop1=592133 AND p.prop2='QMC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=141 AND p.prop1=608173 AND p.prop2='5UENR7GFVJ7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=142 AND p.prop1=516501 AND p.prop2='JF4HBC86' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=143 AND p.prop1=957693 AND p.prop2='4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=144 AND p.prop1=497660 AND p.prop2='LNE4JNVCJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=145 AND p.prop1=394920 AND p.prop2='0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=146 AND p.prop1=922644 AND p.prop2='VG2B7R0QVBZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=147 AND p.prop1=44759 AND p.prop2='Z42F32BTNW9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=148 AND p.prop1=685034 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=149 AND p.prop1=539925 AND p.prop2='JJKDKHDPJ9ID' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=150 AND p.prop1=502806 AND p.prop2='QZUKTYUT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=151 AND p.prop1=114969 AND p.prop2='YDJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=152 AND p.prop1=40658 AND p.prop2='UZB2XHWX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=153 AND p.prop1=390989 AND p.prop2='27EZ2QZYQUIDYXV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=154 AND p.prop1=440884 AND p.prop2='MRIW9R9PKFXXWG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=155 AND p.prop1=734377 AND p.prop2='Z5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=156 AND p.prop1=630481 AND p.prop2='C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=157 AND p.prop1=191992 AND p.prop2='XKYHIL3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=158 AND p.prop1=820384 AND p.prop2='FULAR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=159 AND p.prop1=244510 AND p.prop2='D56Z4SF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=160 AND p.prop1=494734 AND p.prop2='TAQV3MLYJD047' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=161 AND p.prop1=629927 AND p.prop2='3OXTLP40GR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=162 AND p.prop1=369165 AND p.prop2='GK43TN45WFLE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=163 AND p.prop1=235024 AND p.prop2='HTU2I171DURL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=164 AND p.prop1=880112 AND p.prop2='VRV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=165 AND p.prop1=844206 AND p.prop2='WNDKLU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=166 AND p.prop1=462068 AND p.prop2='N6U4PC7ARY2K5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=167 AND p.prop1=534866 AND p.prop2='5O68667TI4V3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=168 AND p.prop1=903326 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=169 AND p.prop1=453947 AND p.prop2='VVL3UYYXJN2TM6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=170 AND p.prop1=271343 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=171 AND p.prop1=871109 AND p.prop2='I8Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=172 AND p.prop1=454952 AND p.prop2='4D5B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=173 AND p.prop1=222941 AND p.prop2='CT3B18OGZMKI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=174 AND p.prop1=833976 AND p.prop2='XI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=175 AND p.prop1=135018 AND p.prop2='EVXBF4QE5A' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=176 AND p.prop1=782324 AND p.prop2='T6ZJ61AGYQN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=177 AND p.prop1=905482 AND p.prop2='1EB2LXZ434YX0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=178 AND p.prop1=223428 AND p.prop2='I4I7142' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=179 AND p.prop1=594296 AND p.prop2='PZ8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=180 AND p.prop1=544426 AND p.prop2='T5FOKNCL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=181 AND p.prop1=125393 AND p.prop2='F' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=182 AND p.prop1=8255 AND p.prop2='8Z3AXZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=183 AND p.prop1=37142 AND p.prop2='X99BSKTORMME' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=184 AND p.prop1=225633 AND p.prop2='HE087WORS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=185 AND p.prop1=34079 AND p.prop2='H3CC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=186 AND p.prop1=676606 AND p.prop2='H6W1G3BWBDH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=187 AND p.prop1=6388 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=188 AND p.prop1=962040 AND p.prop2='2Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=189 AND p.prop1=198524 AND p.prop2='6KF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=190 AND p.prop1=152006 AND p.prop2='IAW4PL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=191 AND p.prop1=292753 AND p.prop2='NICR8O53PC0773' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=192 AND p.prop1=662167 AND p.prop2='8R4PXTB9QQDW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=193 AND p.prop1=572552 AND p.prop2='R5P9UFF2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=194 AND p.prop1=811113 AND p.prop2='RYE380ZFNFJF7F' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=195 AND p.prop1=327384 AND p.prop2='ONK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=196 AND p.prop1=405724 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=197 AND p.prop1=871561 AND p.prop2='5LSZ2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=198 AND p.prop1=674045 AND p.prop2='1W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=199 AND p.prop1=395645 AND p.prop2='QGCTLTPF4I4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=200 AND p.prop1=462174 AND p.prop2='XS8P433Q5KX1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=201 AND p.prop1=88425 AND p.prop2='ZTCR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=202 AND p.prop1=288861 AND p.prop2='ZM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=203 AND p.prop1=116402 AND p.prop2='VHTOLATS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=204 AND p.prop1=887562 AND p.prop2='3I7TU23O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=205 AND p.prop1=224737 AND p.prop2='PZ7139GGK7A8V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=206 AND p.prop1=268841 AND p.prop2='USNYAC4H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=207 AND p.prop1=621933 AND p.prop2='22X4D1Q1Z4VV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=208 AND p.prop1=520613 AND p.prop2='ESEVKUUK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=209 AND p.prop1=280407 AND p.prop2='HZIE6KE1HNY2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=210 AND p.prop1=844790 AND p.prop2='4TLE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=211 AND p.prop1=83970 AND p.prop2='ZV1RY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=212 AND p.prop1=296349 AND p.prop2='H0S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=213 AND p.prop1=757312 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=214 AND p.prop1=853698 AND p.prop2='VTTMM403Q7JVJBN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=215 AND p.prop1=410925 AND p.prop2='J' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=216 AND p.prop1=310419 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=217 AND p.prop1=679786 AND p.prop2='RZVS3SOZAAF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=218 AND p.prop1=975262 AND p.prop2='19M6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=219 AND p.prop1=289821 AND p.prop2='EEH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=220 AND p.prop1=662388 AND p.prop2='FWB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=221 AND p.prop1=436588 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=222 AND p.prop1=324746 AND p.prop2='9YRP0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=223 AND p.prop1=699161 AND p.prop2='I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=224 AND p.prop1=735853 AND p.prop2='1FBRLJ03ZY73' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=225 AND p.prop1=479085 AND p.prop2='T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=226 AND p.prop1=655291 AND p.prop2='ZSUKW33F2W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=227 AND p.prop1=835867 AND p.prop2='4QQIF5NT86AJD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=228 AND p.prop1=986275 AND p.prop2='3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=229 AND p.prop1=294049 AND p.prop2='YPMT6G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=230 AND p.prop1=413538 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=231 AND p.prop1=177809 AND p.prop2='6DDN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=232 AND p.prop1=738289 AND p.prop2='9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=233 AND p.prop1=10660 AND p.prop2='K8ZVWEU84IZF4PM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=234 AND p.prop1=427506 AND p.prop2='GNYE87' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=235 AND p.prop1=762513 AND p.prop2='AD5K204TJPQNL6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=236 AND p.prop1=260983 AND p.prop2='ZMDQ44' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=237 AND p.prop1=454747 AND p.prop2='GE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=238 AND p.prop1=232801 AND p.prop2='8OYH4B9JXY40VW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=239 AND p.prop1=786186 AND p.prop2='S5B7HLFC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=240 AND p.prop1=27236 AND p.prop2='DVPMJ9YN1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=241 AND p.prop1=171890 AND p.prop2='OSX2Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=242 AND p.prop1=472746 AND p.prop2='9OLJ6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=243 AND p.prop1=391483 AND p.prop2='MK0P1WX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=244 AND p.prop1=585953 AND p.prop2='8LYB9R0MN53S7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=245 AND p.prop1=329419 AND p.prop2='73YVFHQTXH5HP2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=246 AND p.prop1=660510 AND p.prop2='8R6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=247 AND p.prop1=562727 AND p.prop2='EXXIZT79' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=248 AND p.prop1=990153 AND p.prop2='ZLW8PXB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=249 AND p.prop1=485008 AND p.prop2='7S2SAY6R8L2ADLB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=250 AND p.prop1=717787 AND p.prop2='6K6KZS1GTMTBJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=251 AND p.prop1=914875 AND p.prop2='B6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=252 AND p.prop1=760785 AND p.prop2='0B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=253 AND p.prop1=285781 AND p.prop2='BJGN5IAH6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=254 AND p.prop1=910763 AND p.prop2='25Z8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=255 AND p.prop1=747230 AND p.prop2='K3KCN87U4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=256 AND p.prop1=954294 AND p.prop2='3G7KIU4ZSELC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=257 AND p.prop1=709840 AND p.prop2='WJHE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=258 AND p.prop1=739379 AND p.prop2='6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=259 AND p.prop1=321387 AND p.prop2='DWBLCZP0V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=260 AND p.prop1=126667 AND p.prop2='Z81NLTM36D' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=261 AND p.prop1=402383 AND p.prop2='IMLYNJNRWK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=262 AND p.prop1=265875 AND p.prop2='K2CJXVP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=263 AND p.prop1=421157 AND p.prop2='FEXY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=264 AND p.prop1=915608 AND p.prop2='HSO8T88' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=265 AND p.prop1=95350 AND p.prop2='I99MGI9B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=266 AND p.prop1=523169 AND p.prop2='G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=267 AND p.prop1=216252 AND p.prop2='ZRGOTFGJZ30' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=268 AND p.prop1=350858 AND p.prop2='IFTBFU6XZ3SZE5Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=269 AND p.prop1=716103 AND p.prop2='D2RHVZ6CGCGR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=270 AND p.prop1=330884 AND p.prop2='4VENCV9ASBGBKRF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=271 AND p.prop1=363796 AND p.prop2='BZ5VGH3L' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=272 AND p.prop1=222647 AND p.prop2='ISIYYM8S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=273 AND p.prop1=241754 AND p.prop2='8PW9OL67KWJK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=274 AND p.prop1=946564 AND p.prop2='AJ4FSMRBO1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=275 AND p.prop1=613257 AND p.prop2='EH1PD7VY6MY9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=276 AND p.prop1=931154 AND p.prop2='60O57' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=277 AND p.prop1=656112 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=278 AND p.prop1=281344 AND p.prop2='SK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=279 AND p.prop1=288437 AND p.prop2='ATJ1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=280 AND p.prop1=949633 AND p.prop2='L0G4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=281 AND p.prop1=533941 AND p.prop2='N6VP2MSI7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=282 AND p.prop1=688596 AND p.prop2='UD28YW7HM2FG2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=283 AND p.prop1=636589 AND p.prop2='2AZ5E1SP1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=284 AND p.prop1=843812 AND p.prop2='W6HETKVO4Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=285 AND p.prop1=641012 AND p.prop2='FFNFE8G2E' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=286 AND p.prop1=425626 AND p.prop2='K1HHKRW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=287 AND p.prop1=383051 AND p.prop2='Q70Z2OK1HK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=288 AND p.prop1=85241 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=289 AND p.prop1=653641 AND p.prop2='050PD4867' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=290 AND p.prop1=880159 AND p.prop2='6YNDB4ZPX3UGX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=291 AND p.prop1=163818 AND p.prop2='YMLM0T7AD15Y6R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=292 AND p.prop1=560946 AND p.prop2='HPVZT23KBN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=293 AND p.prop1=323105 AND p.prop2='MIJYZGXSBDQEXOY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=294 AND p.prop1=922551 AND p.prop2='TQF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=295 AND p.prop1=637013 AND p.prop2='I9F5IXS1WX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=296 AND p.prop1=537762 AND p.prop2='QBUV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=297 AND p.prop1=709409 AND p.prop2='FSMSLA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=298 AND p.prop1=219421 AND p.prop2='GKI0TZ9HL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=299 AND p.prop1=575534 AND p.prop2='I8A3I8MBJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=300 AND p.prop1=495790 AND p.prop2='AV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=301 AND p.prop1=164280 AND p.prop2='Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=302 AND p.prop1=857553 AND p.prop2='GRAY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=303 AND p.prop1=415602 AND p.prop2='56S3X6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=304 AND p.prop1=533701 AND p.prop2='9SH7M' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=305 AND p.prop1=478174 AND p.prop2='ZR9W8M3K072IM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=306 AND p.prop1=560184 AND p.prop2='F83RTG6W67Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=307 AND p.prop1=321642 AND p.prop2='0LUB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=308 AND p.prop1=987544 AND p.prop2='R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=309 AND p.prop1=411604 AND p.prop2='YNIQ8G5YQUEJ2YT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=310 AND p.prop1=213349 AND p.prop2='V9WOPK7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=311 AND p.prop1=213199 AND p.prop2='BSMUAGT304ZPIEV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=312 AND p.prop1=905451 AND p.prop2='AECJU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=313 AND p.prop1=43274 AND p.prop2='YX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=314 AND p.prop1=153063 AND p.prop2='8GTC5VGPL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=315 AND p.prop1=606314 AND p.prop2='41LNY2VHY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=316 AND p.prop1=85485 AND p.prop2='0I5Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=317 AND p.prop1=70561 AND p.prop2='DWHOL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=318 AND p.prop1=713046 AND p.prop2='YQCNAP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=319 AND p.prop1=224919 AND p.prop2='5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=320 AND p.prop1=701011 AND p.prop2='FQ2VVR9RYW63Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=321 AND p.prop1=792846 AND p.prop2='7663' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=322 AND p.prop1=118194 AND p.prop2='U418GML21BGEEHB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=323 AND p.prop1=930111 AND p.prop2='K2SU82PKS8WO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=324 AND p.prop1=199833 AND p.prop2='3A2J9631SVEK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=325 AND p.prop1=94525 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=326 AND p.prop1=644504 AND p.prop2='2X526TX7P8ZT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=327 AND p.prop1=610924 AND p.prop2='P851BZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=328 AND p.prop1=105592 AND p.prop2='72DWX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=329 AND p.prop1=118673 AND p.prop2='MYEBIHF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=330 AND p.prop1=572728 AND p.prop2='FD6JV5567SC5KF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=331 AND p.prop1=832154 AND p.prop2='B3N1RE74KJ3KJ8T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=332 AND p.prop1=783792 AND p.prop2='I8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=333 AND p.prop1=148611 AND p.prop2='S0RISRHI2J48' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=334 AND p.prop1=66527 AND p.prop2='QFQDG74FX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=335 AND p.prop1=522321 AND p.prop2='OSVT8KROBU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=336 AND p.prop1=66936 AND p.prop2='WL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=337 AND p.prop1=497847 AND p.prop2='W8JESP55' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=338 AND p.prop1=845447 AND p.prop2='15' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=339 AND p.prop1=781343 AND p.prop2='ZUPJZT8R2B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=340 AND p.prop1=343180 AND p.prop2='7T8ZRKK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=341 AND p.prop1=4929 AND p.prop2='I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=342 AND p.prop1=132902 AND p.prop2='WW5BQU9I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=343 AND p.prop1=488509 AND p.prop2='NWCEPS9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=344 AND p.prop1=64694 AND p.prop2='WZLMTWZF6VN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=345 AND p.prop1=449132 AND p.prop2='2AA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=346 AND p.prop1=575889 AND p.prop2='1EPB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=347 AND p.prop1=45215 AND p.prop2='35AGD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=348 AND p.prop1=970030 AND p.prop2='IZZAOMTYQYRB7C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=349 AND p.prop1=453223 AND p.prop2='JO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=350 AND p.prop1=821793 AND p.prop2='749' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=351 AND p.prop1=950571 AND p.prop2='PT872H5XUCND' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=352 AND p.prop1=720321 AND p.prop2='7V32124OHYV3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=353 AND p.prop1=300987 AND p.prop2='K20OEM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=354 AND p.prop1=646710 AND p.prop2='8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=355 AND p.prop1=253539 AND p.prop2='1462BK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=356 AND p.prop1=589840 AND p.prop2='P2JH87' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=357 AND p.prop1=954218 AND p.prop2='EONNEYOL5M' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=358 AND p.prop1=571588 AND p.prop2='I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=359 AND p.prop1=601747 AND p.prop2='8XWJQCXDF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=360 AND p.prop1=946023 AND p.prop2='KSYFF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=361 AND p.prop1=969232 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=362 AND p.prop1=64081 AND p.prop2='S9EZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=363 AND p.prop1=13235 AND p.prop2='IRIKZDTB4NA6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=364 AND p.prop1=236342 AND p.prop2='76OK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=365 AND p.prop1=634885 AND p.prop2='5U2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=366 AND p.prop1=754049 AND p.prop2='IDALDMDWD5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=367 AND p.prop1=164282 AND p.prop2='J1C8PAHHMG560R6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=368 AND p.prop1=807608 AND p.prop2='GHY9TBY5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=369 AND p.prop1=68780 AND p.prop2='5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=370 AND p.prop1=383042 AND p.prop2='YJ39H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=371 AND p.prop1=393704 AND p.prop2='WC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=372 AND p.prop1=86061 AND p.prop2='PVRSRRY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=373 AND p.prop1=226238 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=374 AND p.prop1=237693 AND p.prop2='B44Z2N5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=375 AND p.prop1=90989 AND p.prop2='SVA8TW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=376 AND p.prop1=529059 AND p.prop2='HWZ0EW3S8LE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=377 AND p.prop1=818095 AND p.prop2='N0IABNDE8E' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=378 AND p.prop1=397368 AND p.prop2='O2WSIO2C13NAKEV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=379 AND p.prop1=553393 AND p.prop2='T9S495' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=380 AND p.prop1=625516 AND p.prop2='1Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=381 AND p.prop1=428584 AND p.prop2='T8NWM5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=382 AND p.prop1=416608 AND p.prop2='VAUTHZ8L643PILR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=383 AND p.prop1=193979 AND p.prop2='K0C26' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=384 AND p.prop1=494700 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=385 AND p.prop1=852823 AND p.prop2='XLX6GZYV3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=386 AND p.prop1=756538 AND p.prop2='RF09STO9GXAH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=387 AND p.prop1=375593 AND p.prop2='FXBVL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=388 AND p.prop1=96835 AND p.prop2='YQNQ6CR7PZ8PCV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=389 AND p.prop1=282885 AND p.prop2='CZ5SJTJJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=390 AND p.prop1=543548 AND p.prop2='AQXQS0X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=391 AND p.prop1=181154 AND p.prop2='1G23VRGK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=392 AND p.prop1=581131 AND p.prop2='5MORMGN4MDBYHDX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=393 AND p.prop1=619480 AND p.prop2='NX0603XXVG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=394 AND p.prop1=68792 AND p.prop2='WH0ML0CPF30W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=395 AND p.prop1=890917 AND p.prop2='ZRH97846THGJYA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=396 AND p.prop1=838728 AND p.prop2='5OPIFB4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=397 AND p.prop1=222606 AND p.prop2='3LFLEZSP6V1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=398 AND p.prop1=982116 AND p.prop2='3EEQ8PHR94' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=399 AND p.prop1=652161 AND p.prop2='I2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=400 AND p.prop1=841569 AND p.prop2='HDEH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=401 AND p.prop1=469186 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=402 AND p.prop1=837495 AND p.prop2='3MTEN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=403 AND p.prop1=990988 AND p.prop2='UJ9E76I4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=404 AND p.prop1=563304 AND p.prop2='R5RD9I0TGN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=405 AND p.prop1=709357 AND p.prop2='ZH7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=406 AND p.prop1=725595 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=407 AND p.prop1=461587 AND p.prop2='8XE86H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=408 AND p.prop1=910053 AND p.prop2='VFOGTA8G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=409 AND p.prop1=640945 AND p.prop2='15WRM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=410 AND p.prop1=11896 AND p.prop2='ID0HO2P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=411 AND p.prop1=657625 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=412 AND p.prop1=369481 AND p.prop2='9J5I68P7C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=413 AND p.prop1=222590 AND p.prop2='ZJPE6BYJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=414 AND p.prop1=406345 AND p.prop2='SIDMHLYHV1CYOM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=415 AND p.prop1=136029 AND p.prop2='GT1W95QRQUL0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=416 AND p.prop1=825143 AND p.prop2='F11TGV03WKLVP9P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=417 AND p.prop1=61786 AND p.prop2='QBWC1I4CRT86' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=418 AND p.prop1=121359 AND p.prop2='Y1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=419 AND p.prop1=367725 AND p.prop2='R9O2LMU07X5VRA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=420 AND p.prop1=799769 AND p.prop2='DGP5JR2Z9G7YBSR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=421 AND p.prop1=424369 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=422 AND p.prop1=585278 AND p.prop2='97SZV220E2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=423 AND p.prop1=621193 AND p.prop2='UF3OXRB255G3KN6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=424 AND p.prop1=192294 AND p.prop2='F11C5QQNYL9GH5T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=425 AND p.prop1=830061 AND p.prop2='SC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=426 AND p.prop1=134664 AND p.prop2='IWIYF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=427 AND p.prop1=563700 AND p.prop2='6AZMUI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=428 AND p.prop1=225744 AND p.prop2='KIRN82R9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=429 AND p.prop1=605610 AND p.prop2='7LXYASFTZ87' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=430 AND p.prop1=660732 AND p.prop2='J5XHCN8Y0O2SN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=431 AND p.prop1=712624 AND p.prop2='BWCUWHPA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=432 AND p.prop1=76271 AND p.prop2='KRL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=433 AND p.prop1=488397 AND p.prop2='H6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=434 AND p.prop1=894742 AND p.prop2='9ZXT131U' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=435 AND p.prop1=219610 AND p.prop2='3F6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=436 AND p.prop1=378634 AND p.prop2='2DF96PZWKXKH3YW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=437 AND p.prop1=912271 AND p.prop2='Q9HFT6KID13' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=438 AND p.prop1=642330 AND p.prop2='7B7Y13K1QLFYF4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=439 AND p.prop1=883818 AND p.prop2='IVKVZ2WN2E4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=440 AND p.prop1=835557 AND p.prop2='9ZUWLR0EWR8JD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=441 AND p.prop1=442343 AND p.prop2='PB4MBY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=442 AND p.prop1=548113 AND p.prop2='P6B6X5F4E5BA3C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=443 AND p.prop1=778766 AND p.prop2='6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=444 AND p.prop1=289452 AND p.prop2='AV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=445 AND p.prop1=144038 AND p.prop2='WLHVZBR9KZEL7BJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=446 AND p.prop1=653104 AND p.prop2='XXP8NI5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=447 AND p.prop1=404822 AND p.prop2='133CV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=448 AND p.prop1=828039 AND p.prop2='8N1886SD24USMZQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=449 AND p.prop1=403379 AND p.prop2='JNOE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=450 AND p.prop1=717466 AND p.prop2='B4RAZMNT8Z5S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=451 AND p.prop1=449924 AND p.prop2='1ST6HF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=452 AND p.prop1=489710 AND p.prop2='XPJX33ETX42' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=453 AND p.prop1=98965 AND p.prop2='V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=454 AND p.prop1=115763 AND p.prop2='W2Y3MNB1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=455 AND p.prop1=503334 AND p.prop2='6GE0SL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=456 AND p.prop1=597859 AND p.prop2='3Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=457 AND p.prop1=225392 AND p.prop2='OOLH1OPJSPK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=458 AND p.prop1=563599 AND p.prop2='YUBK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=459 AND p.prop1=900299 AND p.prop2='25UGKX5R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=460 AND p.prop1=424854 AND p.prop2='6F1DAMQ9SZYU0W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=461 AND p.prop1=638528 AND p.prop2='NL6LIJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=462 AND p.prop1=632686 AND p.prop2='FC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=463 AND p.prop1=68530 AND p.prop2='12N4SP7IW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=464 AND p.prop1=785331 AND p.prop2='JPN0PY1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=465 AND p.prop1=68059 AND p.prop2='B7HLXLW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=466 AND p.prop1=535239 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=467 AND p.prop1=406003 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=468 AND p.prop1=641669 AND p.prop2='3O32B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=469 AND p.prop1=35085 AND p.prop2='H5WKMOILX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=470 AND p.prop1=47273 AND p.prop2='V7B7N3TO12C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=471 AND p.prop1=516061 AND p.prop2='PLH4C8L0SB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=472 AND p.prop1=128641 AND p.prop2='6URM3JRKZC8Y3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=473 AND p.prop1=869031 AND p.prop2='2PIS8WG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=474 AND p.prop1=700621 AND p.prop2='4HHVS2B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=475 AND p.prop1=324756 AND p.prop2='PTXUW7M3UW7Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=476 AND p.prop1=975496 AND p.prop2='DEI52' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=477 AND p.prop1=994319 AND p.prop2='5VO05WF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=478 AND p.prop1=981110 AND p.prop2='N1OA7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=479 AND p.prop1=20975 AND p.prop2='NFSWQ0W2SH5PNI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=480 AND p.prop1=931809 AND p.prop2='TH34C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=481 AND p.prop1=236777 AND p.prop2='Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=482 AND p.prop1=315448 AND p.prop2='5SP6A1GAU40OV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=483 AND p.prop1=436839 AND p.prop2='RILQTTXCWP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=484 AND p.prop1=628785 AND p.prop2='RWAX8E15MF2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=485 AND p.prop1=123556 AND p.prop2='ZFZRJCSIGCWV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=486 AND p.prop1=753004 AND p.prop2='CVS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=487 AND p.prop1=68915 AND p.prop2='7NZW1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=488 AND p.prop1=555336 AND p.prop2='YDW2RMNL89B4AVJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=489 AND p.prop1=15184 AND p.prop2='82KPS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=490 AND p.prop1=217076 AND p.prop2='AVAV6KTYRF4DV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=491 AND p.prop1=990918 AND p.prop2='0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=492 AND p.prop1=563927 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=493 AND p.prop1=714762 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=494 AND p.prop1=852314 AND p.prop2='A7IOTWZF22X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=495 AND p.prop1=991143 AND p.prop2='X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=496 AND p.prop1=292869 AND p.prop2='ZW5O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=497 AND p.prop1=150418 AND p.prop2='KFVOKYL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=498 AND p.prop1=229997 AND p.prop2='YFPR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=499 AND p.prop1=133597 AND p.prop2='T24OVAXVIH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=500 AND p.prop1=53404 AND p.prop2='S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=501 AND p.prop1=418334 AND p.prop2='FZ7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=502 AND p.prop1=226074 AND p.prop2='4PPFZJ0XESA9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=503 AND p.prop1=727958 AND p.prop2='7DHNIC4YP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=504 AND p.prop1=602431 AND p.prop2='2AEPENBXJU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=505 AND p.prop1=699135 AND p.prop2='B0G4XEOOIX0XD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=506 AND p.prop1=895374 AND p.prop2='3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=507 AND p.prop1=366928 AND p.prop2='BEW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=508 AND p.prop1=42270 AND p.prop2='L84TJ4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=509 AND p.prop1=337799 AND p.prop2='KF2Z2TMP4C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=510 AND p.prop1=844128 AND p.prop2='1A' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=511 AND p.prop1=863723 AND p.prop2='SF9R0X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=512 AND p.prop1=511907 AND p.prop2='SSU4B4QRI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=513 AND p.prop1=72152 AND p.prop2='JI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=514 AND p.prop1=57401 AND p.prop2='9U50RC2BH02Q0HF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=515 AND p.prop1=514742 AND p.prop2='CYCSB4E9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=516 AND p.prop1=497558 AND p.prop2='OGCG12102XH4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=517 AND p.prop1=274782 AND p.prop2='XZ3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=518 AND p.prop1=722327 AND p.prop2='WAZU63KHG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=519 AND p.prop1=344167 AND p.prop2='H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=520 AND p.prop1=902029 AND p.prop2='Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=521 AND p.prop1=986051 AND p.prop2='MGF1GC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=522 AND p.prop1=815225 AND p.prop2='SONKJO6I743S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=523 AND p.prop1=494448 AND p.prop2='OLY8ZVS5BKO1Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=524 AND p.prop1=496098 AND p.prop2='NMI5ZCBE9ING5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=525 AND p.prop1=842833 AND p.prop2='T4SLZR4FDWN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=526 AND p.prop1=101869 AND p.prop2='8U7KM3H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=527 AND p.prop1=653393 AND p.prop2='LRIUFSPLIO8WQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=528 AND p.prop1=477532 AND p.prop2='0IZJVS05' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=529 AND p.prop1=663846 AND p.prop2='2EC6OUV8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=530 AND p.prop1=922713 AND p.prop2='ZDSL9VXS34' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=531 AND p.prop1=631594 AND p.prop2='DS3Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=532 AND p.prop1=937700 AND p.prop2='84' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=533 AND p.prop1=620805 AND p.prop2='N5PB2U3C9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=534 AND p.prop1=463913 AND p.prop2='N9JBO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=535 AND p.prop1=128550 AND p.prop2='FMPYX3S8KV1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=536 AND p.prop1=998761 AND p.prop2='PCG7NBEAGP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=537 AND p.prop1=857187 AND p.prop2='1VS7T8CNRCS7E6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=538 AND p.prop1=660784 AND p.prop2='EY5B8115' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=539 AND p.prop1=820509 AND p.prop2='BV2G7L07' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=540 AND p.prop1=619458 AND p.prop2='1Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=541 AND p.prop1=677393 AND p.prop2='Y0SPGCXE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=542 AND p.prop1=566910 AND p.prop2='2PJ7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=543 AND p.prop1=933745 AND p.prop2='6WV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=544 AND p.prop1=553248 AND p.prop2='Z1S7RRCZLU2PJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=545 AND p.prop1=833433 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=546 AND p.prop1=619663 AND p.prop2='I7RO7TBG48BC4P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=547 AND p.prop1=610750 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=548 AND p.prop1=909571 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=549 AND p.prop1=124612 AND p.prop2='S7TM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=550 AND p.prop1=832897 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=551 AND p.prop1=582155 AND p.prop2='QVUK4X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=552 AND p.prop1=220115 AND p.prop2='INBKQYFQHBCB6T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=553 AND p.prop1=485790 AND p.prop2='HF2E6VMA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=554 AND p.prop1=208123 AND p.prop2='N4Q3Y9PME' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=555 AND p.prop1=975960 AND p.prop2='EKDPDG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=556 AND p.prop1=504318 AND p.prop2='UQY0ZHJ5PR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=557 AND p.prop1=484098 AND p.prop2='FT0L' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=558 AND p.prop1=361180 AND p.prop2='P480OEE4RPHZ3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=559 AND p.prop1=332664 AND p.prop2='CFMNQ3TBJE8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=560 AND p.prop1=655321 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=561 AND p.prop1=252209 AND p.prop2='JRWXXPN4661IL0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=562 AND p.prop1=880708 AND p.prop2='01T4X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=563 AND p.prop1=137845 AND p.prop2='VIGJB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=564 AND p.prop1=689023 AND p.prop2='JQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=565 AND p.prop1=575955 AND p.prop2='ML9RT2M69' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=566 AND p.prop1=401573 AND p.prop2='825EZML676' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=567 AND p.prop1=880218 AND p.prop2='IWX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=568 AND p.prop1=204365 AND p.prop2='DS065PZR4T13' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=569 AND p.prop1=22674 AND p.prop2='CYIR6IK6XQ89AYV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=570 AND p.prop1=529449 AND p.prop2='7IBMU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=571 AND p.prop1=61851 AND p.prop2='7CK4Z0S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=572 AND p.prop1=901263 AND p.prop2='P1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=573 AND p.prop1=269222 AND p.prop2='QXVM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=574 AND p.prop1=28913 AND p.prop2='TKWBLZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=575 AND p.prop1=308949 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=576 AND p.prop1=805751 AND p.prop2='ZUX3UB3GAHV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=577 AND p.prop1=662326 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=578 AND p.prop1=60534 AND p.prop2='KWC7BCC3CY0MX2X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=579 AND p.prop1=663639 AND p.prop2='M7SGYXM9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=580 AND p.prop1=836997 AND p.prop2='9J5RQBK6CIM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=581 AND p.prop1=55787 AND p.prop2='JJ9E4YK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=582 AND p.prop1=12736 AND p.prop2='WH9POV76K' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=583 AND p.prop1=280894 AND p.prop2='70' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=584 AND p.prop1=53401 AND p.prop2='1YYZG796' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=585 AND p.prop1=725580 AND p.prop2='CAGKGMTLL4ETTRL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=586 AND p.prop1=119203 AND p.prop2='DW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=587 AND p.prop1=959312 AND p.prop2='30GS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=588 AND p.prop1=612281 AND p.prop2='2G169WGPZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=589 AND p.prop1=765461 AND p.prop2='ECT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=590 AND p.prop1=527992 AND p.prop2='Z5JVXK9FNS1KJFP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=591 AND p.prop1=647029 AND p.prop2='AKO8XFUJUPP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=592 AND p.prop1=971718 AND p.prop2='L' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=593 AND p.prop1=451068 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=594 AND p.prop1=334532 AND p.prop2='ZC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=595 AND p.prop1=463682 AND p.prop2='ICKZ2GT7KL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=596 AND p.prop1=163354 AND p.prop2='5ESUHXG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=597 AND p.prop1=716176 AND p.prop2='1Y0999NI1T0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=598 AND p.prop1=340071 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=599 AND p.prop1=122409 AND p.prop2='3MV7NVBJ89M4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=600 AND p.prop1=397932 AND p.prop2='7VDFR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=601 AND p.prop1=77409 AND p.prop2='UVYCPTLY9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=602 AND p.prop1=963479 AND p.prop2='NW915DJJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=603 AND p.prop1=982421 AND p.prop2='9JDZBJ1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=604 AND p.prop1=230894 AND p.prop2='1S1NQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=605 AND p.prop1=527145 AND p.prop2='22' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=606 AND p.prop1=649454 AND p.prop2='ST58KRS2WN99BBK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=607 AND p.prop1=658253 AND p.prop2='FHINK5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=608 AND p.prop1=608344 AND p.prop2='63U1CTZ6OPZ6HKK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=609 AND p.prop1=165208 AND p.prop2='7YWQVQA4V2RA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=610 AND p.prop1=211633 AND p.prop2='OXMQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=611 AND p.prop1=521526 AND p.prop2='0GGKBW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=612 AND p.prop1=908564 AND p.prop2='493' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=613 AND p.prop1=320421 AND p.prop2='HGP97BUI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=614 AND p.prop1=580404 AND p.prop2='K7PFY1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=615 AND p.prop1=722606 AND p.prop2='K0LL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=616 AND p.prop1=993752 AND p.prop2='LAQOTOS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=617 AND p.prop1=814532 AND p.prop2='DBM1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=618 AND p.prop1=406833 AND p.prop2='8EQ1CGMX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=619 AND p.prop1=307266 AND p.prop2='O4HV7YJOKNNFYP3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=620 AND p.prop1=314958 AND p.prop2='KCZYBLQKMSO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=621 AND p.prop1=770077 AND p.prop2='S0U1NBE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=622 AND p.prop1=139021 AND p.prop2='5IJ7SOR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=623 AND p.prop1=821201 AND p.prop2='7CWKCSZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=624 AND p.prop1=423647 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=625 AND p.prop1=457356 AND p.prop2='SBYNTJ0UVFXNV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=626 AND p.prop1=180780 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=627 AND p.prop1=485065 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=628 AND p.prop1=7308 AND p.prop2='MYX5RJAEPDYQZNG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=629 AND p.prop1=585439 AND p.prop2='66G53' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=630 AND p.prop1=17910 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=631 AND p.prop1=689917 AND p.prop2='GJFQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=632 AND p.prop1=975195 AND p.prop2='NS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=633 AND p.prop1=912502 AND p.prop2='TX97CFNMYE7B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=634 AND p.prop1=861767 AND p.prop2='A7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=635 AND p.prop1=367691 AND p.prop2='OE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=636 AND p.prop1=471435 AND p.prop2='A1JFTND37GL7IK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=637 AND p.prop1=65853 AND p.prop2='GM56G0192WGN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=638 AND p.prop1=389375 AND p.prop2='LP7L' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=639 AND p.prop1=940337 AND p.prop2='Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=640 AND p.prop1=971565 AND p.prop2='H7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=641 AND p.prop1=424219 AND p.prop2='VQG5ZP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=642 AND p.prop1=897483 AND p.prop2='WYJZFZ688HZ7QD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=643 AND p.prop1=399273 AND p.prop2='T8OMDAS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=644 AND p.prop1=478465 AND p.prop2='HRJA2GPX34' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=645 AND p.prop1=344932 AND p.prop2='QM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=646 AND p.prop1=81415 AND p.prop2='X4FGRVTF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=647 AND p.prop1=35230 AND p.prop2='U038' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=648 AND p.prop1=940752 AND p.prop2='BVFEBR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=649 AND p.prop1=172534 AND p.prop2='SR0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=650 AND p.prop1=801151 AND p.prop2='KERHFWKZFQWAAR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=651 AND p.prop1=834460 AND p.prop2='60LFTI4Z0LNLY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=652 AND p.prop1=762961 AND p.prop2='HTFM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=653 AND p.prop1=776237 AND p.prop2='6X9Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=654 AND p.prop1=742897 AND p.prop2='2FDV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=655 AND p.prop1=2174 AND p.prop2='W6C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=656 AND p.prop1=40288 AND p.prop2='3QSTXEP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=657 AND p.prop1=30684 AND p.prop2='EQT4DCM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=658 AND p.prop1=270774 AND p.prop2='GP5IWG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=659 AND p.prop1=558542 AND p.prop2='LANC6U58N2HVSIN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=660 AND p.prop1=98623 AND p.prop2='Y120ZAP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=661 AND p.prop1=491834 AND p.prop2='UBV52THSIP05OC9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=662 AND p.prop1=825245 AND p.prop2='BLJIHD5MZ5Y2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=663 AND p.prop1=457272 AND p.prop2='4O2WT8LQOSUGNY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=664 AND p.prop1=31823 AND p.prop2='1U1FX7K4N8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=665 AND p.prop1=988155 AND p.prop2='P3CRGKRK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=666 AND p.prop1=818499 AND p.prop2='PTFYH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=667 AND p.prop1=619420 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=668 AND p.prop1=743588 AND p.prop2='3CSE0HN41B5D' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=669 AND p.prop1=335215 AND p.prop2='B3HRGRFXX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=670 AND p.prop1=787690 AND p.prop2='ZP1VTQ128MQ8A' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=671 AND p.prop1=787275 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=672 AND p.prop1=114886 AND p.prop2='X7IQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=673 AND p.prop1=394847 AND p.prop2='E89D84I2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=674 AND p.prop1=657583 AND p.prop2='WA2MH4OTH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=675 AND p.prop1=259098 AND p.prop2='5L793QHG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=676 AND p.prop1=188432 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=677 AND p.prop1=381417 AND p.prop2='XDI1TKBEU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=678 AND p.prop1=423183 AND p.prop2='PC5PB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=679 AND p.prop1=105617 AND p.prop2='O1U5BYAFAV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=680 AND p.prop1=383693 AND p.prop2='02FRWM6P4MZT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=681 AND p.prop1=701756 AND p.prop2='I1Y5KU6KIO7YF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=682 AND p.prop1=66313 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=683 AND p.prop1=506104 AND p.prop2='YRWTBOOPZUTO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=684 AND p.prop1=183315 AND p.prop2='3AMSRMY7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=685 AND p.prop1=810041 AND p.prop2='LG3XT9Z42DPFV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=686 AND p.prop1=509411 AND p.prop2='I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=687 AND p.prop1=206801 AND p.prop2='Q5TVG48DM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=688 AND p.prop1=516108 AND p.prop2='TYRYS5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=689 AND p.prop1=340200 AND p.prop2='QG40WYKOHV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=690 AND p.prop1=757478 AND p.prop2='0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=691 AND p.prop1=997613 AND p.prop2='24' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=692 AND p.prop1=305381 AND p.prop2='M0V2BG5Z8O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=693 AND p.prop1=516977 AND p.prop2='5KODUN64LG23' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=694 AND p.prop1=477132 AND p.prop2='SASYKXPAT3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=695 AND p.prop1=778825 AND p.prop2='KEECSWCXQOZY97' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=696 AND p.prop1=475913 AND p.prop2='9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=697 AND p.prop1=60440 AND p.prop2='UCTOT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=698 AND p.prop1=538176 AND p.prop2='GZMHPCM511D' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=699 AND p.prop1=731985 AND p.prop2='Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=700 AND p.prop1=83616 AND p.prop2='SDRMJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=701 AND p.prop1=441868 AND p.prop2='S2EZIQDC9YJ88Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=702 AND p.prop1=783981 AND p.prop2='T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=703 AND p.prop1=963209 AND p.prop2='5U6UTNIT4JVKECN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=704 AND p.prop1=382539 AND p.prop2='AP3ZTXR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=705 AND p.prop1=421761 AND p.prop2='69OQP3NPB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=706 AND p.prop1=562314 AND p.prop2='MLI9UBE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=707 AND p.prop1=871817 AND p.prop2='SA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=708 AND p.prop1=538969 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=709 AND p.prop1=883489 AND p.prop2='1JPZYJJBUWNBE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=710 AND p.prop1=799813 AND p.prop2='NJ6REVV7FXCWOK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=711 AND p.prop1=358179 AND p.prop2='0TUJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=712 AND p.prop1=494492 AND p.prop2='M' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=713 AND p.prop1=123951 AND p.prop2='7XGSN9PDQQQCV1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=714 AND p.prop1=376909 AND p.prop2='53996RZBN0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=715 AND p.prop1=203367 AND p.prop2='YNAFB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=716 AND p.prop1=563140 AND p.prop2='WZFNJJDSIMOL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=717 AND p.prop1=460495 AND p.prop2='PEVIH0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=718 AND p.prop1=480257 AND p.prop2='LR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=719 AND p.prop1=351826 AND p.prop2='CQZEHWJXR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=720 AND p.prop1=502891 AND p.prop2='BNO8NE9M9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=721 AND p.prop1=368942 AND p.prop2='VHR7IQ3OM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=722 AND p.prop1=792731 AND p.prop2='3V1V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=723 AND p.prop1=597183 AND p.prop2='WEYRG35FJVKSRO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=724 AND p.prop1=982499 AND p.prop2='RKJK2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=725 AND p.prop1=252729 AND p.prop2='CG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=726 AND p.prop1=172742 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=727 AND p.prop1=318335 AND p.prop2='770VQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=728 AND p.prop1=707951 AND p.prop2='PJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=729 AND p.prop1=84909 AND p.prop2='0YR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=730 AND p.prop1=826711 AND p.prop2='BU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=731 AND p.prop1=918444 AND p.prop2='O63QJ1042YOR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=732 AND p.prop1=519158 AND p.prop2='UFVTJ6X1YB4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=733 AND p.prop1=587717 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=734 AND p.prop1=69086 AND p.prop2='ZD0SAYZTX3KF82' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=735 AND p.prop1=258411 AND p.prop2='4V07M2B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=736 AND p.prop1=202523 AND p.prop2='RHTX2DYN35P18' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=737 AND p.prop1=593572 AND p.prop2='P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=738 AND p.prop1=81462 AND p.prop2='M9ORT50BZCHZEOE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=739 AND p.prop1=640022 AND p.prop2='02E0EVRN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=740 AND p.prop1=999673 AND p.prop2='EOV9CEDYTL8TX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=741 AND p.prop1=398833 AND p.prop2='JFCOCIMKW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=742 AND p.prop1=213771 AND p.prop2='FFYNXG3HTZO0S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=743 AND p.prop1=275074 AND p.prop2='K70WBHQ4UQJ8SV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=744 AND p.prop1=665203 AND p.prop2='A47EUVRXLY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=745 AND p.prop1=554943 AND p.prop2='NMI9GGKK0E' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=746 AND p.prop1=186041 AND p.prop2='TO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=747 AND p.prop1=451983 AND p.prop2='01OVWIN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=748 AND p.prop1=657035 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=749 AND p.prop1=381292 AND p.prop2='K7W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=750 AND p.prop1=49671 AND p.prop2='QFSNCLRCL04LR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=751 AND p.prop1=886106 AND p.prop2='7GII677G3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=752 AND p.prop1=641157 AND p.prop2='G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=753 AND p.prop1=996771 AND p.prop2='OLSWHSDL19QT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=754 AND p.prop1=69267 AND p.prop2='L4Z8T64AT84V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=755 AND p.prop1=933245 AND p.prop2='G855ASOEI4G00X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=756 AND p.prop1=376822 AND p.prop2='L8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=757 AND p.prop1=711668 AND p.prop2='5H3OE4B6B2TILX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=758 AND p.prop1=611004 AND p.prop2='JC64YI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=759 AND p.prop1=746144 AND p.prop2='G4UHD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=760 AND p.prop1=288194 AND p.prop2='KMRVJC2S0DS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=761 AND p.prop1=220689 AND p.prop2='W63' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=762 AND p.prop1=420641 AND p.prop2='K7C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=763 AND p.prop1=86384 AND p.prop2='CL0SZFB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=764 AND p.prop1=92112 AND p.prop2='F1BTQ5Q5EP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=765 AND p.prop1=601052 AND p.prop2='NSCXOF9DTH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=766 AND p.prop1=297671 AND p.prop2='R6KOXN2QH5RV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=767 AND p.prop1=306986 AND p.prop2='UKRCTXT431D22MK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=768 AND p.prop1=118651 AND p.prop2='AZ9QS18BIW6E1SZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=769 AND p.prop1=387713 AND p.prop2='3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=770 AND p.prop1=698874 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=771 AND p.prop1=596451 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=772 AND p.prop1=954553 AND p.prop2='37WG2GFM8L8FHH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=773 AND p.prop1=846094 AND p.prop2='C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=774 AND p.prop1=40265 AND p.prop2='5B05UFXMG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=775 AND p.prop1=500960 AND p.prop2='41Y2ZTOCWXPD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=776 AND p.prop1=777913 AND p.prop2='9AHJUTDVR0L6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=777 AND p.prop1=340617 AND p.prop2='1CLE8V88' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=778 AND p.prop1=424418 AND p.prop2='GEVJFCPBVD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=779 AND p.prop1=980271 AND p.prop2='F9MWWQPKV63' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=780 AND p.prop1=26548 AND p.prop2='XS9E' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=781 AND p.prop1=128345 AND p.prop2='AGAA4T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=782 AND p.prop1=479646 AND p.prop2='BWX5F9I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=783 AND p.prop1=712445 AND p.prop2='YS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=784 AND p.prop1=142387 AND p.prop2='V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=785 AND p.prop1=13253 AND p.prop2='FIJ7PCOULO1AN0J' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=786 AND p.prop1=943609 AND p.prop2='19WGIAQ0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=787 AND p.prop1=535048 AND p.prop2='B0N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=788 AND p.prop1=86106 AND p.prop2='4DLQGYR6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=789 AND p.prop1=142878 AND p.prop2='0BOR4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=790 AND p.prop1=516507 AND p.prop2='K3XGN2JSZRO9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=791 AND p.prop1=598999 AND p.prop2='BDBPGQ1U7Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=792 AND p.prop1=224533 AND p.prop2='RBGRZW5EEH9FDP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=793 AND p.prop1=800314 AND p.prop2='7DX8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=794 AND p.prop1=349555 AND p.prop2='G85UM9PA2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=795 AND p.prop1=878647 AND p.prop2='1F09F74A332W' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=796 AND p.prop1=244396 AND p.prop2='8429C3T3U4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=797 AND p.prop1=65403 AND p.prop2='CMM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=798 AND p.prop1=548098 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=799 AND p.prop1=303757 AND p.prop2='CU21BVEUQQFB1O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=800 AND p.prop1=921695 AND p.prop2='SA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=801 AND p.prop1=563745 AND p.prop2='8HUO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=802 AND p.prop1=552974 AND p.prop2='IL11BB3T7V6IUNH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=803 AND p.prop1=2186 AND p.prop2='OTPWGZTWIMBN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=804 AND p.prop1=51293 AND p.prop2='AACC1ZBLM2L19F' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=805 AND p.prop1=700205 AND p.prop2='T0LRDX9S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=806 AND p.prop1=511169 AND p.prop2='5F99T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=807 AND p.prop1=529986 AND p.prop2='1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=808 AND p.prop1=654160 AND p.prop2='9DRVVZE906' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=809 AND p.prop1=931149 AND p.prop2='78P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=810 AND p.prop1=309101 AND p.prop2='51' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=811 AND p.prop1=555070 AND p.prop2='U1HFT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=812 AND p.prop1=600385 AND p.prop2='QX6U31M1QMYPUPA' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=813 AND p.prop1=701572 AND p.prop2='UX30OLTU1659' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=814 AND p.prop1=838526 AND p.prop2='GSNTP8M2AJ85R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=815 AND p.prop1=129752 AND p.prop2='0N1S1DGB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=816 AND p.prop1=621945 AND p.prop2='NQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=817 AND p.prop1=740537 AND p.prop2='44AZ9NSFZ9TPPK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=818 AND p.prop1=736123 AND p.prop2='TTSVN7Z1ISXFH0' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=819 AND p.prop1=357503 AND p.prop2='02HT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=820 AND p.prop1=424125 AND p.prop2='BHO9NBW9TWP5YXD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=821 AND p.prop1=244340 AND p.prop2='97VKPEO2FRFV' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=822 AND p.prop1=226752 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=823 AND p.prop1=134643 AND p.prop2='D' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=824 AND p.prop1=783729 AND p.prop2='SGUF4LX1QLMWI0V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=825 AND p.prop1=896228 AND p.prop2='SJ6XEQJJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=826 AND p.prop1=537378 AND p.prop2='37QQU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=827 AND p.prop1=737328 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=828 AND p.prop1=178385 AND p.prop2='OVEJISHGIS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=829 AND p.prop1=225648 AND p.prop2='Z44N4C37WIM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=830 AND p.prop1=969182 AND p.prop2='35U716IRE3ZI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=831 AND p.prop1=57539 AND p.prop2='RUM9CZ8C9T' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=832 AND p.prop1=362577 AND p.prop2='8AL9O6V9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=833 AND p.prop1=850019 AND p.prop2='U4ISQ2M' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=834 AND p.prop1=366493 AND p.prop2='GJTG1090' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=835 AND p.prop1=664823 AND p.prop2='27QARXGXWD7U' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=836 AND p.prop1=816428 AND p.prop2='D3ZLWVYU2M' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=837 AND p.prop1=791917 AND p.prop2='KAWX07' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=838 AND p.prop1=871307 AND p.prop2='O93B37PUR1W6V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=839 AND p.prop1=19798 AND p.prop2='E57DS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=840 AND p.prop1=993995 AND p.prop2='H06X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=841 AND p.prop1=108359 AND p.prop2='MCYVTOO27IXHI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=842 AND p.prop1=750748 AND p.prop2='11N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=843 AND p.prop1=848806 AND p.prop2='9KBWJF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=844 AND p.prop1=656421 AND p.prop2='2PUJ8E1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=845 AND p.prop1=605980 AND p.prop2='3HJNFYX69TB7T92' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=846 AND p.prop1=455177 AND p.prop2='OFJ6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=847 AND p.prop1=569235 AND p.prop2='4VXI43OWKQI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=848 AND p.prop1=986151 AND p.prop2='9ME' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=849 AND p.prop1=154108 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=850 AND p.prop1=512450 AND p.prop2='3P4FQMR4EAZT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=851 AND p.prop1=209608 AND p.prop2='FD3D1HDCO5Y' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=852 AND p.prop1=960608 AND p.prop2='6WDRM82HWPALMHT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=853 AND p.prop1=129314 AND p.prop2='EWGY5114QT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=854 AND p.prop1=500752 AND p.prop2='PG90R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=855 AND p.prop1=24402 AND p.prop2='AXWARMMRP2K399' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=856 AND p.prop1=702032 AND p.prop2='K13IC25' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=857 AND p.prop1=914596 AND p.prop2='4N81T98Q93Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=858 AND p.prop1=975164 AND p.prop2='E54Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=859 AND p.prop1=854602 AND p.prop2='5GWIJXQ14K09J' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=860 AND p.prop1=523133 AND p.prop2='WAYR5E9' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=861 AND p.prop1=926343 AND p.prop2='MJQUO4PLZIYNJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=862 AND p.prop1=890503 AND p.prop2='7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=863 AND p.prop1=995293 AND p.prop2='QT87C106F' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=864 AND p.prop1=785377 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=865 AND p.prop1=756958 AND p.prop2='5A' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=866 AND p.prop1=684842 AND p.prop2='H70W6O5JCX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=867 AND p.prop1=426304 AND p.prop2='Y7ZW5K' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=868 AND p.prop1=780935 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=869 AND p.prop1=508374 AND p.prop2='VTEB8Q18WH7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=870 AND p.prop1=996890 AND p.prop2='W91T3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=871 AND p.prop1=8478 AND p.prop2='M5B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=872 AND p.prop1=609868 AND p.prop2='ZN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=873 AND p.prop1=965508 AND p.prop2='XBG3BA9K0UR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=874 AND p.prop1=671190 AND p.prop2='AOF7ISB86H' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=875 AND p.prop1=386538 AND p.prop2='TC5W5WRB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=876 AND p.prop1=116460 AND p.prop2='X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=877 AND p.prop1=323899 AND p.prop2='X32' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=878 AND p.prop1=620732 AND p.prop2='JNY4JDOZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=879 AND p.prop1=562987 AND p.prop2='1OVOY7AQEAYZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=880 AND p.prop1=191373 AND p.prop2='ME' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=881 AND p.prop1=747843 AND p.prop2='TVO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=882 AND p.prop1=501433 AND p.prop2='5D9H97ZAOB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=883 AND p.prop1=88673 AND p.prop2='JFCBF3A4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=884 AND p.prop1=843877 AND p.prop2='GS7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=885 AND p.prop1=642427 AND p.prop2='9LPS2P6N' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=886 AND p.prop1=428839 AND p.prop2='YMT2WYIJ24' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=887 AND p.prop1=497354 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=888 AND p.prop1=456975 AND p.prop2='O6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=889 AND p.prop1=783910 AND p.prop2='I' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=890 AND p.prop1=465047 AND p.prop2='S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=891 AND p.prop1=380378 AND p.prop2='A5YRTK8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=892 AND p.prop1=101821 AND p.prop2='E55WLB9DI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=893 AND p.prop1=310362 AND p.prop2='CAGO0U6X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=894 AND p.prop1=301984 AND p.prop2='45JNC9OS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=895 AND p.prop1=940856 AND p.prop2='MG3AQP5IVN' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=896 AND p.prop1=521565 AND p.prop2='21H2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=897 AND p.prop1=404063 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=898 AND p.prop1=631401 AND p.prop2='YBW366' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=899 AND p.prop1=126126 AND p.prop2='43' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=900 AND p.prop1=99716 AND p.prop2='3YGUAG3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=901 AND p.prop1=422743 AND p.prop2='34IHAC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=902 AND p.prop1=601542 AND p.prop2='PKBXCR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=903 AND p.prop1=360555 AND p.prop2='0ITJBWCPJQS6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=904 AND p.prop1=898384 AND p.prop2='AQ9RB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=905 AND p.prop1=267187 AND p.prop2='7ODNS' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=906 AND p.prop1=528232 AND p.prop2='ZXVUIN0UCQ8NEV7' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=907 AND p.prop1=826422 AND p.prop2='Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=908 AND p.prop1=972155 AND p.prop2='5CGRS1FWDSCJ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=909 AND p.prop1=840127 AND p.prop2='MN7JX' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=910 AND p.prop1=846332 AND p.prop2='QSIAE8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=911 AND p.prop1=881706 AND p.prop2='B3881X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=912 AND p.prop1=427532 AND p.prop2='GB7Q2V60' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=913 AND p.prop1=784307 AND p.prop2='5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=914 AND p.prop1=372206 AND p.prop2='D' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=915 AND p.prop1=339800 AND p.prop2='S6JK3EF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=916 AND p.prop1=363202 AND p.prop2='U' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=917 AND p.prop1=267686 AND p.prop2='FYF88E4U0B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=918 AND p.prop1=201851 AND p.prop2='JE7XOI29FQM09L' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=919 AND p.prop1=480833 AND p.prop2='N83DEQVTIKZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=920 AND p.prop1=756133 AND p.prop2='JLO1Q7LGE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=921 AND p.prop1=649633 AND p.prop2='DKTNO1VX8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=922 AND p.prop1=655840 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=923 AND p.prop1=656130 AND p.prop2='NAGHE9JAOMDC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=924 AND p.prop1=644337 AND p.prop2='W8DD5BUHVIOFKP5' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=925 AND p.prop1=831648 AND p.prop2='UW' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=926 AND p.prop1=519354 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=927 AND p.prop1=616041 AND p.prop2='J' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=928 AND p.prop1=857213 AND p.prop2='X' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=929 AND p.prop1=572213 AND p.prop2='C8C9OAPYKTG5W0O' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=930 AND p.prop1=778226 AND p.prop2='Q2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=931 AND p.prop1=462618 AND p.prop2='7RDWAPXYCQYYCPB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=932 AND p.prop1=735572 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=933 AND p.prop1=218169 AND p.prop2='P14JQLDK' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=934 AND p.prop1=62947 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=935 AND p.prop1=239560 AND p.prop2='MQMK9O9CVCT70BI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=936 AND p.prop1=65970 AND p.prop2='V02ZC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=937 AND p.prop1=356524 AND p.prop2='1VJKUYDZNSM6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=938 AND p.prop1=971643 AND p.prop2='FPSE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=939 AND p.prop1=507539 AND p.prop2='8V3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=940 AND p.prop1=179675 AND p.prop2='0RK2GBPR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=941 AND p.prop1=718372 AND p.prop2='IAERU8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=942 AND p.prop1=758098 AND p.prop2='TCO7QJG' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=943 AND p.prop1=604562 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=944 AND p.prop1=982789 AND p.prop2='QW1NCJXVI9C4R7U' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=945 AND p.prop1=207852 AND p.prop2='LQD1' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=946 AND p.prop1=878586 AND p.prop2='HG4Z3YVTT0C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=947 AND p.prop1=350952 AND p.prop2='OOU4AXKG556' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=948 AND p.prop1=73189 AND p.prop2='U' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=949 AND p.prop1=929891 AND p.prop2='59CW2ZB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=950 AND p.prop1=963585 AND p.prop2='I7T6RBX6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=951 AND p.prop1=243195 AND p.prop2='G' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=952 AND p.prop1=591486 AND p.prop2='XV9D165HP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=953 AND p.prop1=203722 AND p.prop2='02' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=954 AND p.prop1=226465 AND p.prop2='3C6' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=955 AND p.prop1=656275 AND p.prop2='LKMXV9O8K16S' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=956 AND p.prop1=785509 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=957 AND p.prop1=613976 AND p.prop2='2B' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=958 AND p.prop1=972995 AND p.prop2='3R7GN0QJRC' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=959 AND p.prop1=982973 AND p.prop2='C' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=960 AND p.prop1=6846 AND p.prop2='XI07C4FBY5JZ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=961 AND p.prop1=219163 AND p.prop2='VCLB' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=962 AND p.prop1=410246 AND p.prop2='5GL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=963 AND p.prop1=667818 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=964 AND p.prop1=181234 AND p.prop2='4JD27PRH7TAS4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=965 AND p.prop1=226227 AND p.prop2='G3MRK548P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=966 AND p.prop1=578961 AND p.prop2='V4E8' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=967 AND p.prop1=730591 AND p.prop2='MFBJGE1EQA4' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=968 AND p.prop1=530830 AND p.prop2='287' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=969 AND p.prop1=573394 AND p.prop2='XVLQR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=970 AND p.prop1=696688 AND p.prop2='GSNC8NECI' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=971 AND p.prop1=399414 AND p.prop2='B2OXLY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=972 AND p.prop1=496931 AND p.prop2='X4GWEK2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=973 AND p.prop1=85364 AND p.prop2='CVTRC9KE3DO5R' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=974 AND p.prop1=133669 AND p.prop2='W5SC58VFVJY' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=975 AND p.prop1=760240 AND p.prop2='9ESG02FEMMVA9Q' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=976 AND p.prop1=781824 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=977 AND p.prop1=700768 AND p.prop2='TL' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=978 AND p.prop1=884081 AND p.prop2='2Z8MXJRFF2GRSQ' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=979 AND p.prop1=992748 AND p.prop2='I8VVND4BR' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=980 AND p.prop1=941454 AND p.prop2='1IHFOVBVE' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=981 AND p.prop1=323230 AND p.prop2='6N2' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=982 AND p.prop1=569611 AND p.prop2='NMQTDO' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=983 AND p.prop1=333298 AND p.prop2='T1MQEIRH' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=984 AND p.prop1=890940 AND p.prop2='RYIHT385J' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=985 AND p.prop1=244687 AND p.prop2='7B6LAD' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=986 AND p.prop1=175180 AND p.prop2='07P' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=987 AND p.prop1=523195 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=988 AND p.prop1=214723 AND p.prop2='A9KVESQ587U' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=989 AND p.prop1=891945 AND p.prop2='Y3L307KPRDJ4WR3' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=990 AND p.prop1=550035 AND p.prop2='L7X67G4QY4V' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=991 AND p.prop1=424124 AND p.prop2='1OF523OWP' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=992 AND p.prop1=104646 AND p.prop2='' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=993 AND p.prop1=765752 AND p.prop2='PSU21N9YV5KT' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=994 AND p.prop1=649873 AND p.prop2='I1PEA8K' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=995 AND p.prop1=959449 AND p.prop2='ZAUL7LERRJU' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=996 AND p.prop1=752360 AND p.prop2='WJF' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=997 AND p.prop1=661157 AND p.prop2='FAUWJ055ZSM' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=998 AND p.prop1=708876 AND p.prop2='M4UGSLZLSQ257Z' DELETE p; ----- ok --STATEMENT MATCH (p:Person) WHERE p.id=999 AND p.prop1=375732 AND p.prop2='84' DELETE p; ----- ok --STATEMENT MATCH () RETURN COUNT(*) ----- 1 -0 --STATEMENT MATCH ()-[]->() RETURN COUNT(*) ----- 1 -0 diff --git a/test/include/graph_test/base_graph_test.h b/test/include/graph_test/base_graph_test.h index 3e099137aa9..e129cceefc0 100644 --- a/test/include/graph_test/base_graph_test.h +++ b/test/include/graph_test/base_graph_test.h @@ -101,17 +101,17 @@ class BaseGraphTest : public Test { static inline main::ClientContext* getClientContext(main::Connection& connection) { return connection.clientContext.get(); } - static inline void sortAndCheckTestResults( - std::vector& actualResult, std::vector& expectedResult) { + static inline void sortAndCheckTestResults(std::vector& actualResult, + std::vector& expectedResult) { sort(expectedResult.begin(), expectedResult.end()); ASSERT_EQ(actualResult, expectedResult); } static inline bool containsOverflowFile(common::LogicalTypeID typeID) { - return typeID == common::LogicalTypeID::STRING || typeID == common::LogicalTypeID::VAR_LIST; + return typeID == common::LogicalTypeID::STRING || typeID == common::LogicalTypeID::LIST; } - void commitOrRollbackConnectionAndInitDBIfNecessary( - bool isCommit, TransactionTestType transactionTestType); + void commitOrRollbackConnectionAndInitDBIfNecessary(bool isCommit, + TransactionTestType transactionTestType); inline std::string getTestGroupAndName() { const ::testing::TestInfo* const testInfo = diff --git a/test/include/test_helper/test_helper.h b/test/include/test_helper/test_helper.h index 1c95e26b823..e62911719cf 100644 --- a/test/include/test_helper/test_helper.h +++ b/test/include/test_helper/test_helper.h @@ -27,11 +27,11 @@ class TestHelper { static constexpr char TEST_STATEMENTS_PATH[] = "test/statements"; static constexpr char DEFAULT_CONN_NAME[] = "conn_default"; - static std::vector> parseTestFile( - const std::string& path, bool checkOutputOrder = false); + static std::vector> parseTestFile(const std::string& path, + bool checkOutputOrder = false); - static std::vector convertResultToString( - main::QueryResult& queryResult, bool checkOutputOrder = false); + static std::vector convertResultToString(main::QueryResult& queryResult, + bool checkOutputOrder = false); static void executeScript(const std::string& path, main::Connection& conn); diff --git a/test/include/test_runner/csv_to_parquet_converter.h b/test/include/test_runner/csv_to_parquet_converter.h index 9a2fe671142..0eeae9144de 100644 --- a/test/include/test_runner/csv_to_parquet_converter.h +++ b/test/include/test_runner/csv_to_parquet_converter.h @@ -2,6 +2,8 @@ #include #include +#include "main/kuzu.h" + namespace kuzu { namespace testing { @@ -9,41 +11,51 @@ namespace testing { // The dataset directory must contain schema and copy files. class CSVToParquetConverter { public: - static std::string convertCSVDatasetToParquet( - const std::string& csvDatasetPath, const std::string& parquetDatasetPath); + explicit CSVToParquetConverter(std::string csvDatasetPath, std::string parquetDatasetPath, + uint64_t bufferPoolSize) + : csvDatasetPath{csvDatasetPath}, parquetDatasetPath{parquetDatasetPath}, + bufferPoolSize{bufferPoolSize} {} + + void convertCSVDatasetToParquet(); - inline static std::string replaceSlashesWithUnderscores(std::string dataset) { - std::replace(dataset.begin(), dataset.end(), '/', '_'); - return dataset; - } +private: + void copySchemaFile(); + void createTableInfo(std::string schemaFile); + void readCopyCommandsFromCSVDataset(); + void createCopyFile(); + void convertCSVFilesToParquet(); private: - struct CopyCommandInfo { - std::string table; + struct TableInfo { + std::string name; std::string csvFilePath; std::string parquetFilePath; - bool csvHasHeader; - char delimiter; + // get cypher query to convert csv file to parquet file + virtual std::string getConverterQuery() const = 0; }; - static std::vector readCopyCommandsFromCopyCypherFile( - const std::string& csvDatasetPath, const std::string& parquetDatasetPath); - - static void convertCSVFilesToParquet( - const std::vector& copyCommands); - - static CopyCommandInfo createCopyCommandInfo( - const std::string& parquetDatasetPath, std::string copyStatement); - - // TODO: This has to be re-implemented to not rely on arrow, instead of on our own parquet lib. - // static arrow::Status runCSVToParquetConversion(const std::string& inputFile, - // const std::string& outputFile, char delimiter, bool hasHeader); + struct NodeTableInfo final : public TableInfo { + std::string primaryKey; + // get converter query for node table + std::string getConverterQuery() const override; + }; - static void copySchema( - const std::string& csvDatasetPath, const std::string& parquetDatasetPath); + struct RelTableInfo final : public TableInfo { + std::shared_ptr fromTable; + std::shared_ptr toTable; + // get converter query for rel table + std::string getConverterQuery() const override; + }; - static void createCopyFile(const std::string& parquetDatasetPath, - const std::vector& copyCommands); +private: + std::string csvDatasetPath; + std::string parquetDatasetPath; + std::vector> tables; + std::unordered_map> tableNameMap; + uint64_t bufferPoolSize; + std::unique_ptr systemConfig; + std::unique_ptr tempDb; + std::unique_ptr tempConn; }; } // namespace testing diff --git a/test/include/test_runner/test_parser.h b/test/include/test_runner/test_parser.h index c9214c0bc90..297d54cb6b9 100644 --- a/test/include/test_runner/test_parser.h +++ b/test/include/test_runner/test_parser.h @@ -16,8 +16,6 @@ enum class TokenType { SKIP_MUSL, SKIP_32BIT, // body - BEGIN_READ_ONLY_TRANSACTION, - BEGIN_WRITE_TRANSACTION, BUFFER_POOL_SIZE, CASE, CHECK_ORDER, @@ -52,13 +50,10 @@ const std::unordered_map tokenMap = {{"-GROUP", TokenTyp {"-DATASET", TokenType::DATASET}, {"-CASE", TokenType::CASE}, {"-COMMIT", TokenType::COMMIT}, {"-CHECK_ORDER", TokenType::CHECK_ORDER}, {"-ENCODED_JOIN", TokenType::ENCODED_JOIN}, {"-LOG", TokenType::LOG}, {"-DEFINE_STATEMENT_BLOCK", TokenType::DEFINE_STATEMENT_BLOCK}, - {"-ENUMERATE", TokenType::ENUMERATE}, - {"-BEGIN_WRITE_TRANSACTION", TokenType::BEGIN_WRITE_TRANSACTION}, - {"-BEGIN_READ_ONLY_TRANSACTION", TokenType::BEGIN_READ_ONLY_TRANSACTION}, - {"-PARALLELISM", TokenType::PARALLELISM}, {"-SKIP", TokenType::SKIP}, - {"-SKIP_MUSL", TokenType::SKIP_MUSL}, {"-SKIP_LINE", TokenType::DEFINE}, - {"-SKIP_32BIT", TokenType::SKIP_32BIT}, {"-DEFINE", TokenType::DEFINE}, - {"-STATEMENT", TokenType::STATEMENT}, + {"-ENUMERATE", TokenType::ENUMERATE}, {"-PARALLELISM", TokenType::PARALLELISM}, + {"-SKIP", TokenType::SKIP}, {"-SKIP_MUSL", TokenType::SKIP_MUSL}, + {"-SKIP_LINE", TokenType::DEFINE}, {"-SKIP_32BIT", TokenType::SKIP_32BIT}, + {"-DEFINE", TokenType::DEFINE}, {"-STATEMENT", TokenType::STATEMENT}, {"-INSERT_STATEMENT_BLOCK", TokenType::INSERT_STATEMENT_BLOCK}, {"-ROLLBACK", TokenType::ROLLBACK}, {"-BUFFER_POOL_SIZE", TokenType::BUFFER_POOL_SIZE}, {"-CHECKPOINT_WAIT_TIMEOUT", TokenType::CHECKPOINT_WAIT_TIMEOUT}, @@ -130,8 +125,8 @@ class TestParser { inline std::string getParam(int paramIdx) { return currentToken.params[paramIdx]; } - TestStatement* extractStatement( - TestStatement* currentStatement, const std::string& testCaseName); + TestStatement* extractStatement(TestStatement* currentStatement, + const std::string& testCaseName); TestStatement* addNewStatement(std::string& name); const std::string exportDBPath = TestHelper::appendKuzuRootPath( diff --git a/test/include/test_runner/test_runner.h b/test/include/test_runner/test_runner.h index cc3696d1fdf..ad8c1168541 100644 --- a/test/include/test_runner/test_runner.h +++ b/test/include/test_runner/test_runner.h @@ -8,21 +8,21 @@ namespace testing { class TestRunner { public: - static void runTest( - TestStatement* statement, main::Connection& conn, std::string& databasePath); + static void runTest(TestStatement* statement, main::Connection& conn, + std::string& databasePath); - static std::unique_ptr getLogicalPlan( - const std::string& query, main::Connection& conn); + static std::unique_ptr getLogicalPlan(const std::string& query, + main::Connection& conn); private: - static bool testStatement( - TestStatement* statement, main::Connection& conn, std::string& databasePath); + static bool testStatement(TestStatement* statement, main::Connection& conn, + std::string& databasePath); static bool checkLogicalPlans(std::unique_ptr& preparedStatement, TestStatement* statement, main::Connection& conn); static bool checkLogicalPlan(std::unique_ptr& preparedStatement, TestStatement* statement, main::Connection& conn, uint32_t planIdx); - static std::vector convertResultToString( - main::QueryResult& queryResult, bool checkOutputOrder = false); + static std::vector convertResultToString(main::QueryResult& queryResult, + bool checkOutputOrder = false); static std::string convertResultToMD5Hash(main::QueryResult& queryResult, bool checkOutputOrder); // returns hash and number of values hashed static bool checkPlanResult(std::unique_ptr& result, diff --git a/test/main/connection_test.cpp b/test/main/connection_test.cpp index d7bda29f578..8a6538b19b1 100644 --- a/test/main/connection_test.cpp +++ b/test/main/connection_test.cpp @@ -114,10 +114,18 @@ TEST_F(ApiTest, MultipleQuery) { "MATCH (a:person) RETURN a.fName; MATCH (a:person)-[:knows]->(b:person) RETURN count(*);"); ASSERT_TRUE(result->isSuccess()); - result = - conn->query("CREATE NODE TABLE N(ID INT64, PRIMARY KEY(ID));CREATE REL TABLE E(FROM N TO " - "N, MANY_MANY);MATCH (a:N)-[:E]->(b:N) WHERE a.ID = 0 return b.ID;"); + result = conn->query("CREATE NODE TABLE Test(name STRING, age INT64, PRIMARY KEY(name));CREATE " + "(:Test {name: 'Alice', age: 25});" + "MATCH (a:Test) where a.name='Alice' return a.age;"); + ASSERT_TRUE(result->isSuccess()); + + result = conn->query("return 1; return 2; return 3;"); ASSERT_TRUE(result->isSuccess()); + ASSERT_EQ(result->toString(), "1\n1\n"); + ASSERT_TRUE(result->hasNextQueryResult()); + ASSERT_EQ(result->getNextQueryResult()->toString(), "2\n2\n"); + ASSERT_TRUE(result->hasNextQueryResult()); + ASSERT_EQ(result->getNextQueryResult()->toString(), "3\n3\n"); } TEST_F(ApiTest, Prepare) { diff --git a/test/main/db_locking_test.cpp b/test/main/db_locking_test.cpp index 14d1489f3f6..95cc94ef348 100644 --- a/test/main/db_locking_test.cpp +++ b/test/main/db_locking_test.cpp @@ -13,8 +13,8 @@ class DBLockingTest : public ApiTest { }; TEST_F(DBLockingTest, testReadLock) { - uint64_t* count = (uint64_t*)mmap( - NULL, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); + uint64_t* count = (uint64_t*)mmap(NULL, sizeof(uint64_t), PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED, 0, 0); *count = 0; // create db EXPECT_NO_THROW(createDBAndConn()); @@ -52,8 +52,8 @@ TEST_F(DBLockingTest, testReadLock) { } TEST_F(DBLockingTest, testWriteLock) { - uint64_t* count = (uint64_t*)mmap( - NULL, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); + uint64_t* count = (uint64_t*)mmap(NULL, sizeof(uint64_t), PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED, 0, 0); *count = 0; // test write lock // fork away a child @@ -94,8 +94,8 @@ TEST_F(DBLockingTest, testWriteLock) { } TEST_F(DBLockingTest, testReadOnly) { - uint64_t* count = (uint64_t*)mmap( - NULL, sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); + uint64_t* count = (uint64_t*)mmap(NULL, sizeof(uint64_t), PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED, 0, 0); *count = 0; // cannot create a read-only database in a new directory systemConfig->readOnly = true; diff --git a/test/main/prepare_test.cpp b/test/main/prepare_test.cpp index d393233934e..3886b23db7e 100644 --- a/test/main/prepare_test.cpp +++ b/test/main/prepare_test.cpp @@ -7,6 +7,48 @@ static void checkTuple(kuzu::processor::FlatTuple* tuple, const std::string& gro ASSERT_STREQ(tuple->toString().c_str(), groundTruth.c_str()); } +TEST_F(ApiTest, issueTest1) { + conn->query("CREATE NODE TABLE T(id SERIAL, name STRING, PRIMARY KEY(id));"); + conn->query("CREATE (t:T {name: \"foo\"});"); + auto preparedStatement = conn->prepare("MATCH (t:T {id: $p}) return t.name;"); + auto result = conn->execute(preparedStatement.get(), std::make_pair(std::string("p"), 0)); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "foo\n"); + ASSERT_FALSE(result->hasNext()); +} + +TEST_F(ApiTest, issueTest2) { + conn->query("CREATE NODE TABLE NodeOne(id INT64, name STRING, PRIMARY KEY(id));"); + conn->query("CREATE NODE TABLE NodeTwo(id INT64, name STRING, PRIMARY KEY(id));"); + conn->query("CREATE Rel TABLE RelA(from NodeOne to NodeOne);"); + conn->query("CREATE Rel TABLE RelB(from NodeTwo to NodeOne, name String);"); + conn->query("CREATE (t: NodeOne {id:1, name: \"Alice\"});"); + conn->query("CREATE (t: NodeOne {id:2, name: \"Jack\"});"); + conn->query("CREATE (t: NodeTwo {id:3, name: \"Bob\"});"); + auto preparedStatement = conn->prepare("MATCH (a:NodeOne { id: $a_id })," + "(b:NodeTwo { id: $b_id })," + "(c: NodeOne{ id: $c_id } )" + " MERGE" + " (a)-[:RelA]->(c)," + " (b)-[r:RelB { name: $my_param }]->(c)" + " return r.name;"); + auto result = conn->execute(preparedStatement.get(), std::make_pair(std::string("a_id"), 1), + std::make_pair(std::string("b_id"), 3), std::make_pair(std::string("c_id"), 2), + std::make_pair(std::string("my_param"), "friend")); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "friend\n"); + ASSERT_FALSE(result->hasNext()); +} + +TEST_F(ApiTest, issueTest) { + auto preparedStatement = conn->prepare("RETURN $1 + 1;"); + auto result = + conn->execute(preparedStatement.get(), std::make_pair(std::string("1"), (int8_t)1)); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "2\n"); + ASSERT_FALSE(result->hasNext()); +} + TEST_F(ApiTest, MultiParamsPrepare) { auto preparedStatement = conn->prepare( "MATCH (a:person) WHERE a.fName STARTS WITH $n OR a.fName CONTAINS $xx RETURN COUNT(*)"); @@ -57,8 +99,8 @@ TEST_F(ApiTest, PrepareString) { TEST_F(ApiTest, PrepareDate) { auto preparedStatement = conn->prepare("MATCH (a:person) WHERE a.birthdate = $n RETURN COUNT(*)"); - auto result = conn->execute( - preparedStatement.get(), std::make_pair(std::string("n"), Date::fromDate(1900, 1, 1))); + auto result = conn->execute(preparedStatement.get(), + std::make_pair(std::string("n"), Date::fromDate(1900, 1, 1))); ASSERT_TRUE(result->hasNext()); checkTuple(result->getNext().get(), "2\n"); ASSERT_FALSE(result->hasNext()); @@ -81,8 +123,8 @@ TEST_F(ApiTest, PrepareInterval) { conn->prepare("MATCH (a:person) WHERE a.lastJobDuration = $n RETURN COUNT(*)"); std::string intervalStr = "3 years 2 days 13 hours 2 minutes"; auto result = conn->execute(preparedStatement.get(), - std::make_pair( - std::string("n"), Interval::fromCString(intervalStr.c_str(), intervalStr.length()))); + std::make_pair(std::string("n"), + Interval::fromCString(intervalStr.c_str(), intervalStr.length()))); ASSERT_TRUE(result->hasNext()); checkTuple(result->getNext().get(), "2\n"); ASSERT_FALSE(result->hasNext()); @@ -96,9 +138,8 @@ TEST_F(ApiTest, PrepareDefaultParam) { ASSERT_FALSE(result->hasNext()); preparedStatement = conn->prepare("RETURN size($1)"); result = conn->execute(preparedStatement.get(), std::make_pair(std::string("1"), 1)); - ASSERT_FALSE(result->isSuccess()); - ASSERT_STREQ( - result->getErrorMessage().c_str(), "Parameter 1 has data type INT32 but expects STRING."); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "1\n"); } TEST_F(ApiTest, PrepareDefaultListParam) { @@ -109,8 +150,8 @@ TEST_F(ApiTest, PrepareDefaultListParam) { checkTuple(result->getNext().get(), "[1,1]\n"); result = conn->execute(preparedStatement.get(), std::make_pair(std::string("1"), "as")); ASSERT_FALSE(result->isSuccess()); - ASSERT_STREQ( - result->getErrorMessage().c_str(), "Parameter 1 has data type STRING but expects INT64."); + ASSERT_STREQ(result->getErrorMessage().c_str(), + "Binder exception: Cannot bind LIST_CREATION with parameter type INT64 and STRING."); preparedStatement = conn->prepare("RETURN [$1]"); result = conn->execute(preparedStatement.get(), std::make_pair(std::string("1"), "as")); ASSERT_TRUE(result->hasNext()); @@ -127,9 +168,9 @@ TEST_F(ApiTest, PrepareDefaultStructParam) { ASSERT_TRUE(result->hasNext()); checkTuple(result->getNext().get(), "{a: 10}\n"); result = conn->execute(preparedStatement.get(), std::make_pair(std::string("1"), 1)); - ASSERT_FALSE(result->isSuccess()); - ASSERT_STREQ( - result->getErrorMessage().c_str(), "Parameter 1 has data type INT32 but expects STRING."); + ASSERT_TRUE(result->isSuccess()); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "{a: 1}\n"); } TEST_F(ApiTest, PrepareDefaultMapParam) { @@ -170,9 +211,8 @@ TEST_F(ApiTest, ParamTypeError) { conn->prepare("MATCH (a:person) WHERE a.fName STARTS WITH $n RETURN COUNT(*)"); auto result = conn->execute(preparedStatement.get(), std::make_pair(std::string("n"), (int64_t)36)); - ASSERT_FALSE(result->isSuccess()); - ASSERT_STREQ( - "Parameter n has data type INT64 but expects STRING.", result->getErrorMessage().c_str()); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "0\n"); } TEST_F(ApiTest, MultipleExecutionOfPreparedStatement) { @@ -185,3 +225,19 @@ TEST_F(ApiTest, MultipleExecutionOfPreparedStatement) { groundTruth = std::vector{"2|Bob"}; ASSERT_EQ(groundTruth, TestHelper::convertResultToString(*result)); } + +TEST_F(ApiTest, issueTest4) { + auto preparedStatement = conn->prepare("RETURN CAST($1, 'STRING')"); + auto result = conn->execute(preparedStatement.get(), + std::make_pair(std::string("1"), int128_t(-123456789))); + ASSERT_TRUE(result->hasNext()); + checkTuple(result->getNext().get(), "-123456789\n"); + ASSERT_FALSE(result->hasNext()); +} + +TEST_F(ApiTest, PrepareExport) { + auto newDBPath = databasePath + "/newdb"; + auto preparedStatement = conn->prepare("EXPORT DATABASE '" + newDBPath + '\''); + auto result = conn->execute(preparedStatement.get()); + ASSERT_TRUE(result->isSuccess()); +} diff --git a/test/main/result_value_test.cpp b/test/main/result_value_test.cpp index 513b239b6c0..38cbfa6544c 100644 --- a/test/main/result_value_test.cpp +++ b/test/main/result_value_test.cpp @@ -17,7 +17,9 @@ TEST_F(ResultValueTest, getNextException) { ASSERT_STREQ("Runtime exception: No more tuples in QueryResult, Please check hasNext() " "before calling getNext().", exception.what()); - } catch (Exception& exception) { FAIL(); } catch (std::exception& exception) { + } catch (Exception& exception) { + FAIL(); + } catch (std::exception& exception) { FAIL(); } } @@ -33,7 +35,9 @@ TEST_F(ResultValueTest, getResultValueException) { ASSERT_STREQ("Runtime exception: ValIdx is out of range. Number of values in flatTuple: 1, " "valIdx: 100.", exception.what()); - } catch (Exception& exception) { FAIL(); } catch (std::exception& exception) { + } catch (Exception& exception) { + FAIL(); + } catch (std::exception& exception) { FAIL(); } } diff --git a/test/main/udf_test.cpp b/test/main/udf_test.cpp index b29d15391fd..c01be2315a8 100644 --- a/test/main/udf_test.cpp +++ b/test/main/udf_test.cpp @@ -1,4 +1,3 @@ -#include "function/string/functions/concat_function.h" #include "main_test_helper/main_test_helper.h" using namespace kuzu::common; @@ -21,8 +20,8 @@ TEST_F(ApiTest, UnaryUDFInt64) { } TEST_F(ApiTest, UnaryUDFAddDate) { - conn->createScalarFunction( - "addFiveDays", std::vector{LogicalTypeID::DATE}, LogicalTypeID::DATE, &add5); + conn->createScalarFunction("addFiveDays", std::vector{LogicalTypeID::DATE}, + LogicalTypeID::DATE, &add5); auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (p:person) return addFiveDays(p.birthdate)")); auto expectedResult = std::vector{"1900-01-06", "1900-01-06", "1940-06-27", @@ -77,8 +76,8 @@ TEST_F(ApiTest, BinaryUDFFlatUnflat) { auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (p:person)-[:knows]->(p1:person) return " "addSecondParamTwice(to_int16(p.ID), to_int32(p1.age))")); - auto expectedResult = std::vector{ - "60", "90", "40", "72", "92", "42", "73", "63", "43", "75", "65", "95", "57", "87"}; + auto expectedResult = std::vector{"60", "90", "40", "72", "92", "42", "73", "63", + "43", "75", "65", "95", "57", "87"}; sortAndCheckTestResults(actualResult, expectedResult); } @@ -133,8 +132,8 @@ TEST_F(ApiTest, BinaryAddNanoSeconds) { auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (m:movies) return addNano(m.description.release_ns, " "to_int32(m.description.stars))")); - auto expectedResult = std::vector{ - "2011-08-20 11:25:30.123456", "2018-11-13 13:33:11.123456", "2011-02-11 16:44:22.123456"}; + auto expectedResult = std::vector{"2011-08-20 11:25:30.123456", + "2018-11-13 13:33:11.123456", "2011-02-11 16:44:22.123456"}; sortAndCheckTestResults(actualResult, expectedResult); } @@ -145,8 +144,8 @@ TEST_F(ApiTest, BinaryAddMilliSeconds) { auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (m:movies) return addMilli(m.description.release_ms, " "to_int32(m.description.stars))")); - auto expectedResult = std::vector{ - "2011-08-20 11:25:30.125", "2018-11-13 13:33:11.133", "2011-02-11 16:44:22.223"}; + auto expectedResult = std::vector{"2011-08-20 11:25:30.125", + "2018-11-13 13:33:11.133", "2011-02-11 16:44:22.223"}; sortAndCheckTestResults(actualResult, expectedResult); } @@ -157,8 +156,8 @@ TEST_F(ApiTest, BinaryAddSeconds) { auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (m:movies) return addSec(m.description.release_sec, " "to_int32(m.description.stars))")); - auto expectedResult = std::vector{ - "2011-08-20 11:25:32", "2018-11-13 13:33:21", "2011-02-11 16:46:02"}; + auto expectedResult = std::vector{"2011-08-20 11:25:32", "2018-11-13 13:33:21", + "2011-02-11 16:46:02"}; sortAndCheckTestResults(actualResult, expectedResult); } @@ -180,8 +179,8 @@ int32_t ternaryLenTotal(ku_string_t a, blob_t b, ku_string_t c) { TEST_F(ApiTest, TernaryUDFStr) { conn->createScalarFunction("ternaryLenTotal", - std::vector{ - LogicalTypeID::STRING, LogicalTypeID::BLOB, LogicalTypeID::STRING}, + std::vector{LogicalTypeID::STRING, LogicalTypeID::BLOB, + LogicalTypeID::STRING}, LogicalTypeID::INT32, &ternaryLenTotal); auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (m:movies) return ternaryLenTotal(m.name, m.content, m.note)")); @@ -195,7 +194,9 @@ static void validateUDFError(std::function createFunc, std::string errMs } catch (CatalogException& e) { ASSERT_EQ(std::string(e.what()), errMsg); return; - } catch (Exception&) { FAIL(); } + } catch (Exception&) { + FAIL(); + } FAIL(); } @@ -279,8 +280,8 @@ struct AddDate { static void addDate(const std::vector>& parameters, ValueVector& result, void* /*dataPtr*/ = nullptr) { KU_ASSERT(parameters.size() == 2); - function::BinaryFunctionExecutor::execute( - *parameters[0], *parameters[1], result); + function::BinaryFunctionExecutor::execute(*parameters[0], + *parameters[1], result); } TEST_F(ApiTest, vectorizedBinaryAddDate) { @@ -294,14 +295,29 @@ TEST_F(ApiTest, vectorizedBinaryAddDate) { sortAndCheckTestResults(actualResult, expectedResult); } +static void concat(const ku_string_t& left, const ku_string_t& right, ku_string_t& result, + ValueVector& resultValueVector) { + result.len = left.len + right.len; + if (result.len <= ku_string_t::SHORT_STR_LENGTH /* concat result is short */) { + memcpy(result.prefix, left.getData(), left.len); + memcpy(result.prefix + left.len, right.getData(), right.len); + } else { + StringVector::reserveString(&resultValueVector, result, result.len); + auto buffer = reinterpret_cast(result.overflowPtr); + memcpy(buffer, left.getData(), left.len); + memcpy(buffer + left.len, right.getData(), right.len); + memcpy(result.prefix, buffer, ku_string_t::PREFIX_LENGTH); + } +} + struct ConditionalConcat { - static inline void operation( - ku_string_t& a, bool& b, ku_string_t& c, ku_string_t& result, ValueVector& resultVector) { + static inline void operation(ku_string_t& a, bool& b, ku_string_t& c, ku_string_t& result, + ValueVector& resultVector) { // Concat a,c if b is true, otherwise concat c,a. if (b) { - function::Concat::operation(a, c, result, resultVector); + concat(a, c, result, resultVector); } else { - function::Concat::operation(c, a, result, resultVector); + concat(c, a, result, resultVector); } } }; @@ -314,8 +330,8 @@ static void conditionalConcat(const std::vector>& p } TEST_F(ApiTest, vectorizedTernaryConditionalAdd) { - conn->createVectorizedFunction( - "conditionalConcat", &conditionalConcat); + conn->createVectorizedFunction("conditionalConcat", + &conditionalConcat); auto actualResult = TestHelper::convertResultToString( *conn->query("MATCH (p:person)-[:knows]->(p1:person) return conditionalConcat(p.fName, " "p.isStudent, p1.fName)")); diff --git a/test/runner/cleanup_test.cpp b/test/runner/cleanup_test.cpp index fc0bfcfaa49..caf30e06667 100644 --- a/test/runner/cleanup_test.cpp +++ b/test/runner/cleanup_test.cpp @@ -12,8 +12,8 @@ void deleteMatchingDir(const std::string& dirPath, const std::string& match) { } int main(int argc, char** argv) { - std::vector tempDirs = { - TestHelper::PARQUET_TEMP_DATASET_PATH, TestHelper::TMP_TEST_DIR}; + std::vector tempDirs = {TestHelper::PARQUET_TEMP_DATASET_PATH, + TestHelper::TMP_TEST_DIR}; if (argc > 1 && std::string(argv[1]) == "--gtest_list_tests") { for (const auto& tempDir : tempDirs) { // path = test/unittest_temp_ diff --git a/test/runner/e2e_test.cpp b/test/runner/e2e_test.cpp index 4b397a22873..a68be2d31aa 100644 --- a/test/runner/e2e_test.cpp +++ b/test/runner/e2e_test.cpp @@ -15,8 +15,8 @@ class EndToEndTest : public DBTest { const std::set& connNames, std::vector> testStatements) : datasetType{datasetType}, dataset{std::move(dataset)}, bufferPoolSize{bufferPoolSize}, - checkpointWaitTimeout{checkpointWaitTimeout}, - testStatements{std::move(testStatements)}, connNames{connNames} {} + checkpointWaitTimeout{checkpointWaitTimeout}, testStatements{std::move(testStatements)}, + connNames{connNames} {} void SetUp() override { setUpDataset(); @@ -30,17 +30,23 @@ class EndToEndTest : public DBTest { } void setUpDataset() { - parquetTempDatasetPath = generateParquetTempDatasetPath(); - dataset = TestHelper::appendKuzuRootPath("dataset/" + dataset); if (datasetType == TestGroup::DatasetType::CSV_TO_PARQUET) { - throw NotImplementedException("CSV_TO_PARQUET dataset type is not implemented yet."); + auto csvDatasetPath = TestHelper::appendKuzuRootPath("dataset/" + dataset); + parquetTempDatasetPath = generateParquetTempDatasetPath(); + CSVToParquetConverter converter(csvDatasetPath, parquetTempDatasetPath, bufferPoolSize); + converter.convertCSVDatasetToParquet(); + dataset = parquetTempDatasetPath; + } else { + dataset = TestHelper::appendKuzuRootPath("dataset/" + dataset); } } void TearDown() override { std::filesystem::remove_all(databasePath); - std::filesystem::remove_all(parquetTempDatasetPath); BaseGraphTest::removeIEDBPath(); + if (datasetType == TestGroup::DatasetType::CSV_TO_PARQUET) { + std::filesystem::remove_all(parquetTempDatasetPath); + } } void TestBody() override { runTest(testStatements, checkpointWaitTimeout, connNames); } @@ -56,10 +62,11 @@ class EndToEndTest : public DBTest { std::set connNames; std::string generateParquetTempDatasetPath() { - return TestHelper::appendKuzuRootPath( - TestHelper::PARQUET_TEMP_DATASET_PATH + - CSVToParquetConverter::replaceSlashesWithUnderscores(dataset) + getTestGroupAndName() + - TestHelper::getMillisecondsSuffix()); + std::string datasetName = dataset; + std::replace(datasetName.begin(), datasetName.end(), '/', '_'); + return TestHelper::appendKuzuRootPath(TestHelper::PARQUET_TEMP_DATASET_PATH + datasetName + + "_" + getTestGroupAndName() + "_" + + TestHelper::getMillisecondsSuffix()); } }; diff --git a/test/storage/compression_test.cpp b/test/storage/compression_test.cpp index 8b351e0518d..7675372ea99 100644 --- a/test/storage/compression_test.cpp +++ b/test/storage/compression_test.cpp @@ -33,8 +33,8 @@ void test_compression(CompressionAlg& alg, std::vector src) { EXPECT_EQ(decompressed[1], value); for (auto i = 0u; i < src.size(); i++) { - alg.decompressFromPage( - dest.data(), i, (uint8_t*)decompressed.data(), i, 1 /*numValues*/, metadata); + alg.decompressFromPage(dest.data(), i, (uint8_t*)decompressed.data(), i, 1 /*numValues*/, + metadata); EXPECT_EQ(decompressed[i], src[i]); } EXPECT_EQ(decompressed, src); @@ -145,8 +145,8 @@ void integerPackingMultiPage(const std::vector& src) { size_t pageNum = 0; while (numValuesRemaining > 0) { ASSERT_LT(pageNum, pages); - alg.compressNextPage( - srcCursor, numValuesRemaining, dest[pageNum++].data(), pageSize, metadata); + alg.compressNextPage(srcCursor, numValuesRemaining, dest[pageNum++].data(), pageSize, + metadata); numValuesRemaining -= numValuesPerPage; } ASSERT_EQ(srcCursor, (uint8_t*)(src.data() + src.size())); @@ -154,8 +154,8 @@ void integerPackingMultiPage(const std::vector& src) { auto page = i / numValuesPerPage; auto indexInPage = i % numValuesPerPage; T value; - alg.decompressFromPage( - dest[page].data(), indexInPage, (uint8_t*)&value, 0, 1 /*numValues*/, metadata); + alg.decompressFromPage(dest[page].data(), indexInPage, (uint8_t*)&value, 0, 1 /*numValues*/, + metadata); EXPECT_EQ(src[i] - value, 0); EXPECT_EQ(src[i], value); } diff --git a/test/test_files/common/comment.test b/test/test_files/common/comment.test new file mode 100644 index 00000000000..710ab478834 --- /dev/null +++ b/test/test_files/common/comment.test @@ -0,0 +1,23 @@ +-GROUP CommentTests +-DATASET CSV empty + +-- + +-CASE CommentTest + +-STATEMENT RETURN 1; // This is a comment +---- 1 +1 +-STATEMENT RETURN 1 // This is a comment ; +---- 1 +1 +-STATEMENT RETURN 1; /* This is a commnet */ +---- 1 +1 +-STATEMENT RETURN 1 /* This is a commnet */ ; +---- 1 +1 +-STATEMENT /* This is a commnet */ + RETURN 1; +---- 1 +1 \ No newline at end of file diff --git a/test/test_files/common/types/null.test b/test/test_files/common/types/null.test new file mode 100644 index 00000000000..f66647a64d3 --- /dev/null +++ b/test/test_files/common/types/null.test @@ -0,0 +1,16 @@ +-GROUP IntervalTests +-DATASET CSV empty + +-- + +-CASE NullTest + +-STATEMENT CREATE NODE TABLE V1 (id UUID, PRIMARY KEY(id)); +---- ok +-STATEMENT CREATE NODE TABLE V2 (id INT64, PRIMARY KEY(id)); +---- ok +-STATEMENT WITH NULL as bid MATCH (b:V1 {id: bid}) RETURN b; +---- 0 + +-STATEMENT WITH NULL as bid MATCH (b:V2 {id: bid}) RETURN b; +---- 0 diff --git a/test/test_files/copy/copy_pk_long_string_parquet.test b/test/test_files/copy/copy_pk_long_string_parquet.test index 0a34d037ff8..c70f0e7058e 100644 --- a/test/test_files/copy/copy_pk_long_string_parquet.test +++ b/test/test_files/copy/copy_pk_long_string_parquet.test @@ -1,6 +1,5 @@ -GROUP LongStringPKTest -DATASET PARQUET CSV_TO_PARQUET(long-string-pk-tests) --SKIP -- diff --git a/test/test_files/copy/copy_to_parquet.test b/test/test_files/copy/copy_to_parquet.test index 344abba4ad9..c855d84bb01 100644 --- a/test/test_files/copy/copy_to_parquet.test +++ b/test/test_files/copy/copy_to_parquet.test @@ -5,7 +5,6 @@ -CASE TinySnbCopyToParquet --CASE CopyPersonToParquet -STATEMENT COPY (MATCH (p:person) return p.ID, p.fName, p.gender, p.isStudent, p.isWorker, p.age, p.eyeSight, p.birthdate, p.registerTime, p.lastJobDuration, p.workedHours, p.usedNames, p.courseScoresPerTerm, p.height) to '${DATABASE_PATH}/tinysnb.parquet'; ---- ok -STATEMENT LOAD FROM '${DATABASE_PATH}/tinysnb.parquet' RETURN *; diff --git a/test/test_files/copy/copy_transaction.test b/test/test_files/copy/copy_transaction.test index 54660994273..2b6eb3a8b51 100644 --- a/test/test_files/copy/copy_transaction.test +++ b/test/test_files/copy/copy_transaction.test @@ -43,8 +43,12 @@ notes UNION(firstmet DATE, type INT16, comment STRING), someMap MAP(STRING, STRING), MANY_MANY); ---- ok +-STATEMENT CALL ENABLE_MULTI_COPY=true; +---- ok -STATEMENT COPY knows FROM "${KUZU_ROOT_DIRECTORY}/dataset/tinysnb/eKnows.csv" ---- ok +-STATEMENT COPY knows FROM "${KUZU_ROOT_DIRECTORY}/dataset/tinysnb/eKnows_2.csv" +---- ok -STATEMENT match (:person)-[e:knows]->(:person) return e.date ---- 14 1905-12-12 diff --git a/test/test_files/copy/export_import_db.test b/test/test_files/copy/export_import_db.test index e4690ab4d93..86a97d9aa73 100644 --- a/test/test_files/copy/export_import_db.test +++ b/test/test_files/copy/export_import_db.test @@ -41,13 +41,13 @@ 50 -STATEMENT Export Database "${KUZU_EXPORT_DB_DIRECTORY}_case2/demo-db2" (format='csv', header=true) ---- error -Binder exception: Directory ${KUZU_EXPORT_DB_DIRECTORY}_case2/demo-db2 already exists. +Runtime exception: Directory ${KUZU_EXPORT_DB_DIRECTORY}_case2/demo-db2 already exists. -CASE ExportImportDatabaseWithPARQUET --STATEMENT Export Database "${KUZU_EXPORT_DB_DIRECTORY}_case2/demo-db3" (format='parquet') +-STATEMENT Export Database "${KUZU_EXPORT_DB_DIRECTORY}_case4/demo-db3" (format='parquet') ---- ok --IMPORT_DATABASE "${KUZU_EXPORT_DB_DIRECTORY}_case2/demo-db3" --STATEMENT IMPORT DATABASE "${KUZU_EXPORT_DB_DIRECTORY}_case2/demo-db3" +-IMPORT_DATABASE "${KUZU_EXPORT_DB_DIRECTORY}_case4/demo-db3" +-STATEMENT IMPORT DATABASE "${KUZU_EXPORT_DB_DIRECTORY}_case4/demo-db3" ---- ok -STATEMENT MATCH (u:User) WHERE u.name = 'Adam' SET u.age = 50 ---- ok diff --git a/test/test_files/cypherlogic/index/orderby_nosort/1000/slt_good_0.test b/test/test_files/cypherlogic/index/orderby_nosort/1000/slt_good_0.test new file mode 100644 index 00000000000..f06d913ff65 --- /dev/null +++ b/test/test_files/cypherlogic/index/orderby_nosort/1000/slt_good_0.test @@ -0,0 +1,1161 @@ +# These test are translated from SQLLogicTest. +# They are part of the CypherLogicTest project. +-GROUP CypherLogicTest +-DATASET CSV empty + +-- + +-CASE indexorderby_nosort1000slt_good_0 +-SKIP_32BIT +-STATEMENT CREATE NODE TABLE tab0(ID SERIAL,pk INT32, col0 INT32, col1 FLOAT, col2 STRING, col3 INT32, col4 FLOAT, col5 STRING, PRIMARY KEY(ID)) +---- ok +-STATEMENT CREATE (:tab0 {pk:0,col0:7086,col1:4595.50,col2:'gqivt',col3:9925,col4:6167.39,col5:'hzmxz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:1,col0:6270,col1:7871.18,col2:'llwfi',col3:5983,col4:6247.6,col5:'sufqd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:2,col0:5619,col1:9015.49,col2:'hheql',col3:9244,col4:2610.97,col5:'oqqxj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:3,col0:620,col1:5977.83,col2:'gsgir',col3:5949,col4:605.30,col5:'vhsef'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:4,col0:9598,col1:6807.56,col2:'wewcu',col3:8763,col4:6288.2,col5:'kjemy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:5,col0:1119,col1:904.65,col2:'xivyv',col3:3025,col4:7710.50,col5:'uhtvo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:6,col0:9092,col1:595.28,col2:'nxxwc',col3:3004,col4:6129.13,col5:'ltjya'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:7,col0:9589,col1:718.47,col2:'ffbfn',col3:8140,col4:7281.98,col5:'uiaxk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:8,col0:6985,col1:3221.72,col2:'evmqo',col3:9304,col4:2624.39,col5:'offqy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:9,col0:621,col1:5054.64,col2:'hdxjk',col3:5038,col4:588.61,col5:'nsvtb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:10,col0:8973,col1:1105.53,col2:'gbldf',col3:7813,col4:7827.44,col5:'czjxv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:11,col0:624,col1:5105.6,col2:'sqapz',col3:604,col4:582.81,col5:'aocsq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:12,col0:3564,col1:890.86,col2:'mphca',col3:1491,col4:5352.44,col5:'ubbdu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:13,col0:9093,col1:3627.15,col2:'naufs',col3:3213,col4:1308.48,col5:'sslge'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:14,col0:2079,col1:1104.39,col2:'cbdjx',col3:6113,col4:583.9,col5:'wehtu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:15,col0:626,col1:4939.87,col2:'bjdny',col3:6039,col4:9078.10,col5:'mwdtp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:16,col0:8652,col1:1856.36,col2:'rywss',col3:606,col4:9646.62,col5:'wxreu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:17,col0:8348,col1:4923.70,col2:'cotvw',col3:3742,col4:1296.67,col5:'qldru'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:18,col0:627,col1:4806.50,col2:'fmwab',col3:5346,col4:1460.79,col5:'tojyo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:19,col0:2471,col1:1021.66,col2:'wfxms',col3:4129,col4:7046.70,col5:'urzom'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:20,col0:6564,col1:3179.10,col2:'buicp',col3:5567,col4:5684.89,col5:'xhknu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:21,col0:3540,col1:2240.30,col2:'zuoyn',col3:7816,col4:6976.25,col5:'bozxj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:22,col0:628,col1:1762.97,col2:'crayv',col3:7953,col4:3747.73,col5:'cygmc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:23,col0:5531,col1:9150.69,col2:'lnhpg',col3:8234,col4:3295.91,col5:'ywzhz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:24,col0:6618,col1:6906.47,col2:'nrile',col3:2340,col4:8641.67,col5:'offjb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:25,col0:5233,col1:3881.44,col2:'qjkxu',col3:1626,col4:9776.80,col5:'hengv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:26,col0:3914,col1:6524.46,col2:'ygjpa',col3:1376,col4:4916.60,col5:'vocub'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:27,col0:2249,col1:598.71,col2:'lduiw',col3:7047,col4:1752.56,col5:'lvvng'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:28,col0:3129,col1:602.35,col2:'jnxkn',col3:607,col4:8691.93,col5:'zgmkm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:29,col0:8994,col1:3147.16,col2:'bialg',col3:6364,col4:6120.38,col5:'cyuqp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:30,col0:8085,col1:8640.9,col2:'gmjxv',col3:8055,col4:7643.61,col5:'jgpxm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:31,col0:697,col1:9756.99,col2:'djjum',col3:4258,col4:1340.97,col5:'jlxia'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:32,col0:5414,col1:4778.14,col2:'muteb',col3:5059,col4:1012.11,col5:'vkfyh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:33,col0:5389,col1:8337.94,col2:'sirxc',col3:8221,col4:7434.58,col5:'tbjjq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:34,col0:4563,col1:2664.50,col2:'favhb',col3:5433,col4:9603.45,col5:'pgxhy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:35,col0:3931,col1:8834.28,col2:'fcnml',col3:8559,col4:5987.97,col5:'feakm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:36,col0:7790,col1:8023.71,col2:'dlyju',col3:5889,col4:5780.16,col5:'heurj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:37,col0:9985,col1:2754.81,col2:'ojccx',col3:8389,col4:584.46,col5:'cdhgk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:38,col0:632,col1:8145.83,col2:'jddpz',col3:5951,col4:3471.32,col5:'xisyl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:39,col0:633,col1:3164.86,col2:'yqglr',col3:3641,col4:4618.88,col5:'bxkth'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:40,col0:9572,col1:1877.45,col2:'hybeh',col3:7955,col4:8169.53,col5:'zqdvz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:41,col0:3348,col1:4697.28,col2:'bcnfv',col3:3059,col4:5678.59,col5:'iictv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:42,col0:6707,col1:9633.70,col2:'uncih',col3:7050,col4:6925.92,col5:'htehp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:43,col0:2050,col1:3546.46,col2:'zvafm',col3:8197,col4:1159.51,col5:'lawbr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:44,col0:5078,col1:3389.25,col2:'ehghm',col3:1197,col4:8355.15,col5:'cgqdy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:45,col0:1045,col1:7467.34,col2:'eprdn',col3:3422,col4:591.5,col5:'hivqi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:46,col0:1006,col1:6681.26,col2:'dkeig',col3:1171,col4:2639.44,col5:'bizim'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:47,col0:8063,col1:5780.37,col2:'ozwwu',col3:5916,col4:4536.19,col5:'ikujh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:48,col0:3623,col1:4610.48,col2:'swdvx',col3:608,col4:1515.49,col5:'gchvq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:49,col0:3642,col1:9366.52,col2:'lkudb',col3:5671,col4:5913.41,col5:'gfchw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:50,col0:4877,col1:3838.14,col2:'lmdbq',col3:5756,col4:8289.57,col5:'eiior'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:51,col0:1135,col1:669.33,col2:'lzfxz',col3:5491,col4:8674.75,col5:'hmwii'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:52,col0:9525,col1:2591.4,col2:'fsumo',col3:5978,col4:7825.48,col5:'qrmpu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:53,col0:6705,col1:3693.83,col2:'trpzc',col3:998,col4:8467.75,col5:'zrwow'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:54,col0:5137,col1:656.47,col2:'jyjlr',col3:3247,col4:6551.53,col5:'anvze'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:55,col0:9331,col1:4010.60,col2:'vebjx',col3:613,col4:2500.50,col5:'jdlam'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:56,col0:2098,col1:9383.30,col2:'ogvky',col3:2399,col4:2459.58,col5:'yacsu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:57,col0:801,col1:8750.76,col2:'pzjzt',col3:5587,col4:9546.62,col5:'uxsug'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:58,col0:3603,col1:1685.89,col2:'yotwe',col3:1084,col4:5101.0,col5:'nesao'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:59,col0:5718,col1:6608.95,col2:'lixvy',col3:9973,col4:9938.27,col5:'cuiaz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:60,col0:5661,col1:2037.16,col2:'bmkhb',col3:9763,col4:5594.73,col5:'grqxj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:61,col0:1496,col1:7838.34,col2:'zjuyr',col3:638,col4:5575.11,col5:'lmrwm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:62,col0:7091,col1:6476.53,col2:'vmrgh',col3:1709,col4:6615.19,col5:'bbqqy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:63,col0:8363,col1:4261.63,col2:'mwtiz',col3:7263,col4:9916.38,col5:'mivmm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:64,col0:9529,col1:2603.99,col2:'ouchk',col3:3010,col4:2405.37,col5:'hqzky'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:65,col0:9357,col1:9258.7,col2:'jlecy',col3:2341,col4:7982.79,col5:'gojcn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:66,col0:7418,col1:9580.3,col2:'blxaw',col3:2565,col4:8768.78,col5:'pmtkw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:67,col0:634,col1:7771.41,col2:'robjk',col3:1174,col4:6358.65,col5:'cdrzd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:68,col0:8018,col1:8132.69,col2:'lfacz',col3:2083,col4:3069.47,col5:'eloxg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:69,col0:9950,col1:6309.96,col2:'siehf',col3:1883,col4:3191.74,col5:'yvtju'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:70,col0:1400,col1:610.53,col2:'gsxcc',col3:6091,col4:4237.99,col5:'metfk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:71,col0:9690,col1:2939.54,col2:'gtvbc',col3:5398,col4:8190.40,col5:'yegps'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:72,col0:636,col1:675.64,col2:'mfuui',col3:1923,col4:2761.45,col5:'ochrp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:73,col0:3841,col1:7293.52,col2:'mpbvq',col3:5460,col4:2628.51,col5:'vllaf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:74,col0:852,col1:3928.65,col2:'nxmxt',col3:9729,col4:696.49,col5:'rlvpb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:75,col0:9505,col1:613.79,col2:'yinwk',col3:8625,col4:9339.46,col5:'otiaj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:76,col0:1128,col1:7283.71,col2:'csndj',col3:2471,col4:1657.28,col5:'qdqkw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:77,col0:6597,col1:5511.77,col2:'qhplu',col3:4261,col4:2720.19,col5:'ralyf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:78,col0:2593,col1:9275.53,col2:'liaic',col3:5921,col4:822.50,col5:'oaqmz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:79,col0:7844,col1:6450.41,col2:'ypevf',col3:4548,col4:8730.15,col5:'awegt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:80,col0:9381,col1:615.31,col2:'deugr',col3:8667,col4:4932.39,col5:'aqlii'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:81,col0:8785,col1:9263.21,col2:'rbylw',col3:4479,col4:4891.35,col5:'vsjku'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:82,col0:8437,col1:1138.81,col2:'dpiuw',col3:2109,col4:2290.71,col5:'agikr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:83,col0:7772,col1:1394.17,col2:'ajfox',col3:1858,col4:593.30,col5:'uvpyc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:84,col0:9521,col1:5895.31,col2:'wptug',col3:610,col4:2763.74,col5:'xbffu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:85,col0:5970,col1:1850.84,col2:'oyyqk',col3:7304,col4:5568.6,col5:'zeeji'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:86,col0:5202,col1:9067.62,col2:'eavfi',col3:733,col4:7778.31,col5:'mwqhg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:87,col0:7355,col1:1200.31,col2:'iarbj',col3:4246,col4:2940.21,col5:'ypyfb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:88,col0:868,col1:7002.9,col2:'flayn',col3:2776,col4:594.77,col5:'ylvgp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:89,col0:8718,col1:1574.19,col2:'tptip',col3:8928,col4:6176.89,col5:'mplcu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:90,col0:4704,col1:7613.59,col2:'qgjaf',col3:9234,col4:4959.0,col5:'xerrf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:91,col0:9661,col1:6666.62,col2:'qkawy',col3:611,col4:614.72,col5:'zoyqx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:92,col0:7729,col1:617.54,col2:'mqrjo',col3:5570,col4:7794.43,col5:'hhsen'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:93,col0:2598,col1:1734.26,col2:'fadgb',col3:612,col4:3142.91,col5:'cphmq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:94,col0:3760,col1:6328.87,col2:'enhcu',col3:616,col4:6510.99,col5:'pwdms'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:95,col0:2756,col1:3595.33,col2:'dugao',col3:4023,col4:2227.15,col5:'zpyif'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:96,col0:9429,col1:8069.5,col2:'nrigw',col3:3779,col4:599.17,col5:'psugx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:97,col0:8174,col1:633.56,col2:'lwhtx',col3:8338,col4:7890.70,col5:'dhext'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:98,col0:4184,col1:9762.9,col2:'vomxu',col3:639,col4:600.97,col5:'oifff'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:99,col0:9705,col1:2787.22,col2:'pcvbo',col3:3794,col4:1714.32,col5:'ldtxg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:100,col0:637,col1:7132.50,col2:'sndfk',col3:7345,col4:8156.93,col5:'bdndo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:101,col0:1014,col1:1568.10,col2:'keaqu',col3:3507,col4:6847.33,col5:'ikedq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:102,col0:2796,col1:7466.37,col2:'fohjm',col3:3423,col4:8424.12,col5:'dgovw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:103,col0:8576,col1:620.53,col2:'eptbv',col3:3409,col4:7998.56,col5:'lbqls'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:104,col0:9606,col1:9614.28,col2:'vpqmr',col3:1208,col4:6401.16,col5:'hqudv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:105,col0:1683,col1:2843.39,col2:'opncu',col3:2241,col4:1439.37,col5:'zawpe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:106,col0:1409,col1:3990.36,col2:'lfovp',col3:5851,col4:9140.17,col5:'hziwe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:107,col0:2435,col1:6163.5,col2:'qenns',col3:1559,col4:5004.67,col5:'lujos'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:108,col0:1714,col1:2568.27,col2:'hxart',col3:5311,col4:5256.81,col5:'ltaxm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:109,col0:5748,col1:7758.44,col2:'weobo',col3:5730,col4:8091.90,col5:'wuhdw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:110,col0:6841,col1:8886.19,col2:'curhl',col3:617,col4:4928.29,col5:'jggfg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:111,col0:9348,col1:6948.1,col2:'edcmd',col3:1936,col4:1659.0,col5:'ofija'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:112,col0:5924,col1:8043.85,col2:'xwwzb',col3:4595,col4:9897.33,col5:'emdtv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:113,col0:3776,col1:4614.75,col2:'vmisg',col3:619,col4:8229.48,col5:'hyycp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:114,col0:909,col1:6703.49,col2:'gymcs',col3:4403,col4:3465.19,col5:'ihmlp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:115,col0:2382,col1:3200.18,col2:'niznm',col3:3230,col4:1887.35,col5:'gsglu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:116,col0:6553,col1:3091.91,col2:'angap',col3:9001,col4:615.66,col5:'sipit'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:117,col0:1333,col1:6712.35,col2:'jqpwl',col3:6743,col4:8279.18,col5:'abyiv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:118,col0:638,col1:6994.41,col2:'oxjfs',col3:620,col4:7427.6,col5:'ozqlj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:119,col0:9603,col1:719.83,col2:'xcerp',col3:9135,col4:4615.6,col5:'pflxs'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:120,col0:2918,col1:9763.84,col2:'ngvay',col3:3470,col4:2239.25,col5:'qjixm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:121,col0:8984,col1:2351.74,col2:'agovh',col3:1648,col4:9667.59,col5:'jhufm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:122,col0:7216,col1:4308.57,col2:'akead',col3:5827,col4:4489.60,col5:'znzua'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:123,col0:4078,col1:623.71,col2:'bhdlw',col3:8340,col4:3769.94,col5:'dcsjz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:124,col0:9333,col1:5107.51,col2:'rbsqa',col3:7944,col4:5292.4,col5:'ddrfw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:125,col0:2298,col1:4834.92,col2:'siakl',col3:6076,col4:8818.77,col5:'bhooa'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:126,col0:8088,col1:8197.10,col2:'irglg',col3:3095,col4:7327.2,col5:'zsdjs'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:127,col0:3872,col1:7759.8,col2:'efwwd',col3:4537,col4:8274.31,col5:'vhjyh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:128,col0:5116,col1:1177.32,col2:'jkmaj',col3:7365,col4:4834.50,col5:'wpqlf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:129,col0:1840,col1:2460.41,col2:'yodwz',col3:6216,col4:7158.30,col5:'lgusj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:130,col0:4862,col1:3211.66,col2:'ojnxv',col3:9654,col4:3617.99,col5:'mvgsz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:131,col0:2053,col1:3882.70,col2:'zswov',col3:6418,col4:2056.1,col5:'heeeu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:132,col0:4584,col1:5023.15,col2:'zggvz',col3:1673,col4:1041.55,col5:'zhqjj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:133,col0:3176,col1:8531.22,col2:'qysao',col3:3261,col4:1114.24,col5:'guopz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:134,col0:4352,col1:8901.36,col2:'gsgjd',col3:7947,col4:6035.74,col5:'wqbuw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:135,col0:6686,col1:4476.83,col2:'rebmv',col3:7674,col4:4041.34,col5:'oqmgg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:136,col0:7051,col1:8695.38,col2:'ibrfj',col3:5811,col4:9089.65,col5:'dgofq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:137,col0:6873,col1:1347.86,col2:'hdydh',col3:3401,col4:2110.17,col5:'ubjmu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:138,col0:8377,col1:9818.84,col2:'omjdw',col3:5415,col4:2257.94,col5:'cksby'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:139,col0:839,col1:625.23,col2:'ajafl',col3:6997,col4:8155.14,col5:'cdbsu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:140,col0:6836,col1:9245.90,col2:'tvvxo',col3:9719,col4:9153.75,col5:'nbvru'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:141,col0:8497,col1:4210.34,col2:'wepau',col3:7829,col4:6573.17,col5:'wshhg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:142,col0:3751,col1:5513.24,col2:'buegi',col3:4499,col4:4957.80,col5:'nywng'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:143,col0:2576,col1:7276.16,col2:'grruq',col3:8078,col4:3323.72,col5:'zmfrc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:144,col0:3254,col1:8722.9,col2:'byhzz',col3:8341,col4:6409.30,col5:'tqkaf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:145,col0:8616,col1:5420.16,col2:'wrwyg',col3:2735,col4:5928.80,col5:'sxwig'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:146,col0:2292,col1:626.20,col2:'vlqaf',col3:2640,col4:1813.1,col5:'cmsrl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:147,col0:4967,col1:6084.38,col2:'axntt',col3:9607,col4:3472.91,col5:'sdtul'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:148,col0:640,col1:4178.84,col2:'rkgfr',col3:1613,col4:1033.23,col5:'zpryq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:149,col0:2794,col1:8277.35,col2:'gsnrf',col3:9311,col4:6601.13,col5:'dgdmh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:150,col0:816,col1:4438.84,col2:'mpalw',col3:2281,col4:5499.78,col5:'fvxlm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:151,col0:6075,col1:2566.15,col2:'pkodq',col3:5278,col4:7526.3,col5:'jzybk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:152,col0:8257,col1:7664.54,col2:'krhre',col3:4482,col4:8201.1,col5:'yxprl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:153,col0:1599,col1:1083.39,col2:'mxupw',col3:3749,col4:619.74,col5:'kyrch'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:154,col0:1139,col1:1770.81,col2:'dzfwy',col3:864,col4:3692.80,col5:'tgqiz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:155,col0:8968,col1:7521.23,col2:'ragnr',col3:3780,col4:9412.91,col5:'mlpfg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:156,col0:641,col1:6230.6,col2:'ptmbk',col3:6886,col4:8088.57,col5:'sdozl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:157,col0:642,col1:7138.32,col2:'mhlku',col3:7239,col4:2605.70,col5:'iqnaq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:158,col0:644,col1:2082.23,col2:'ivoht',col3:826,col4:9067.26,col5:'eopia'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:159,col0:1712,col1:6751.88,col2:'ncpwu',col3:8807,col4:8056.85,col5:'bkagq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:160,col0:6589,col1:1927.79,col2:'camoz',col3:3768,col4:5871.36,col5:'zhnbx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:161,col0:645,col1:4743.63,col2:'vnqmd',col3:5974,col4:5787.59,col5:'elgpj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:162,col0:9450,col1:9927.75,col2:'fvzba',col3:9613,col4:9301.87,col5:'iyxxc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:163,col0:7374,col1:1056.85,col2:'vlcuh',col3:9048,col4:7383.69,col5:'qgavu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:164,col0:920,col1:1806.63,col2:'gnkvu',col3:5070,col4:1724.33,col5:'xwxqq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:165,col0:6437,col1:7199.34,col2:'kpeno',col3:1145,col4:5991.47,col5:'tbwsv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:166,col0:6070,col1:4853.49,col2:'jfuca',col3:9664,col4:7069.82,col5:'rghbj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:167,col0:4019,col1:6238.42,col2:'ulthd',col3:8195,col4:6319.76,col5:'gxwai'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:168,col0:2783,col1:7918.94,col2:'xrvak',col3:5731,col4:825.93,col5:'dypya'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:169,col0:9412,col1:2806.95,col2:'rehwd',col3:8942,col4:4641.92,col5:'hpxra'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:170,col0:1755,col1:1413.9,col2:'wqwvm',col3:8421,col4:620.81,col5:'csxfi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:171,col0:4715,col1:3097.33,col2:'ewzyq',col3:4940,col4:8791.86,col5:'ltkmn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:172,col0:6495,col1:7313.62,col2:'kmwuu',col3:5695,col4:3348.11,col5:'wabsw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:173,col0:4845,col1:4866.48,col2:'rirhn',col3:622,col4:8164.1,col5:'qsmjj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:174,col0:3322,col1:9156.69,col2:'ijofr',col3:8326,col4:909.3,col5:'adlkb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:175,col0:7528,col1:7433.86,col2:'ddvtr',col3:2974,col4:3723.33,col5:'grxga'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:176,col0:1370,col1:2043.5,col2:'pjeim',col3:9902,col4:4469.31,col5:'rdefk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:177,col0:3304,col1:1679.44,col2:'wqpdv',col3:2183,col4:7987.31,col5:'aocdu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:178,col0:2586,col1:2634.93,col2:'vdspj',col3:6820,col4:7333.19,col5:'iuacd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:179,col0:5524,col1:629.75,col2:'mathq',col3:989,col4:5041.98,col5:'ecdzz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:180,col0:1727,col1:9157.11,col2:'vhuil',col3:8293,col4:4365.47,col5:'vukcn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:181,col0:647,col1:6546.83,col2:'dfucs',col3:5010,col4:621.89,col5:'gvuvt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:182,col0:6365,col1:1398.92,col2:'zcsyt',col3:6344,col4:1994.48,col5:'lmjgq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:183,col0:6770,col1:6742.27,col2:'jxtol',col3:2676,col4:1672.14,col5:'hylse'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:184,col0:6882,col1:709.20,col2:'yskwf',col3:5810,col4:8211.6,col5:'warqn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:185,col0:6562,col1:7768.17,col2:'bpmog',col3:5230,col4:7229.33,col5:'qpdue'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:186,col0:6474,col1:9998.32,col2:'xalqq',col3:4340,col4:2568.59,col5:'gkqic'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:187,col0:4331,col1:8317.17,col2:'opidk',col3:6726,col4:7540.63,col5:'cppds'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:188,col0:1150,col1:3744.19,col2:'hqbst',col3:2395,col4:6182.0,col5:'bjjnf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:189,col0:7494,col1:8645.46,col2:'oxkgd',col3:4033,col4:4502.70,col5:'xofxn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:190,col0:9730,col1:7984.25,col2:'dbfpg',col3:3250,col4:1731.73,col5:'fknjp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:191,col0:6275,col1:631.73,col2:'gklal',col3:6831,col4:1573.77,col5:'qxyhi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:192,col0:3848,col1:634.48,col2:'snlyq',col3:2989,col4:3455.76,col5:'zvlbw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:193,col0:3716,col1:7479.21,col2:'ctvnk',col3:7612,col4:3776.57,col5:'jwnns'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:194,col0:7950,col1:9909.36,col2:'uzxhj',col3:624,col4:7159.60,col5:'esevr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:195,col0:5668,col1:4309.69,col2:'dgpvy',col3:1682,col4:7695.39,col5:'ljfve'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:196,col0:9293,col1:7481.93,col2:'ohohu',col3:7533,col4:622.28,col5:'wyixk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:197,col0:796,col1:7570.44,col2:'relcu',col3:7158,col4:1478.2,col5:'uecme'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:198,col0:7949,col1:5322.77,col2:'nzxoe',col3:8573,col4:1525.38,col5:'pdgqk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:199,col0:651,col1:5329.31,col2:'mkuns',col3:4971,col4:4833.80,col5:'putuz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:200,col0:6801,col1:7282.95,col2:'qkdws',col3:969,col4:1609.0,col5:'hsyia'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:201,col0:9299,col1:7219.66,col2:'ttohi',col3:8862,col4:9033.61,col5:'mpndw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:202,col0:1545,col1:8774.12,col2:'itbxn',col3:4870,col4:2509.78,col5:'ixzik'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:203,col0:4066,col1:4432.37,col2:'atlre',col3:5388,col4:6912.83,col5:'oqjvy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:204,col0:691,col1:6773.42,col2:'jwfkm',col3:3238,col4:7841.88,col5:'lsrap'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:205,col0:4792,col1:9726.87,col2:'gquys',col3:3916,col4:2867.41,col5:'fvwig'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:206,col0:5554,col1:9817.54,col2:'xnsdo',col3:1846,col4:2784.99,col5:'vwzwr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:207,col0:4204,col1:7419.11,col2:'xopjg',col3:6626,col4:2857.81,col5:'juhbs'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:208,col0:652,col1:8005.71,col2:'ndkzo',col3:9281,col4:4078.35,col5:'aymgl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:209,col0:7841,col1:3393.58,col2:'skmha',col3:8511,col4:4406.1,col5:'hzqlf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:210,col0:1791,col1:3000.67,col2:'hattd',col3:6942,col4:623.71,col5:'aglsu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:211,col0:4056,col1:5091.29,col2:'xttbg',col3:7376,col4:6596.55,col5:'pqkam'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:212,col0:9868,col1:8027.71,col2:'ndwjx',col3:9040,col4:624.37,col5:'dyutj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:213,col0:4013,col1:1520.80,col2:'ccicx',col3:3839,col4:625.47,col5:'lsxhf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:214,col0:7074,col1:7875.65,col2:'bknrk',col3:2600,col4:6913.15,col5:'gvbwv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:215,col0:1689,col1:3248.19,col2:'gpwwb',col3:1329,col4:7053.37,col5:'hbywz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:216,col0:8793,col1:8892.82,col2:'djeqc',col3:7457,col4:2268.39,col5:'mrnrr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:217,col0:3873,col1:2408.5,col2:'viptn',col3:6090,col4:1301.37,col5:'afehf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:218,col0:3219,col1:8992.10,col2:'jlwgf',col3:6260,col4:1117.99,col5:'lxauj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:219,col0:654,col1:2692.54,col2:'qzkgb',col3:7177,col4:8154.10,col5:'yntei'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:220,col0:1362,col1:7650.91,col2:'tuknb',col3:4472,col4:9574.35,col5:'etcve'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:221,col0:2990,col1:9358.33,col2:'xeyyl',col3:6456,col4:4509.77,col5:'tcofq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:222,col0:7042,col1:5903.17,col2:'tjelt',col3:626,col4:5317.43,col5:'bgyml'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:223,col0:7563,col1:9223.63,col2:'hfkie',col3:8610,col4:8826.7,col5:'owcch'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:224,col0:6893,col1:6351.37,col2:'fwgdj',col3:5027,col4:7587.70,col5:'xeklf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:225,col0:1928,col1:670.16,col2:'vgsau',col3:1130,col4:1126.25,col5:'ynpml'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:226,col0:655,col1:3158.49,col2:'iviru',col3:2356,col4:7188.17,col5:'ycakp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:227,col0:6937,col1:3642.19,col2:'ydiqs',col3:4321,col4:2993.8,col5:'tnvea'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:228,col0:9702,col1:2047.8,col2:'vnuez',col3:9064,col4:6484.38,col5:'vkyep'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:229,col0:6254,col1:9645.54,col2:'npoug',col3:1301,col4:7575.88,col5:'jdhya'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:230,col0:9989,col1:635.19,col2:'tbqvp',col3:4674,col4:9405.41,col5:'ogyoz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:231,col0:6357,col1:1750.51,col2:'ucedp',col3:8001,col4:9582.47,col5:'njeof'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:232,col0:9106,col1:6788.43,col2:'ngpuk',col3:1524,col4:1440.85,col5:'pooip'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:233,col0:6535,col1:4585.97,col2:'lwtmx',col3:3163,col4:5285.23,col5:'ibfwi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:234,col0:7746,col1:1902.91,col2:'auzix',col3:4761,col4:9644.84,col5:'tawjc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:235,col0:8890,col1:4347.33,col2:'oykme',col3:8342,col4:2518.6,col5:'jvyvb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:236,col0:9419,col1:7625.30,col2:'oavrq',col3:2348,col4:2631.5,col5:'icspb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:237,col0:8337,col1:8790.49,col2:'qczxk',col3:7904,col4:680.39,col5:'palfw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:238,col0:656,col1:7494.78,col2:'uftcy',col3:5058,col4:626.67,col5:'zcnxa'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:239,col0:2603,col1:7234.91,col2:'nzapj',col3:9033,col4:728.17,col5:'jumbf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:240,col0:9961,col1:6609.8,col2:'vhbye',col3:6478,col4:5234.43,col5:'tbifi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:241,col0:2227,col1:637.58,col2:'nxokv',col3:1719,col4:5185.91,col5:'lcmhm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:242,col0:9907,col1:1632.44,col2:'ebton',col3:3006,col4:9892.59,col5:'dvznh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:243,col0:658,col1:1213.2,col2:'ibmdm',col3:8768,col4:8136.62,col5:'aroxx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:244,col0:5045,col1:793.65,col2:'ralib',col3:3855,col4:9422.93,col5:'aavxe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:245,col0:3770,col1:3197.26,col2:'bjfsw',col3:5797,col4:5228.87,col5:'rzlyr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:246,col0:2945,col1:3869.2,col2:'rnkqw',col3:1047,col4:628.79,col5:'qzzia'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:247,col0:831,col1:2083.91,col2:'fnvbl',col3:1237,col4:3670.73,col5:'kimmv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:248,col0:3990,col1:2219.40,col2:'yroyu',col3:9421,col4:629.1,col5:'syexx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:249,col0:3534,col1:5002.5,col2:'tbcdq',col3:6330,col4:2233.84,col5:'ouuoj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:250,col0:1376,col1:8754.16,col2:'mintr',col3:6623,col4:9340.98,col5:'jvsst'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:251,col0:6480,col1:650.34,col2:'yfmyq',col3:5132,col4:1253.33,col5:'afbie'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:252,col0:1111,col1:7947.21,col2:'yenmi',col3:3116,col4:8263.61,col5:'bjsxj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:253,col0:7084,col1:9274.95,col2:'ocbms',col3:4510,col4:2627.90,col5:'xfqya'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:254,col0:2016,col1:5838.99,col2:'esmth',col3:2174,col4:9826.35,col5:'tcvro'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:255,col0:5574,col1:2703.58,col2:'smmuy',col3:4144,col4:9814.74,col5:'wfopp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:256,col0:5725,col1:638.46,col2:'obzce',col3:9883,col4:8267.17,col5:'sikfx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:257,col0:4988,col1:4315.47,col2:'yagah',col3:6528,col4:7835.61,col5:'yjmmn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:258,col0:6682,col1:9673.14,col2:'viedk',col3:5142,col4:9390.59,col5:'rdmsz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:259,col0:1178,col1:9053.38,col2:'fdifr',col3:6965,col4:3276.78,col5:'osuwh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:260,col0:2147,col1:5505.5,col2:'dgzmj',col3:9663,col4:637.65,col5:'virmg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:261,col0:2811,col1:3425.62,col2:'wylny',col3:3575,col4:4283.6,col5:'nylbi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:262,col0:2191,col1:9809.76,col2:'alyuh',col3:7969,col4:707.91,col5:'pqjuc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:263,col0:1361,col1:5499.0,col2:'rnyeu',col3:7286,col4:638.78,col5:'bpbhz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:264,col0:9696,col1:6436.36,col2:'mfetj',col3:7396,col4:643.49,col5:'almzt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:265,col0:1120,col1:4906.91,col2:'vmwiv',col3:1843,col4:3397.81,col5:'wazyl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:266,col0:662,col1:799.47,col2:'xtpdr',col3:8095,col4:1452.1,col5:'kzqkl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:267,col0:9188,col1:2841.21,col2:'wmvhp',col3:3799,col4:5610.54,col5:'yiekv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:268,col0:2686,col1:9868.26,col2:'axsqf',col3:3026,col4:7720.64,col5:'meekg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:269,col0:5481,col1:2058.35,col2:'usggo',col3:2523,col4:1603.93,col5:'uifbf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:270,col0:8001,col1:2187.41,col2:'alpbw',col3:7963,col4:4302.7,col5:'mvamd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:271,col0:2725,col1:6878.26,col2:'ziana',col3:630,col4:7334.41,col5:'fskin'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:272,col0:663,col1:7854.15,col2:'nvcfk',col3:1492,col4:7937.54,col5:'xnsba'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:273,col0:6461,col1:3182.45,col2:'ffvmg',col3:1806,col4:644.99,col5:'ozrsq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:274,col0:6935,col1:8532.22,col2:'mhszo',col3:5013,col4:6931.81,col5:'topos'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:275,col0:5039,col1:8414.91,col2:'syymk',col3:5164,col4:9662.20,col5:'lgprh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:276,col0:7259,col1:7443.91,col2:'iwogy',col3:2737,col4:1148.15,col5:'jbooy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:277,col0:9626,col1:1579.22,col2:'bajxo',col3:885,col4:5992.8,col5:'zpkud'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:278,col0:3977,col1:9379.3,col2:'xljwa',col3:1688,col4:2016.41,col5:'pwdpg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:279,col0:4197,col1:3247.43,col2:'hrqer',col3:2400,col4:1522.23,col5:'quaot'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:280,col0:2473,col1:688.93,col2:'jopvh',col3:1701,col4:2527.91,col5:'ptpfg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:281,col0:5543,col1:5549.16,col2:'vvbtp',col3:5950,col4:650.76,col5:'ijyqq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:282,col0:943,col1:9282.48,col2:'iqjcb',col3:5428,col4:7233.57,col5:'zcubi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:283,col0:3265,col1:2180.56,col2:'mhodd',col3:632,col4:6838.32,col5:'islpe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:284,col0:665,col1:4637.9,col2:'xvkrn',col3:8327,col4:2251.77,col5:'segtu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:285,col0:9777,col1:8394.30,col2:'mqrvz',col3:8193,col4:8855.10,col5:'jyjcp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:286,col0:4651,col1:7790.69,col2:'lcdpv',col3:8675,col4:5258.49,col5:'gzeyy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:287,col0:667,col1:1011.58,col2:'lesks',col3:3433,col4:4537.80,col5:'ozfwe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:288,col0:668,col1:1342.77,col2:'udpxb',col3:7556,col4:5495.18,col5:'kiljx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:289,col0:2896,col1:8415.14,col2:'lbmlw',col3:3805,col4:3905.67,col5:'kmfoz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:290,col0:6915,col1:9455.31,col2:'gnmtd',col3:8870,col4:3765.86,col5:'kunss'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:291,col0:8394,col1:640.24,col2:'yenou',col3:9614,col4:8544.49,col5:'vydyz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:292,col0:6629,col1:7855.86,col2:'kmfgy',col3:9328,col4:2435.8,col5:'vspuj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:293,col0:670,col1:8909.69,col2:'tfdkw',col3:3978,col4:1602.55,col5:'fpnve'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:294,col0:4553,col1:3828.47,col2:'kdvnf',col3:8455,col4:5432.89,col5:'thmjs'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:295,col0:5589,col1:6578.80,col2:'eqbpg',col3:2827,col4:7786.71,col5:'fnmzh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:296,col0:8572,col1:6224.74,col2:'phyur',col3:8586,col4:8247.91,col5:'plrgn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:297,col0:3053,col1:8181.45,col2:'wqxyc',col3:4903,col4:3370.32,col5:'bmvhd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:298,col0:9382,col1:5458.80,col2:'yqyhw',col3:4871,col4:7933.27,col5:'gvgjl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:299,col0:4960,col1:9913.2,col2:'wiuck',col3:1762,col4:6188.28,col5:'gcaoh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:300,col0:672,col1:3503.31,col2:'sovgg',col3:5271,col4:3106.64,col5:'xybnd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:301,col0:6223,col1:9531.44,col2:'smnxe',col3:7771,col4:5636.3,col5:'ttfui'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:302,col0:8216,col1:3897.44,col2:'oghzh',col3:633,col4:3945.20,col5:'hcmrb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:303,col0:4572,col1:6352.17,col2:'grqcf',col3:634,col4:2675.53,col5:'yocvr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:304,col0:1695,col1:1741.94,col2:'osouf',col3:4324,col4:2189.70,col5:'khrtp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:305,col0:676,col1:1258.18,col2:'vggng',col3:8774,col4:9827.27,col5:'poerr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:306,col0:2873,col1:3696.3,col2:'grqbg',col3:2962,col4:1143.38,col5:'ukiub'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:307,col0:7492,col1:6694.99,col2:'blecz',col3:6566,col4:1173.28,col5:'vjnho'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:308,col0:6508,col1:7989.51,col2:'nsecm',col3:5686,col4:5671.4,col5:'gaytr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:309,col0:1581,col1:6665.65,col2:'ccvrz',col3:9103,col4:2365.11,col5:'iovup'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:310,col0:677,col1:4406.69,col2:'rdkjz',col3:4520,col4:2203.99,col5:'dnnsn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:311,col0:1787,col1:6740.75,col2:'maieq',col3:4817,col4:653.85,col5:'zkodt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:312,col0:4243,col1:4297.42,col2:'kbhhq',col3:4300,col4:8728.11,col5:'ddvsr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:313,col0:9900,col1:4051.39,col2:'bplok',col3:4950,col4:4679.11,col5:'fysma'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:314,col0:1922,col1:651.7,col2:'wjlih',col3:2675,col4:4801.75,col5:'htewa'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:315,col0:678,col1:7292.21,col2:'ffqwo',col3:3557,col4:4908.6,col5:'wazyj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:316,col0:9217,col1:7717.55,col2:'pscaq',col3:636,col4:1536.85,col5:'ddril'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:317,col0:1069,col1:6718.40,col2:'rvxag',col3:7506,col4:3194.36,col5:'chvrm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:318,col0:4947,col1:1759.30,col2:'modxj',col3:9868,col4:1613.85,col5:'qvahq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:319,col0:1766,col1:4150.64,col2:'ojaeo',col3:6477,col4:2996.23,col5:'odevc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:320,col0:747,col1:652.28,col2:'xccna',col3:8046,col4:9270.72,col5:'adnxg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:321,col0:5653,col1:2967.18,col2:'kkjjo',col3:2963,col4:9336.42,col5:'gutqu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:322,col0:1059,col1:2504.0,col2:'pkhmz',col3:3540,col4:654.98,col5:'abekw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:323,col0:8583,col1:8114.78,col2:'dizsc',col3:2268,col4:8798.20,col5:'pfwjd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:324,col0:3146,col1:9096.50,col2:'sfmks',col3:8061,col4:2107.66,col5:'vorcy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:325,col0:9220,col1:6097.74,col2:'ejpia',col3:2511,col4:9530.37,col5:'lcnhm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:326,col0:7077,col1:2363.33,col2:'vdhzl',col3:6134,col4:3580.34,col5:'yfjgw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:327,col0:9041,col1:4985.90,col2:'glolz',col3:4622,col4:1241.27,col5:'zbjre'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:328,col0:5735,col1:6155.59,col2:'wmvxh',col3:5093,col4:5222.12,col5:'imdew'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:329,col0:2335,col1:4410.61,col2:'oiwgs',col3:2343,col4:5203.77,col5:'yjsxm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:330,col0:4816,col1:5886.91,col2:'flzvk',col3:5090,col4:9087.63,col5:'hosgd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:331,col0:6205,col1:5565.76,col2:'pnfzr',col3:2229,col4:4250.27,col5:'hdnjl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:332,col0:2828,col1:8529.44,col2:'rygpt',col3:9083,col4:8790.4,col5:'pkiwt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:333,col0:679,col1:1207.78,col2:'ljwxh',col3:3649,col4:2780.71,col5:'ngjle'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:334,col0:1092,col1:2624.87,col2:'kpuyf',col3:2849,col4:9511.5,col5:'kvykt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:335,col0:8142,col1:5654.62,col2:'kyxhy',col3:8782,col4:6751.53,col5:'nionp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:336,col0:3742,col1:8269.43,col2:'zzkso',col3:4973,col4:7989.88,col5:'ikdjz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:337,col0:4475,col1:4788.77,col2:'icwow',col3:2621,col4:3686.74,col5:'nwado'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:338,col0:7723,col1:7128.86,col2:'lhnso',col3:6854,col4:2528.29,col5:'hkefh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:339,col0:7918,col1:6053.24,col2:'jndzg',col3:2972,col4:2670.87,col5:'fbiuu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:340,col0:2793,col1:2425.44,col2:'eoiwt',col3:2703,col4:2992.58,col5:'ryzlj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:341,col0:9634,col1:8455.58,col2:'eppac',col3:640,col4:4348.96,col5:'swsya'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:342,col0:1524,col1:8949.0,col2:'zrobs',col3:9545,col4:814.56,col5:'hydqv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:343,col0:3600,col1:2563.88,col2:'soxcl',col3:8490,col4:933.60,col5:'lecfu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:344,col0:9300,col1:3049.87,col2:'cfqgu',col3:7216,col4:8977.58,col5:'hcvie'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:345,col0:6607,col1:654.73,col2:'llhpc',col3:3330,col4:6192.91,col5:'ilaeo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:346,col0:4312,col1:2637.93,col2:'cnslk',col3:8364,col4:2041.54,col5:'iuydw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:347,col0:8255,col1:5983.29,col2:'eyrcw',col3:4027,col4:5463.55,col5:'rcrls'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:348,col0:7574,col1:7190.59,col2:'bvnos',col3:8452,col4:6119.84,col5:'iibsg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:349,col0:965,col1:4247.23,col2:'dsqcl',col3:2449,col4:5643.69,col5:'efyro'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:350,col0:2904,col1:7744.79,col2:'jblsx',col3:5753,col4:8890.44,col5:'usiso'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:351,col0:9948,col1:2117.74,col2:'zalcl',col3:3276,col4:5190.5,col5:'ytjnh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:352,col0:6936,col1:6899.0,col2:'xxnya',col3:1354,col4:9594.80,col5:'mtqvy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:353,col0:3259,col1:7974.58,col2:'szytj',col3:4000,col4:4127.86,col5:'ojcua'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:354,col0:9114,col1:8819.21,col2:'xynia',col3:9153,col4:9035.95,col5:'qzlvl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:355,col0:1746,col1:1763.99,col2:'vospo',col3:4927,col4:4037.91,col5:'wnzds'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:356,col0:1700,col1:9228.97,col2:'alubs',col3:5862,col4:9577.41,col5:'wvyla'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:357,col0:9072,col1:4989.79,col2:'ekxjj',col3:9174,col4:8069.50,col5:'fmmkh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:358,col0:9762,col1:5414.33,col2:'hlifx',col3:1005,col4:5151.27,col5:'gjymn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:359,col0:1716,col1:723.30,col2:'yzlrb',col3:2672,col4:934.46,col5:'jhujq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:360,col0:1184,col1:6228.89,col2:'fvwbg',col3:6918,col4:1245.11,col5:'epytu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:361,col0:8965,col1:3593.38,col2:'xnuhr',col3:4162,col4:8896.17,col5:'mtrwk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:362,col0:6661,col1:2080.78,col2:'qfttj',col3:8750,col4:4914.9,col5:'neacl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:363,col0:2923,col1:9796.43,col2:'bbdwi',col3:5202,col4:9798.52,col5:'bmqth'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:364,col0:9703,col1:4948.65,col2:'wbypr',col3:4463,col4:4773.86,col5:'ooamc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:365,col0:8504,col1:7088.36,col2:'ylhfw',col3:641,col4:3034.95,col5:'dwszt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:366,col0:6630,col1:8367.69,col2:'ondwq',col3:4831,col4:1000.62,col5:'xcjtf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:367,col0:3435,col1:4786.63,col2:'ketef',col3:6208,col4:9563.41,col5:'zatmi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:368,col0:6575,col1:7439.62,col2:'upqxn',col3:3439,col4:5336.10,col5:'qvdwf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:369,col0:8256,col1:3772.23,col2:'tsrnc',col3:3348,col4:1907.41,col5:'kxdeh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:370,col0:1484,col1:8827.70,col2:'cbjzm',col3:6688,col4:1085.56,col5:'gncvk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:371,col0:6318,col1:6492.67,col2:'revee',col3:4383,col4:4151.96,col5:'pgzcy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:372,col0:6115,col1:754.71,col2:'jkzps',col3:3787,col4:3112.78,col5:'pvrra'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:373,col0:3786,col1:6949.0,col2:'hlrzz',col3:4929,col4:1943.62,col5:'doahl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:374,col0:8040,col1:3009.95,col2:'watbe',col3:6763,col4:7844.9,col5:'zdyjd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:375,col0:9637,col1:716.80,col2:'ciixz',col3:3417,col4:2490.48,col5:'zcqtw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:376,col0:7640,col1:6942.28,col2:'kyqvu',col3:642,col4:3274.34,col5:'cppbu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:377,col0:5662,col1:4918.19,col2:'agnwp',col3:1090,col4:4566.16,col5:'oywpe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:378,col0:8113,col1:5465.7,col2:'adfkk',col3:2496,col4:8954.92,col5:'bgbvx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:379,col0:6460,col1:8254.79,col2:'jnswc',col3:2002,col4:8504.80,col5:'rzmag'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:380,col0:5467,col1:3053.22,col2:'gfsht',col3:3366,col4:6000.74,col5:'hsivi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:381,col0:9449,col1:979.80,col2:'xfyzr',col3:3022,col4:6202.9,col5:'ntubx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:382,col0:8522,col1:5745.19,col2:'bpbam',col3:6331,col4:7091.24,col5:'vqdeu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:383,col0:4853,col1:4913.90,col2:'uczej',col3:3829,col4:1119.24,col5:'stvzu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:384,col0:8911,col1:1140.93,col2:'upved',col3:7479,col4:6465.41,col5:'wftdy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:385,col0:5714,col1:3435.34,col2:'mwfog',col3:6917,col4:8278.0,col5:'gdhzo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:386,col0:1081,col1:8401.95,col2:'defid',col3:5708,col4:9928.76,col5:'fohxj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:387,col0:7882,col1:1490.88,col2:'zxqhe',col3:7590,col4:4262.63,col5:'pwmhs'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:388,col0:2290,col1:8253.27,col2:'idbcw',col3:2730,col4:4845.32,col5:'yniun'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:389,col0:682,col1:5585.83,col2:'qjamz',col3:3967,col4:7218.94,col5:'oskep'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:390,col0:2608,col1:2983.48,col2:'wazeq',col3:3068,col4:655.66,col5:'qugas'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:391,col0:3615,col1:3788.0,col2:'gfrik',col3:6976,col4:6857.28,col5:'jesaq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:392,col0:4919,col1:6441.65,col2:'sgbgn',col3:4060,col4:6316.89,col5:'euzyh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:393,col0:2944,col1:5730.77,col2:'xgpaa',col3:643,col4:4450.51,col5:'sqsbz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:394,col0:4918,col1:4041.42,col2:'hxfar',col3:5853,col4:5413.65,col5:'zrexk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:395,col0:5117,col1:2607.2,col2:'gynuk',col3:679,col4:2831.2,col5:'pdjtu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:396,col0:1115,col1:2757.94,col2:'ixyhb',col3:1410,col4:1053.9,col5:'tldjc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:397,col0:684,col1:7172.17,col2:'fqtxy',col3:7295,col4:6398.75,col5:'mohmc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:398,col0:4829,col1:1127.91,col2:'azivp',col3:6505,col4:8412.92,col5:'rwtql'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:399,col0:685,col1:3746.19,col2:'gkgsb',col3:2389,col4:1110.17,col5:'hpsrw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:400,col0:692,col1:9251.53,col2:'zpgka',col3:9723,col4:4231.36,col5:'iorgh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:401,col0:1884,col1:8211.55,col2:'bcqmx',col3:956,col4:4488.26,col5:'frpty'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:402,col0:4156,col1:8792.57,col2:'ezexb',col3:2464,col4:6815.17,col5:'qtdrl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:403,col0:2691,col1:8009.27,col2:'ykgqt',col3:802,col4:5619.55,col5:'yzohb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:404,col0:6473,col1:2974.30,col2:'agefj',col3:8939,col4:6029.64,col5:'bqbkq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:405,col0:4036,col1:2147.91,col2:'ktbno',col3:2537,col4:5147.10,col5:'pouux'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:406,col0:9716,col1:6585.54,col2:'idbgk',col3:6172,col4:3299.60,col5:'hbzym'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:407,col0:9898,col1:1194.53,col2:'nippj',col3:9599,col4:5283.49,col5:'rfeta'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:408,col0:9268,col1:5976.64,col2:'iihyp',col3:4001,col4:1619.39,col5:'oseyl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:409,col0:7065,col1:7284.75,col2:'sdeiz',col3:8229,col4:9800.84,col5:'aliwy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:410,col0:3326,col1:9059.47,col2:'pdxgh',col3:5071,col4:5540.90,col5:'mbnzb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:411,col0:5140,col1:4104.72,col2:'uyseg',col3:7482,col4:4030.80,col5:'yqkrz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:412,col0:2897,col1:5309.43,col2:'fusft',col3:4847,col4:1179.55,col5:'ainsp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:413,col0:6536,col1:6916.11,col2:'zjurw',col3:9225,col4:4872.56,col5:'exiwm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:414,col0:1801,col1:5763.47,col2:'ofbvb',col3:1601,col4:6214.28,col5:'qnjth'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:415,col0:6482,col1:2538.11,col2:'xrqki',col3:8138,col4:784.82,col5:'vendq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:416,col0:6673,col1:3023.6,col2:'neafh',col3:6421,col4:9884.57,col5:'dmywi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:417,col0:3017,col1:9350.47,col2:'qadwg',col3:1714,col4:1789.82,col5:'kdhfn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:418,col0:6958,col1:1250.20,col2:'icjkk',col3:3205,col4:2995.42,col5:'sttst'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:419,col0:6993,col1:7297.45,col2:'phvuz',col3:644,col4:9472.35,col5:'vgjtd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:420,col0:4915,col1:6168.41,col2:'qikpg',col3:8665,col4:7911.39,col5:'asxdm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:421,col0:2073,col1:7885.85,col2:'rfxsv',col3:6889,col4:6978.71,col5:'lugqk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:422,col0:5615,col1:5068.77,col2:'myexp',col3:2324,col4:8561.53,col5:'cmhwl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:423,col0:4737,col1:4183.1,col2:'cegja',col3:7536,col4:9018.73,col5:'ztdqe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:424,col0:6940,col1:6797.87,col2:'iuknd',col3:6519,col4:656.46,col5:'iaitk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:425,col0:4272,col1:822.77,col2:'omjms',col3:942,col4:1864.79,col5:'pzvpe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:426,col0:9586,col1:1769.83,col2:'cnksk',col3:6399,col4:657.31,col5:'qafra'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:427,col0:2781,col1:3996.53,col2:'delsw',col3:8661,col4:3350.77,col5:'wbtjz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:428,col0:7062,col1:1959.32,col2:'anerx',col3:9926,col4:7630.73,col5:'gzqmw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:429,col0:5180,col1:1461.23,col2:'hzgym',col3:5062,col4:2873.13,col5:'rkaxe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:430,col0:5689,col1:905.52,col2:'vzjta',col3:7871,col4:1746.94,col5:'veddl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:431,col0:9193,col1:2536.30,col2:'xoiwk',col3:7325,col4:1392.81,col5:'lclbf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:432,col0:4599,col1:3705.14,col2:'nyhfc',col3:3824,col4:4674.65,col5:'kptnf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:433,col0:5362,col1:8103.73,col2:'hgukj',col3:5443,col4:1430.31,col5:'yekxl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:434,col0:5739,col1:7023.45,col2:'sdxlh',col3:4183,col4:9718.13,col5:'ndgsj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:435,col0:7038,col1:655.5,col2:'efljz',col3:2220,col4:7071.65,col5:'hhzib'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:436,col0:3867,col1:9086.23,col2:'fbxus',col3:8158,col4:1743.17,col5:'akcqf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:437,col0:693,col1:4049.30,col2:'pksrx',col3:3275,col4:3962.40,col5:'dyzli'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:438,col0:6554,col1:9679.78,col2:'jclsj',col3:7774,col4:7177.8,col5:'dthjv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:439,col0:4382,col1:4004.6,col2:'cmtgn',col3:7037,col4:9312.63,col5:'lmtgg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:440,col0:4182,col1:657.96,col2:'whopf',col3:7868,col4:4012.72,col5:'rjozg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:441,col0:818,col1:7600.44,col2:'pahag',col3:4749,col4:1894.97,col5:'qxixu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:442,col0:9949,col1:3420.14,col2:'xpvzc',col3:6087,col4:1799.48,col5:'pgipj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:443,col0:4292,col1:3533.8,col2:'lftai',col3:647,col4:2042.56,col5:'lcmmx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:444,col0:9862,col1:3956.23,col2:'xrlir',col3:2895,col4:1656.27,col5:'ncqib'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:445,col0:2222,col1:2057.15,col2:'iefga',col3:1058,col4:1652.9,col5:'dqndi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:446,col0:2741,col1:7798.66,col2:'xxjdq',col3:1564,col4:6260.53,col5:'ildkb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:447,col0:4835,col1:4992.37,col2:'kskuj',col3:6201,col4:4184.77,col5:'hanbt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:448,col0:699,col1:2547.40,col2:'dodbo',col3:8181,col4:9851.25,col5:'hoeya'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:449,col0:5169,col1:5720.96,col2:'fltrj',col3:8391,col4:4661.34,col5:'yjcmv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:450,col0:6747,col1:7364.97,col2:'lrzqv',col3:1645,col4:8235.93,col5:'eoufm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:451,col0:9076,col1:9183.69,col2:'sugay',col3:2932,col4:9668.8,col5:'nrppz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:452,col0:9577,col1:2976.38,col2:'xatnv',col3:3668,col4:8775.62,col5:'ciqmy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:453,col0:5222,col1:1889.87,col2:'gypax',col3:7942,col4:7348.79,col5:'wsbus'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:454,col0:8783,col1:1669.21,col2:'dezjw',col3:8772,col4:660.87,col5:'qlbbs'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:455,col0:5083,col1:1907.31,col2:'pwfvy',col3:4351,col4:7415.81,col5:'fzcgh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:456,col0:7247,col1:7294.54,col2:'cmxwb',col3:4296,col4:3601.81,col5:'qjzgc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:457,col0:2949,col1:8867.38,col2:'xhbqt',col3:5901,col4:1138.1,col5:'euakz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:458,col0:701,col1:5263.2,col2:'cbhsm',col3:649,col4:661.6,col5:'nhbjg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:459,col0:5921,col1:3964.98,col2:'tsvsu',col3:9148,col4:1354.78,col5:'vhtpw'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:460,col0:7545,col1:2551.78,col2:'zwrte',col3:650,col4:4506.78,col5:'agoxi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:461,col0:3915,col1:9954.52,col2:'dmvhn',col3:3460,col4:2458.7,col5:'qiyfa'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:462,col0:9209,col1:7697.52,col2:'xofra',col3:8930,col4:1004.68,col5:'hymeg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:463,col0:9658,col1:1155.96,col2:'lsasi',col3:1016,col4:665.33,col5:'mnxsj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:464,col0:9790,col1:800.46,col2:'mrsit',col3:5743,col4:6665.98,col5:'xzjry'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:465,col0:8688,col1:3450.78,col2:'lfdhk',col3:6810,col4:2732.55,col5:'okmou'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:466,col0:6233,col1:3522.36,col2:'rlqpd',col3:1844,col4:9794.44,col5:'wqmxf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:467,col0:9358,col1:4281.1,col2:'jqjjx',col3:8646,col4:8509.26,col5:'qcifa'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:468,col0:8297,col1:9089.49,col2:'xwdit',col3:1444,col4:667.35,col5:'mctjt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:469,col0:2833,col1:2656.18,col2:'umsky',col3:7142,col4:8387.51,col5:'srqht'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:470,col0:8552,col1:2289.67,col2:'yvyld',col3:1569,col4:9478.54,col5:'peupf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:471,col0:3090,col1:9143.39,col2:'txttl',col3:5729,col4:4576.90,col5:'jxign'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:472,col0:2383,col1:9470.24,col2:'bxnwr',col3:2053,col4:668.34,col5:'kpsdc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:473,col0:6918,col1:5873.23,col2:'qxvxi',col3:651,col4:848.53,col5:'kiytu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:474,col0:7984,col1:8547.8,col2:'wmyot',col3:5547,col4:7731.66,col5:'lvmqv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:475,col0:3919,col1:6540.86,col2:'hhtji',col3:957,col4:2538.7,col5:'eirjz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:476,col0:6363,col1:8995.60,col2:'jtzpo',col3:7511,col4:7431.90,col5:'ubqtt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:477,col0:6507,col1:6402.94,col2:'ypere',col3:8520,col4:6542.69,col5:'jzluk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:478,col0:1343,col1:1851.73,col2:'aqayg',col3:6219,col4:7230.1,col5:'vjicd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:479,col0:9911,col1:2276.68,col2:'fehhk',col3:8020,col4:1320.10,col5:'dhsrf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:480,col0:9555,col1:9713.95,col2:'qwdsw',col3:2759,col4:6366.47,col5:'jmlkb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:481,col0:2169,col1:2543.82,col2:'edaxo',col3:6948,col4:6893.55,col5:'yvsum'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:482,col0:702,col1:6746.26,col2:'mybzj',col3:1028,col4:5647.29,col5:'qalkq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:483,col0:4134,col1:7149.61,col2:'gjxbb',col3:5611,col4:4847.81,col5:'sdgvh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:484,col0:6276,col1:8675.18,col2:'ffdwp',col3:7738,col4:7436.1,col5:'fjowv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:485,col0:9469,col1:7598.87,col2:'ipdke',col3:7125,col4:8329.19,col5:'wmuon'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:486,col0:2112,col1:2788.79,col2:'xrjoj',col3:2413,col4:5662.69,col5:'gqoom'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:487,col0:4653,col1:6960.92,col2:'rgore',col3:7420,col4:2047.52,col5:'awnwz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:488,col0:5840,col1:7933.68,col2:'zgngh',col3:7390,col4:5815.95,col5:'btxij'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:489,col0:8974,col1:9867.61,col2:'xornd',col3:5241,col4:2273.17,col5:'kcgnk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:490,col0:8155,col1:4524.97,col2:'inwdz',col3:7817,col4:4949.91,col5:'pltae'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:491,col0:4534,col1:2511.35,col2:'cpssc',col3:2140,col4:6843.5,col5:'oukkl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:492,col0:2565,col1:4536.32,col2:'fylmx',col3:1656,col4:1679.25,col5:'aexom'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:493,col0:6250,col1:2651.5,col2:'udlza',col3:2487,col4:5153.58,col5:'liclp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:494,col0:5391,col1:1507.92,col2:'isxpm',col3:9682,col4:6184.15,col5:'cguuv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:495,col0:1846,col1:9603.17,col2:'vujet',col3:3462,col4:8163.72,col5:'jwdpi'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:496,col0:5767,col1:658.49,col2:'uuouz',col3:5479,col4:669.35,col5:'urntn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:497,col0:1863,col1:4250.69,col2:'nxqda',col3:5057,col4:8395.98,col5:'dixta'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:498,col0:5639,col1:8287.29,col2:'bxijq',col3:5447,col4:7043.10,col5:'qhviy'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:499,col0:9653,col1:9036.14,col2:'oqarm',col3:652,col4:9932.36,col5:'ymnzx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:500,col0:9763,col1:2984.8,col2:'brwum',col3:8798,col4:1566.20,col5:'mtdqh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:501,col0:1380,col1:7966.55,col2:'ayzss',col3:4140,col4:8423.44,col5:'jtshe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:502,col0:5712,col1:4415.20,col2:'cjmjq',col3:7555,col4:672.96,col5:'qkmqq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:503,col0:6021,col1:6610.52,col2:'mnqef',col3:5676,col4:1076.30,col5:'jmwsv'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:504,col0:3869,col1:3930.48,col2:'xdcqz',col3:6556,col4:940.25,col5:'ukrlb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:505,col0:5367,col1:2099.14,col2:'vwtbg',col3:5928,col4:6663.54,col5:'jtcjx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:506,col0:7429,col1:4442.30,col2:'ougah',col3:3448,col4:3335.44,col5:'auael'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:507,col0:4020,col1:3127.7,col2:'jfthg',col3:8951,col4:5520.34,col5:'djajh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:508,col0:2401,col1:660.56,col2:'pcgbj',col3:8694,col4:8503.44,col5:'vgoxr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:509,col0:9391,col1:9951.47,col2:'vssxh',col3:1612,col4:9543.36,col5:'yybws'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:510,col0:7605,col1:7919.71,col2:'zkagv',col3:5568,col4:9121.71,col5:'ehaxl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:511,col0:1711,col1:4388.4,col2:'kdizm',col3:3593,col4:2191.81,col5:'iyfby'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:512,col0:4676,col1:4520.71,col2:'aaaeg',col3:654,col4:9429.23,col5:'ifthl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:513,col0:4018,col1:9821.4,col2:'ocapw',col3:7385,col4:8486.45,col5:'inedn'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:514,col0:8058,col1:9394.7,col2:'mxpla',col3:1352,col4:5232.50,col5:'acsif'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:515,col0:2165,col1:1193.21,col2:'hbvwi',col3:8294,col4:5013.55,col5:'krgja'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:516,col0:5010,col1:3266.82,col2:'oxnro',col3:878,col4:3896.56,col5:'jwpgf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:517,col0:4815,col1:5010.86,col2:'zdlxs',col3:4437,col4:9919.90,col5:'jcmau'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:518,col0:5603,col1:8422.52,col2:'snjnd',col3:3246,col4:4347.98,col5:'yctku'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:519,col0:3446,col1:9342.82,col2:'iigxr',col3:6745,col4:2914.86,col5:'mkmlf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:520,col0:2719,col1:8713.27,col2:'zehrw',col3:5801,col4:7077.87,col5:'qfdcg'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:521,col0:2348,col1:3820.45,col2:'nkfdw',col3:8960,col4:5268.28,col5:'iwoxl'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:522,col0:2056,col1:9551.69,col2:'syexv',col3:8690,col4:4140.86,col5:'wmiqt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:523,col0:8621,col1:9638.64,col2:'evbsv',col3:7637,col4:9818.57,col5:'aprvr'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:524,col0:2121,col1:7912.94,col2:'runxc',col3:4873,col4:9151.12,col5:'ivrmk'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:525,col0:2182,col1:9552.82,col2:'fycaa',col3:2145,col4:960.65,col5:'allqx'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:526,col0:4235,col1:2333.72,col2:'bklnm',col3:655,col4:7287.34,col5:'fbcae'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:527,col0:5757,col1:7880.93,col2:'bvhit',col3:4663,col4:4652.0,col5:'cccrc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:528,col0:2531,col1:2914.23,col2:'mgtnu',col3:3032,col4:5291.75,col5:'bsfry'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:529,col0:4886,col1:663.47,col2:'mkhyg',col3:656,col4:8417.60,col5:'qaqnd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:530,col0:3955,col1:1318.23,col2:'xpyut',col3:4993,col4:1465.11,col5:'wcgzp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:531,col0:7920,col1:4869.45,col2:'rgkgt',col3:6512,col4:1341.98,col5:'gjppt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:532,col0:8265,col1:771.1,col2:'tmedy',col3:657,col4:5675.70,col5:'zidkt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:533,col0:6025,col1:9981.42,col2:'hvpqg',col3:4267,col4:4068.19,col5:'beglo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:534,col0:8033,col1:6058.38,col2:'vtdpx',col3:5735,col4:9348.36,col5:'gjlnb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:535,col0:3177,col1:6407.45,col2:'iikns',col3:6878,col4:8811.82,col5:'mgmqf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:536,col0:8641,col1:3531.67,col2:'izhzb',col3:1377,col4:5476.44,col5:'uukwc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:537,col0:6165,col1:6280.17,col2:'eudjb',col3:659,col4:9341.0,col5:'mduud'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:538,col0:8286,col1:1102.78,col2:'xoujt',col3:9792,col4:8613.81,col5:'gdwcf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:539,col0:4592,col1:3294.70,col2:'qztrb',col3:4450,col4:988.36,col5:'jemmt'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:540,col0:7975,col1:8247.10,col2:'orisd',col3:6444,col4:4873.90,col5:'qpkwu'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:541,col0:874,col1:2704.73,col2:'altzj',col3:661,col4:673.9,col5:'umjjh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:542,col0:1529,col1:6003.57,col2:'tgiam',col3:9606,col4:1935.64,col5:'ifetb'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:543,col0:704,col1:1329.46,col2:'xnlvq',col3:2921,col4:6797.90,col5:'waydz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:544,col0:5582,col1:6969.68,col2:'hbvls',col3:662,col4:9040.52,col5:'dtbne'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:545,col0:720,col1:7552.62,col2:'jjqth',col3:9702,col4:9439.4,col5:'ellny'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:546,col0:9580,col1:5310.40,col2:'looaw',col3:2619,col4:6990.55,col5:'ivoxe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:547,col0:3169,col1:1316.48,col2:'vvylu',col3:983,col4:674.29,col5:'pfrhe'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:548,col0:5780,col1:6748.29,col2:'wbywt',col3:3080,col4:8153.27,col5:'nvvra'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:549,col0:1259,col1:4127.84,col2:'dpoml',col3:9879,col4:2120.93,col5:'mpdep'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:550,col0:9254,col1:8573.39,col2:'pqxfd',col3:1271,col4:6455.74,col5:'svroq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:551,col0:1463,col1:9054.3,col2:'pdhom',col3:2325,col4:681.82,col5:'nqyzz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:552,col0:7885,col1:9635.32,col2:'cefet',col3:9530,col4:7388.58,col5:'jtqms'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:553,col0:3070,col1:728.91,col2:'vtrlz',col3:7059,col4:682.32,col5:'ydypc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:554,col0:2368,col1:664.18,col2:'hhfbc',col3:3005,col4:8004.91,col5:'iktfz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:555,col0:8182,col1:5344.87,col2:'yjyuz',col3:5639,col4:683.34,col5:'growp'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:556,col0:6213,col1:2680.65,col2:'kjvas',col3:9657,col4:6920.40,col5:'xevrz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:557,col0:1715,col1:665.83,col2:'kxvkm',col3:2432,col4:9875.29,col5:'jrysz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:558,col0:5740,col1:666.91,col2:'dquly',col3:663,col4:4313.25,col5:'rjjuh'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:559,col0:1393,col1:5986.25,col2:'cwwch',col3:4618,col4:9876.15,col5:'shwas'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:560,col0:705,col1:7934.67,col2:'objoe',col3:8403,col4:1925.18,col5:'salmf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:561,col0:7758,col1:2214.11,col2:'iqesc',col3:2190,col4:2800.41,col5:'bksvc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:562,col0:1182,col1:2616.20,col2:'floum',col3:669,col4:3059.46,col5:'oauuc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:563,col0:4162,col1:1782.93,col2:'ukocr',col3:7954,col4:2734.9,col5:'ouobm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:564,col0:3804,col1:2449.27,col2:'ygymc',col3:5709,col4:2581.87,col5:'axvre'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:565,col0:6768,col1:8699.76,col2:'pcmcm',col3:7524,col4:5325.75,col5:'uzfuz'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:566,col0:5515,col1:7218.20,col2:'cxway',col3:6106,col4:6917.74,col5:'lcqfo'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:567,col0:4555,col1:8533.18,col2:'gjatb',col3:9334,col4:7781.48,col5:'sebbq'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:568,col0:6700,col1:8274.82,col2:'kkexz',col3:6513,col4:4060.91,col5:'mtxlf'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:569,col0:9312,col1:8416.30,col2:'ruzxs',col3:4626,col4:8874.89,col5:'umczm'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:570,col0:706,col1:8530.53,col2:'ysnob',col3:4578,col4:3563.78,col5:'fwbnd'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:571,col0:5640,col1:7039.76,col2:'epsqu',col3:7454,col4:8940.13,col5:'uubrj'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:572,col0:3085,col1:2461.22,col2:'hmenw',col3:763,col4:6541.26,col5:'fedod'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:573,col0:954,col1:4661.73,col2:'mwkxl',col3:4687,col4:9877.89,col5:'yqihc'}) +---- ok +-STATEMENT CREATE (:tab0 {pk:574,col0:3114,col1:6104.34,col2:'idzic',col3:8339,col4:5673.79,col5:'idvsy'}) +---- ok diff --git a/test/test_files/ddl/add_property.test b/test/test_files/ddl/add_property.test deleted file mode 100644 index 2ef869c7975..00000000000 --- a/test/test_files/ddl/add_property.test +++ /dev/null @@ -1,40 +0,0 @@ --GROUP DDL --DATASET CSV empty - --- - --CASE AddNodeProperty --STATEMENT create node table Comment (id int64, PRIMARY KEY (id)); ----- ok --STATEMENT copy Comment from '${KUZU_ROOT_DIRECTORY}/dataset/lsqb-sf01/Comment.csv' (HEADER=true, DELIM='|'); ----- ok --STATEMENT alter table Comment add propx int64; ----- ok --STATEMENT MATCH (c:Comment) RETURN SUM(c.propx); ----- 1 - --STATEMENT alter table Comment add propy int64 default 1; ----- ok --STATEMENT MATCH (c:Comment) RETURN SUM(c.propy); ----- 1 -215488 - --CASE AddRelProperty --STATEMENT create node table Comment (id int64, PRIMARY KEY (id)); ----- ok --STATEMENT create rel table replyOf (FROM Comment TO Comment, MANY_ONE); ----- ok --STATEMENT copy Comment from '${KUZU_ROOT_DIRECTORY}/dataset/lsqb-sf01/Comment.csv' (HEADER=true, DELIM='|'); ----- ok --STATEMENT copy replyOf from '${KUZU_ROOT_DIRECTORY}/dataset/lsqb-sf01/Comment_replyOf_Comment.csv' (HEADER=true, DELIM='|'); ----- ok --STATEMENT alter table replyOf add propx int64; ----- ok --STATEMENT MATCH (c:Comment)-[r:replyOf]->(c2:Comment) RETURN SUM(r.propx); ----- 1 - --STATEMENT alter table replyOf add propy int64 default 1; ----- ok --STATEMENT MATCH (c:Comment)-[r:replyOf]->(c2:Comment) RETURN SUM(r.propy); ----- 1 -108027 diff --git a/test/test_files/ddl/ddl.test b/test/test_files/ddl/ddl.test index cda6fa5dfa6..92861218cd8 100644 --- a/test/test_files/ddl/ddl.test +++ b/test/test_files/ddl/ddl.test @@ -35,10 +35,10 @@ Binder exception: Table movies does not exist. -CASE DDLOutputMessages -STATEMENT CREATE NODE TABLE university(ID INT64, PRIMARY KEY(ID)) ---- 1 -Node table: university has been created. +Table university has been created. -STATEMENT CREATE REL TABLE nearTo(FROM university TO university, MANY_MANY) ---- 1 -Rel table: nearTo has been created. +Table nearTo has been created. -STATEMENT DROP TABLE nearTo; ---- 1 Table: nearTo has been dropped. @@ -47,15 +47,15 @@ Table: nearTo has been dropped. Table: university has been dropped. -STATEMENT ALTER TABLE person DROP fName ---- 1 -Drop succeed. +Table person altered. -STATEMENT ALTER TABLE knows DROP date ---- 1 -Drop succeed. +Table knows altered. -CASE CreateRelGroup -STATEMENT CREATE REL TABLE GROUP likes (FROM person TO person, FROM person TO organisation, since INT64); ---- 1 -Rel table group: likes has been created. +Table likes has been created. -STATEMENT Call table_info('likes_person_person') RETURN *; ---- 1 1|since|INT64 @@ -89,6 +89,42 @@ Binder exception: Table movies does not exist. ---- error Binder exception: Table knows does not exist. +-CASE AddNodeProperty +-STATEMENT create node table Comment (id int64, PRIMARY KEY (id)); +---- ok +-STATEMENT copy Comment from '${KUZU_ROOT_DIRECTORY}/dataset/lsqb-sf01/Comment.csv' (HEADER=true, DELIM='|'); +---- ok +-STATEMENT alter table Comment add propx int64; +---- ok +-STATEMENT MATCH (c:Comment) RETURN SUM(c.propx); +---- 1 + +-STATEMENT alter table Comment add propy int64 default 1; +---- ok +-STATEMENT MATCH (c:Comment) RETURN SUM(c.propy); +---- 1 +215488 + +-CASE AddRelProperty +-STATEMENT create node table Comment (id int64, PRIMARY KEY (id)); +---- ok +-STATEMENT create rel table replyOf (FROM Comment TO Comment, MANY_ONE); +---- ok +-STATEMENT copy Comment from '${KUZU_ROOT_DIRECTORY}/dataset/lsqb-sf01/Comment.csv' (HEADER=true, DELIM='|'); +---- ok +-STATEMENT copy replyOf from '${KUZU_ROOT_DIRECTORY}/dataset/lsqb-sf01/Comment_replyOf_Comment.csv' (HEADER=true, DELIM='|'); +---- ok +-STATEMENT alter table replyOf add propx int64; +---- ok +-STATEMENT MATCH (c:Comment)-[r:replyOf]->(c2:Comment) RETURN SUM(r.propx); +---- 1 + +-STATEMENT alter table replyOf add propy int64 default 1; +---- ok +-STATEMENT MATCH (c:Comment)-[r:replyOf]->(c2:Comment) RETURN SUM(r.propy); +---- 1 +108027 + -CASE DropNodeTablePropertyNormalExecution -STATEMENT ALTER TABLE person DROP gender ---- ok diff --git a/test/test_files/exceptions/binder/binder_error.test b/test/test_files/exceptions/binder/binder_error.test index 992e63da925..8030e349fb4 100644 --- a/test/test_files/exceptions/binder/binder_error.test +++ b/test/test_files/exceptions/binder/binder_error.test @@ -15,11 +15,6 @@ Binder exception: Cannot resolve any node or relationship to create. ---- error Binder exception: Cannot resolve any node or relationship to create. --LOG NodeTableNotExist --STATEMENT MATCH (a:PERSON) RETURN COUNT(*) ----- error -Binder exception: Table PERSON does not exist. - -LOG RepeatedRelName -STATEMENT MATCH (a:person)-[e1:knows]->(b:person)<-[e1:knows]-(:person) RETURN COUNT(*) ---- error @@ -111,7 +106,7 @@ Binder exception: Cannot match a built-in function for given function +(INTERNAL (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE @@ -137,7 +132,7 @@ Binder exception: Cannot match a built-in function for given function +(DATE,DAT (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE @@ -163,7 +158,7 @@ Binder exception: Cannot match a built-in function for given function +(TIMESTAM (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE @@ -189,7 +184,7 @@ Binder exception: Cannot match a built-in function for given function +(TIMESTAM (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE @@ -239,15 +234,7 @@ Binder exception: p1.age has data type INT64 but (STRING) was expected. -LOG UnionAndUnionAllInSingleQuery -STATEMENT MATCH (p:person) RETURN p.age UNION ALL MATCH (p1:person) RETURN p1.age UNION MATCH (p1:person) RETURN p1.age ---- error -Binder exception: Union and union all can't be used together. - --LOG ReadAfterUpdate --STATEMENT MATCH (a:person) SET a.age = 35 WITH a MATCH (a)-[:knows]->(b:person) RETURN a.age ----- error -Binder exception: Read after update is not supported. Try query with multiple statements. --STATEMENT MATCH (a:person) WHERE a.age = 35 DELETE a WITH a MATCH (a)-[:knows]->(b:person) RETURN a.age ----- error -Binder exception: Read after update is not supported. Try query with multiple statements. +Binder exception: Union and union all can not be used together. -LOG SetDataTypeMisMatch -STATEMENT MATCH (a:person) SET a.age = 'hh' @@ -294,7 +281,7 @@ Binder exception: person already exists in catalog. -LOG CreateNodeTablePKColNameNotExists -STATEMENT CREATE NODE TABLE PERSON(NAME STRING, ID INT64, birthdate date, primary key (dummyColName)) ---- error -Binder exception: Primary key dummyColName does not match any of the predefined node properties. +Binder exception: PERSON already exists in catalog. -LOG CreateNodeTableDuplicatedColumnName -STATEMENT CREATE NODE TABLE student (id INT64, eyesight double, eyesight double, PRIMARY KEY(id)) @@ -315,7 +302,7 @@ Binder exception: No file found that matches the pattern: wrong_path.parquet. -STATEMENT COPY person FROM "${KUZU_ROOT_DIRECTORY}/dataset/tinysnb/vPerson.csv" (pk=",") ---- error Binder exception: Unrecognized csv parsing option: PK. --STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/change_config.csv" (HEADER=true, DELIM="|", ESCAPE="~", QUOTE="'", LIST_END=")") RETURN * ; +-STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/change_config.csv" (HEADER=true, DELIM="|", ESCAPE="~", QUOTE="'", LIST_END=")") RETURN * ; ---- error Binder exception: Unrecognized csv parsing option: LIST_END. -STATEMENT LOAD WITH HEADERS (map MAP(STRING, MAP(STRING, INT16))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/map/nested_map_correct.csv" (LIST_BEGIN="(") RETURN *; @@ -323,7 +310,7 @@ Binder exception: Unrecognized csv parsing option: LIST_END. Binder exception: Unrecognized csv parsing option: LIST_BEGIN. -LOG LoadCSVInvalidCol --STATEMENT LOAD WITH HEADERS (list INT32[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/quote_error.csv" RETURN * ; +-STATEMENT LOAD WITH HEADERS (list INT32[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/quote_error.csv" RETURN * ; ---- error Binder exception: Number of columns mismatch. Expected 1 but got 3. @@ -494,20 +481,10 @@ Catalog exception: Table: person1 does not exist. ---- error Binder exception: person table already has property gender. --LOG InvalidFixedListChildType --STATEMENT create node table test1(ID INT64, marks STRING[5], PRIMARY KEY(ID)) ----- error -Binder exception: The child type of a fixed list must be a numeric type. Given: STRING. - --LOG InvalidFixedListNumElements +-LOG InvalidArrayNumElements -STATEMENT create node table test1(ID INT64, marks INT64[0], PRIMARY KEY(ID)) ---- error -Binder exception: The number of elements in a fixed list must be greater than 0. Given: 0. - --LOG InvalidFixedListSize --STATEMENT create node table test1(ID INT64, marks INT64[512], PRIMARY KEY(ID)) ----- error -Binder exception: Cannot store a fixed list of size 4096 in a page. +Binder exception: The number of elements in an array must be greater than 0. Given: 0. -LOG NonPKSerialType -STATEMENT CREATE NODE TABLE test(ID INT64, seq SERIAL, PRIMARY KEY(ID)) @@ -540,7 +517,7 @@ Binder exception: Cannot match a built-in function for given function +(INT64,ST (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE @@ -587,10 +564,12 @@ Binder exception: COPY TO currently only supports csv and parquet files. -LOG InvalidArgCast -STATEMENT RETURN cast("[sdf, fsd, fad]", "STRING[]", "3rd arg"); ---- error -Binder exception: Invalid number of arguments for given function CAST. Expected: 2, Actual: 3. +Binder exception: Cannot match a built-in function for given function CAST(STRING,STRING,STRING). Supported inputs are +(ANY,STRING) -> ANY -STATEMENT RETURN cast("[sdf, fsd, fad]"); ---- error -Binder exception: Invalid number of arguments for given function CAST. Expected: 2, Actual: 1. +Binder exception: Cannot match a built-in function for given function CAST(STRING). Supported inputs are +(ANY,STRING) -> ANY -LOG InvalidImplicitCast -STATEMENT RETURN timestamp("2019-11-21") + "ok"; @@ -608,7 +587,7 @@ Binder exception: Cannot match a built-in function for given function +(TIMESTAM (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE @@ -632,7 +611,7 @@ Binder exception: Cannot match a built-in function for given function +(TIMESTAM (DOUBLE,DOUBLE) -> DOUBLE (FLOAT,FLOAT) -> FLOAT (SERIAL,SERIAL) -> SERIAL -(VAR_LIST,VAR_LIST) -> VAR_LIST +(LIST,LIST) -> LIST (STRING,STRING) -> STRING (INTERVAL,INTERVAL) -> INTERVAL (DATE,INT64) -> DATE diff --git a/test/test_files/exceptions/copy/auto_commit.test b/test/test_files/exceptions/copy/auto_commit.test index 67d7a13c0f8..0a967a772fa 100644 --- a/test/test_files/exceptions/copy/auto_commit.test +++ b/test/test_files/exceptions/copy/auto_commit.test @@ -22,4 +22,4 @@ DDL, Copy, createMacro statements can only run in the AUTO_COMMIT mode. Please c ---- ok -STATEMENT COPY knows FROM "${KUZU_ROOT_DIRECTORY}/dataset/tinysnb/eKnows.csv" ---- 1 -14 number of tuples has been copied to table knows. +6 number of tuples has been copied to table knows. diff --git a/test/test_files/exceptions/copy/npy_fault.test b/test/test_files/exceptions/copy/npy_fault.test index 4eadc0bd150..b3776ba1c6d 100644 --- a/test/test_files/exceptions/copy/npy_fault.test +++ b/test/test_files/exceptions/copy/npy_fault.test @@ -10,4 +10,7 @@ ---- ok -STATEMENT copy knows from ("${KUZU_ROOT_DIRECTORY}/dataset/npy-20k/id_int64.npy") by column; ---- error -Binder exception: Copy from npy files to rel table knows is not supported yet. +Binder exception: Copy by column is not supported for relationship table. +-STATEMENT copy person from ("${KUZU_ROOT_DIRECTORY}/dataset/read-list-tests/large-list/vPerson.csv") by column; +---- error +Binder exception: Copy by column with CSV file type is not supported. diff --git a/test/test_files/issue/issue.test b/test/test_files/issue/issue.test index 76965889a69..442184261f9 100644 --- a/test/test_files/issue/issue.test +++ b/test/test_files/issue/issue.test @@ -233,7 +233,6 @@ True|True|True [t2,t22] [t3] - -CASE 2587 -STATEMENT CREATE NODE TABLE T (id STRING, descr STRING, PRIMARY KEY (id)); ---- ok @@ -397,3 +396,12 @@ v3|v2 {_ID: 1:1, _LABEL: R, id: r12}|v12 |v11 |v111 + +-CASE 3042 +-STATEMENT CREATE NODE TABLE MyTask (id STRING, inputs MAP(STRING, STRING)[], PRIMARY KEY(id)); +---- ok +-STATEMENT CREATE (:MyTask {id: 'myid', inputs: [MAP(['input1'], ['value1'])]}); +---- ok +-STATEMENT MATCH (n:MyTask) RETURN n.*; +---- 1 +myid|[{input1=value1}] diff --git a/test/test_files/issue/issue2.test b/test/test_files/issue/issue2.test new file mode 100644 index 00000000000..934031e9121 --- /dev/null +++ b/test/test_files/issue/issue2.test @@ -0,0 +1,125 @@ +-GROUP IssueTest +-DATASET CSV empty + +-- + +-CASE 3129 +-STATEMENT CREATE NODE TABLE V (id UUID, PRIMARY KEY(id)); +---- ok +-STATEMENT CREATE REL TABLE E (FROM V TO V); +---- ok +-STATEMENT CREATE (v1:V {id: UUID('11111111-1111-1111-1111-111111111111')})-[:E]->(v2:V {id: UUID('22222222-2222-2222-2222-222222222222')}); +---- ok +-STATEMENT MATCH (v:V {id: UUID('11111111-1111-1111-1111-111111111111')}) + OPTIONAL MATCH (v)-[:E]->(v1:V) + RETURN v1.id +---- 1 +22222222-2222-2222-2222-222222222222 + +-CASE 3055 +-STATEMENT CREATE NODE TABLE test ( id STRING, prop1 STRING, prop2 INT64, prop3 STRING, prop4 STRING, PRIMARY KEY(id) ) +---- ok +-STATEMENT MERGE (n:test { id: "ewm8ewnn@l23:" }) SET n.prop1 = "model", n.prop2 = 6, n.prop3 = "trips_2", n.prop4 = "0bbhfwnenwafnw88989382932wwewej332938293jiwojewie923892389283923" RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "ewm8ewnn ewweklnbgeireg@l23:ewe" }) SET n.prop1 = "model", n.prop2 = 16, n.prop3 = "normalize_data", n.prop4 = "1bbhfwnenwafnw88989234342wwewej332938293jiwojewie923892389283923" RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "ewm8ewnn ewweklnbgew888g@lew3:ewe" }) SET n.prop1 = "model", n.prop2 = 74, n.prop3 = "zones", n.prop4 = "2bbhfwnenaafnw88989234342wwewej332938293jiwojewie923192389283923" RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "ewm8ew43lnbgew888g@lew3:ewe" }) SET n.prop1 = "expectation", n.prop2 = 27, n.prop3 = "test_trips_1", n.prop4 = "3bbhfwnenaafnw88989234342wwewej332938213jiwojewie923192389283923" RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "ewm8ew43ffbgew888g@lew3:ewe" }) SET n.prop1 = "expectation", n.prop2 = 37, n.prop3 = "test_trips_2", n.prop4 = "4bbhfwnenaafnw88989234312wwewej332938213jiwojewie923192389283923" RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "ewm8ew43ffrrr88g@lew3:ewe" }) SET n.prop1 = "expectation", n.prop2 = 47, n.prop3 = "test_norm_data_1", n.prop4 = "5bbhfwnenaafnw88989234312wwewej332938213jiwojewie923192389283923" RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "fwfwfe8g@lew3:ewe" }) SET n.prop1 = "model", n.prop4 = "6bbhfwnenaafnw88989234312wwewej332938213jiwojewie923192389283923" RETURN n.id +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "fwfwfe8g@lew3:ewe" AND n.prop1 = "model" AND n.prop2 IS NULL AND n.prop3 IS NULL RETURN n +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "ewm8ewnn ewweklnbgew888g@lew3:ewe" AND n.prop1 = "model" AND n.prop2 = 74 AND n.prop3 = "zones" RETURN n +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "ewm8ewnn@l23:" AND n.prop1 = "model" AND n.prop2 = 6 AND n.prop3 = "trips_2" RETURN n +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "ewm8ewnn ewweklnbgeireg@l23:ewe" AND n.prop1 = "model" AND n.prop2 = 16 AND n.prop3 = "normalize_data" RETURN n +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "ewm8ew43lnbgew888g@lew3:ewe" AND n.prop1 = "expectation" AND n.prop2 = 27 AND n.prop3 = "test_trips_1" RETURN n +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "ewm8ew43ffbgew888g@lew3:ewe" AND n.prop1 = "expectation" AND n.prop2 = 37 AND n.prop3 = "test_trips_2" RETURN n +---- ok +-STATEMENT MATCH (n:test) WHERE n.id = "ewm8ew43ffrrr88g@lew3:ewe" AND n.prop1 = "expectation" AND n.prop2 = 47 AND n.prop3 = "test_norm_data_1" RETURN n +---- ok +-STATEMENT MERGE (n:test { id: "nfewnfwn+wnfw"}) RETURN n.id +---- ok +-STATEMENT MERGE (n:test { id: "nfewn32n+wnfw"}) RETURN n.id +---- ok +-STATEMENT CREATE NODE TABLE res ( name STRING, PRIMARY KEY(name) ) +---- ok +-STATEMENT MERGE (n:res { name: "nfewnnfw" }) RETURN n.name +---- ok +-STATEMENT CREATE REL TABLE etable ( FROM res TO test , eprop1 STRING, eprop2 STRING, eprop3 STRING ) +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "nfewnfwn+wnfw" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "nfewj932-ew2b-5f33-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "fwfsiewmk" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "fwfsiewmk" AND t.id = "nfewnfwn+wnfw" CREATE (f)-[r:etable { eprop1 : "0.0.0", eprop3 : "nfewj932-ew2b-5f33-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "nfewnnfw" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "nfewn32n+wnfw" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "mdewj932-ew2b-5f44-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "s3scan+taxi_fhvhv" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "mdewj932-ew2b-5f44-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "fwfsiewmk" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "fwfsiewmk" AND t.id = "nfewn32n+wnfw" CREATE (f)-[r:etable { eprop1 : "0.0.0", eprop3 : "mdewj932-ew2b-5f44-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "fwfsiewmk" AND t.id = "s3scan+taxi_fhvhv" CREATE (f)-[r:etable { eprop1 : "0.0.0", eprop3 : "mdewj932-ew2b-5f44-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "nfewnnfw" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "ewm8ewnn ewweklnbgew888g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "qqewj932-ew2b-5f88-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "ewm8ewnn@l23:" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "qqewj932-ew2b-5f88-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "ewm8ew43ffrrr88g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "qqewj932-ew2b-5f88-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MATCH (f) - [r:etable] -> (t) WHERE t.id = 'ewm8ewnn@l23:' and r.eprop3 = 'qqewj932-ew2b-5f88-nfew' RETURN COUNT(*); +---- 1 +1 +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "ewm8ew43ffbgew888g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "ooewj932-ew2b-5f19-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "pdanwewer" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "pdanwewer" AND t.id = "ewm8ew43ffbgew888g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.2.4", eprop3 : "ooewj932-ew2b-5f19-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "another_dep" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "another_dep" AND t.id = "ewm8ew43ffbgew888g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "9.9.9", eprop3 : "ooewj932-ew2b-5f19-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "nfewnnfw" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "ewm8ewnn ewweklnbgeireg@l23:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "rrewj932-ew2b-5f92-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "pdanwewer" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "pdanwewer" AND t.id = "ewm8ewnn ewweklnbgeireg@l23:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "rrewj932-ew2b-5f92-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "numpy" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "numpy" AND t.id = "ewm8ewnn ewweklnbgeireg@l23:ewe" CREATE (f)-[r:etable { eprop1 : "2.2.2", eprop3 : "rrewj932-ew2b-5f92-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "nfewnnfw" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "fwfwfe8g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "mmewj932-ew2b-5f00-nfew" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "nfewnnfw" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "nfewnnfw" AND t.id = "ewm8ew43lnbgew888g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.1.1", eprop3 : "piewj932-ew2b-5f00-nfrr" }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:res { name: "pdanwewer" }) RETURN n.name +---- ok +-STATEMENT MATCH (f:res), (t:test) WHERE f.name = "pdanwewer" AND t.id = "ewm8ew43lnbgew888g@lew3:ewe" CREATE (f)-[r:etable { eprop1 : "1.2.3", eprop3 : "piewj932-ew2b-5f00-nfrr" }]->(t) RETURN r +---- ok +-STATEMENT MATCH (f) - [r:etable] -> (t) WHERE t.id = 'ewm8ewnn@l23:' and r.eprop3 = 'qqewj932-ew2b-5f88-nfew' RETURN COUNT(*); +---- 1 +1 diff --git a/test/test_files/issue/issue3.test b/test/test_files/issue/issue3.test new file mode 100644 index 00000000000..693dc4f33cc --- /dev/null +++ b/test/test_files/issue/issue3.test @@ -0,0 +1,36 @@ +-GROUP IssueTest +-DATASET CSV empty + +-- + +-CASE BUG +-STATEMENT CREATE NODE TABLE n ( id STRING, name STRING, PRIMARY KEY(id) ) +---- ok +-STATEMENT CREATE NODE TABLE f ( id STRING, prop1 STRING, prop2 STRING, prop3 INT64, prop4 STRING, prop5 STRING, PRIMARY KEY(id) ) +---- ok +-STATEMENT CREATE REL TABLE E ( FROM n TO f , prop BOOLEAN ) +---- ok +-STATEMENT MERGE (n:f { id: "fewnjw32i3o#new" }) SET n.prop1 = "wen3", n.prop2 = "ewfw23", n.prop5 = "d6112fewnfw2323ir203092323f78r2r" RETURN n.id +---- ok +-STATEMENT MERGE (n:n { id: "wfw24sd" }) SET n.name = "fs23" RETURN n.id +---- ok +-STATEMENT MATCH (f:n), (t:f) WHERE f.id = "wfw24sd" AND t.id = "fewnjw32i3o#new" CREATE (f)-[r:E { prop : True }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:n { id: "fwfw232few" }) SET n.name = "fw3dds" RETURN n.id +---- ok +-STATEMENT MATCH (f:n), (t:f) WHERE f.id = "fwfw232few" AND t.id = "fewnjw32i3o#new" CREATE (f)-[r:E { prop : True }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:n { id: "7fnfjwe*33" }) SET n.name = "89njfew23" RETURN n.id +---- ok +-STATEMENT MATCH (f:n), (t:f) WHERE f.id = "7fnfjwe*33" AND t.id = "fewnjw32i3o#new" CREATE (f)-[r:E { prop : True }]->(t) RETURN r +---- ok +-STATEMENT MERGE (n:n { id: "8nfw*" }) SET n.name = "fs23" RETURN n.id +---- ok +-STATEMENT MERGE (n:n { id: "wefn&323" }) SET n.name = "89njfew23" RETURN n.id +---- ok +-STATEMENT MERGE (n:f { id: "nj2r2br2&323h^w8" }) SET n.prop1 = "wen3", n.prop2 = "wpy", n.prop3 = 6, n.prop4 = "tpi32", n.prop5 = "s12" RETURN n.id +---- ok +-STATEMENT MERGE (n:n { id: "njwf&33bnjkfw*f" }) SET n.name = "cs" RETURN n.id +---- ok +-STATEMENT MATCH (f:n), (t:f) WHERE f.id = "njwf&33bnjkfw*f" AND t.id = "nj2r2br2&323h^w8" CREATE (f)-[r:E { prop : False }]->(t) RETURN r +---- ok diff --git a/test/test_files/issue/issue4.test b/test/test_files/issue/issue4.test new file mode 100644 index 00000000000..f27f8e8a9be --- /dev/null +++ b/test/test_files/issue/issue4.test @@ -0,0 +1,25 @@ +-GROUP IssueTest +-DATASET CSV empty + +-- + +-CASE 3083 +-STATEMENT CREATE NODE TABLE test ( prop0 STRING, prop1 STRING[], prop2 STRING, prop3 INT64, prop4 STRING, PRIMARY KEY(prop4) ) +---- ok +-STATEMENT MERGE (n:test { prop4: "efwb2143d10ccfw" }) SET n.prop0 = "efwoj23", n.prop1 = ["eee", "wefwhiihifwe23343", "dmkwlenfwef232323"], n.prop2 = "NOT eee IS NULL AND dmkwlenfwef232323 < '2023-01-10T00:00:00-05:00' AND dmkwlenfwef232323 >= '2022-01-01T00:00:00-05:00'", n.prop3 = 5 RETURN n.prop4 +---- ok +-STATEMENT MERGE (n:test { prop4: "sdnweh2382933228" }) SET n.prop0 = "efwoj23", n.prop1 = ["customer_name", "wefwhiihifwe23343", "dmkwlenfwef232323"], n.prop2 = "NOT customer_name IS NULL AND NOT dmkwlenfwef232323 IS NULL" RETURN n.prop4 +---- ok +-STATEMENT MERGE (n:test { prop4: "sdnjb232*23ksfew" }) SET n.prop0 = "fw", n.prop1 = ["wefwhiihifwe23343", "dmkwlenfwef232323"], n.prop2 = "wefwhiihifwe23343 > 5" RETURN n.prop4 +---- ok +-STATEMENT MERGE (n:test { prop4: "dsnfjwne*&232" }) SET n.prop0 = "tweee" RETURN n.prop4 +---- ok +-STATEMENT MERGE (n:test { prop4: "nsdwew*232njfds^" }) SET n.prop0 = "fw" RETURN n.prop4 +---- ok +-STATEMENT MERGE (n:test { prop4: "nsdwew*232njfds^" }) SET n.prop0 = "fw" RETURN n.prop4 +---- ok +-STATEMENT MERGE (n:test { prop4: "fwsdmwfnw&" }) SET n.prop0 = "sds" RETURN n.prop4 +---- ok +-STATEMENT MATCH (n:test) WHERE n.prop4 = "efwb2143d10ccfw" RETURN n.prop1 +---- 1 +[eee,wefwhiihifwe23343,dmkwlenfwef232323] diff --git a/test/test_files/issue/issue5.test b/test/test_files/issue/issue5.test new file mode 100644 index 00000000000..487b6131b8a --- /dev/null +++ b/test/test_files/issue/issue5.test @@ -0,0 +1,13 @@ +-GROUP IssueTest +-DATASET CSV ldbc-sf01 + +-- + +-CASE 3188 +-STATEMENT MATCH (a:Comment) RETURN a.id ORDER BY a.length, a.browserUsed, a.locationIP, a.creationDate, a.content, a.id limit 5; +---- 5 +68719546388 +68719764543 +137438958893 +137439023070 +137439023073 diff --git a/test/test_files/ldbc/ldbc-interactive/interactive-short-parquet.disabled b/test/test_files/ldbc/ldbc-interactive/interactive-short-parquet.test similarity index 69% rename from test/test_files/ldbc/ldbc-interactive/interactive-short-parquet.disabled rename to test/test_files/ldbc/ldbc-interactive/interactive-short-parquet.test index d89129ac1b0..1a2cafdfa1e 100644 --- a/test/test_files/ldbc/ldbc-interactive/interactive-short-parquet.disabled +++ b/test/test_files/ldbc/ldbc-interactive/interactive-short-parquet.test @@ -1,9 +1,7 @@ -# FIXME: this test is failing on Parquet dataset -GROUP LDBCTest -DATASET PARQUET CSV_TO_PARQUET(ldbc-sf01) -BUFFER_POOL_SIZE 1073741824 -SKIP - -- -CASE LDBCInteractiveShortParquet @@ -22,6 +20,20 @@ ---- 1 Mahinda|Perera|19891203|119.235.7.103|Firefox|1353|male|20100214153210447 +# IS2 should be changed to use Kleene Star relationship once that is implemented. +# The 'Case When' statement should be supported as coalesce(). +-LOG IS2 +-STATEMENT MATCH (:Person {id: 21990232555803})<-[:Post_hasCreator|:Comment_hasCreator]-(message) + WITH message,message.id AS messageId, message.creationDate AS messageCreationDate + ORDER BY messageCreationDate DESC, messageId ASC LIMIT 10 + MATCH (message)-[:replyOf_Post|:replyOf_Comment*1..2]->(post:Post), (post)-[:Post_hasCreator]->(person) + RETURN messageId, CASE WHEN message.imageFile is NULL THEN message.content ELSE message.imageFile END AS messageContent, messageCreationDate, post.id AS postId, person.id AS personId, person.firstName AS personFirstName, person.lastName AS personLastName + ORDER BY messageCreationDate DESC, messageId ASC; +---- 3 +1030792343617|About H•A•M, d Kanye West, released as the first single from their collaborati|20120823142307823|1030792343610|21990232556463|Victor|Antonescu +1030792343876|thx|20120818110412997|1030792343869|21990232555803|Carlos|Lopez +1030792343986|fine|20120810030544084|1030792343978|21990232556837|Bing|Li + -LOG IS3 -STATEMENT MATCH (n:Person {id: 1129})-[r:knows]-(friend) RETURN friend.id AS personId, @@ -58,17 +70,11 @@ Mahinda|Perera|19891203|119.235.7.103|Firefox|1353|male|20100214153210447 2199023256077|Ibrahim Bare|Ousmane # IS6 should be changed to use Kleene Star relationship once that is implemented -# This query is currently commented out, but will work as soon as multilabelled recursive rels are merged to master. -# -LOG IS6 -# -STATEMENT MATCH (m:Comment {id: 962072675825 })-[:replyOf_Post|:replyOf_Comment*1..2]->(p:Post)<-[:containerOf]-(f:Forum)-[:hasModerator]->(mod:Person) -# RETURN -# f.id AS forumId, -# f.title AS forumTitle, -# mod.id AS moderatorId, -# mod.firstName AS moderatorFirstName, -# mod.lastName AS moderatorLastName; -# ---- 1 -# 687194767491|Wall of Faisal Malik|21990232556585|Faisal|Malik +-LOG IS6 +-STATEMENT MATCH (m:Comment {id: 962072675825 })-[:replyOf_Post|:replyOf_Comment*1..2]->(p:Post)<-[:containerOf]-(f:Forum)-[:hasModerator]->(mod:Person) + RETURN f.id AS forumId,f.title AS forumTitle,mod.id AS moderatorId,mod.firstName AS moderatorFirstName, mod.lastName AS moderatorLastName; +---- 1 +687194767491|Wall of Faisal Malik|21990232556585|Faisal|Malik -LOG IS7 -STATEMENT MATCH (m:Post:Comment {id: 962072971887})<-[:replyOf_Comment|:replyOf_Post]-(c:Comment)-[:Comment_hasCreator]->(p:Person) diff --git a/test/test_files/lsqb/lsqb_queries_parquet.disabled b/test/test_files/lsqb/lsqb_queries_parquet.test similarity index 99% rename from test/test_files/lsqb/lsqb_queries_parquet.disabled rename to test/test_files/lsqb/lsqb_queries_parquet.test index 52497b65ed1..1694656414f 100644 --- a/test/test_files/lsqb/lsqb_queries_parquet.disabled +++ b/test/test_files/lsqb/lsqb_queries_parquet.test @@ -2,7 +2,6 @@ -DATASET PARQUET CSV_TO_PARQUET(lsqb-sf01) -BUFFER_POOL_SIZE 1073741824 -SKIP - -- -CASE LSQBTestParquet diff --git a/test/test_files/order_by/order_by_parquet.test b/test/test_files/order_by/order_by_parquet.test index 7e59732e506..6b587d3c682 100644 --- a/test/test_files/order_by/order_by_parquet.test +++ b/test/test_files/order_by/order_by_parquet.test @@ -10,7 +10,6 @@ -GROUP OrderByTests -DATASET PARQUET CSV_TO_PARQUET(order-by-tests) --SKIP -- diff --git a/test/test_files/read_list/large_adj_list_parquet.test b/test/test_files/read_list/large_adj_list_parquet.test index 5012aad2158..629908f427a 100644 --- a/test/test_files/read_list/large_adj_list_parquet.test +++ b/test/test_files/read_list/large_adj_list_parquet.test @@ -1,6 +1,5 @@ -GROUP EndToEndReadLargeListsTest -DATASET PARQUET CSV_TO_PARQUET(read-list-tests/large-list) --SKIP -- diff --git a/test/test_files/shortest_path/bfs_sssp_parquet.test b/test/test_files/shortest_path/bfs_sssp_parquet.test index 6fdaa31dbaa..fde3cc4253f 100644 --- a/test/test_files/shortest_path/bfs_sssp_parquet.test +++ b/test/test_files/shortest_path/bfs_sssp_parquet.test @@ -1,42 +1,41 @@ -GROUP ShortestPathTest -DATASET PARQUET CSV_TO_PARQUET(shortest-path-tests) --SKIP # Timestamp and Date columns are written as strings in parquet file. Parquet reader should support casting operations. -- -CASE BfsParquet -LOG SingleSourceAllDestinationsSSP --STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE a.fName = 'Alice' RETURN a.fName, b.fName, rels(r), properties(nodes(r), 'fName') +-STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE a.fName = 'Alice' RETURN a.fName, b.fName, properties(nodes(r), 'fName') ---- 7 -Alice|Bob|[(0:0)-{_LABEL: knows, _ID: 1:0}->(0:1)]|[] -Alice|Carol|[(0:0)-{_LABEL: knows, _ID: 1:1}->(0:2)]|[] -Alice|Dan|[(0:0)-{_LABEL: knows, _ID: 1:2}->(0:3)]|[] -Alice|Elizabeth|[(0:0)-{_LABEL: knows, _ID: 1:0}->(0:1),(0:1)-{_LABEL: knows, _ID: 1:6}->(0:4)]|[Bob] -Alice|Farooq|[(0:0)-{_LABEL: knows, _ID: 1:0}->(0:1),(0:1)-{_LABEL: knows, _ID: 1:6}->(0:4),(0:4)-{_LABEL: knows, _ID: 1:13}->(0:5)]|[Bob,Elizabeth] -Alice|Greg|[(0:0)-{_LABEL: knows, _ID: 1:0}->(0:1),(0:1)-{_LABEL: knows, _ID: 1:6}->(0:4),(0:4)-{_LABEL: knows, _ID: 1:14}->(0:6)]|[Bob,Elizabeth] -Alice|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|[(0:0)-{_LABEL: knows, _ID: 1:0}->(0:1),(0:1)-{_LABEL: knows, _ID: 1:6}->(0:4),(0:4)-{_LABEL: knows, _ID: 1:15}->(0:7)]|[Bob,Elizabeth] +Alice|Bob|[] +Alice|Carol|[] +Alice|Dan|[] +Alice|Elizabeth|[Bob] +Alice|Farooq|[Bob,Elizabeth] +Alice|Greg|[Bob,Elizabeth] +Alice|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|[Bob,Elizabeth] -LOG AllSourcesSingleDestinationQuery --STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE b.fName = 'Alice' RETURN a.fName, b.fName, rels(r), properties(nodes(r), 'usedNames') +-STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE b.fName = 'Alice' RETURN a.fName, b.fName, properties(nodes(r), 'usedNames') ---- 6 -Bob|Alice|[(0:0)-{_LABEL: knows, _ID: 1:3}->(0:1)]|[] -Carol|Alice|[(0:0)-{_LABEL: knows, _ID: 1:7}->(0:2)]|[] -Dan|Alice|[(0:0)-{_LABEL: knows, _ID: 1:10}->(0:3)]|[] -Elizabeth|Alice|[(0:0)-{_LABEL: knows, _ID: 1:20}->(0:7),(0:7)-{_LABEL: knows, _ID: 1:15}->(0:4)]|[[Ad,De,Hi,Kye,Orlan]] -Farooq|Alice|[(0:0)-{_LABEL: knows, _ID: 1:20}->(0:7),(0:7)-{_LABEL: knows, _ID: 1:17}->(0:5)]|[[Ad,De,Hi,Kye,Orlan]] -Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|Alice|[(0:0)-{_LABEL: knows, _ID: 1:20}->(0:7)]|[] +Bob|Alice|[] +Carol|Alice|[] +Dan|Alice|[] +Elizabeth|Alice|[[Ad,De,Hi,Kye,Orlan]] +Farooq|Alice|[[Ad,De,Hi,Kye,Orlan]] +Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|Alice|[] -LOG SingleSourceWithAllProperties --STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE a.fName = 'Alice' RETURN length(r), b, a +-STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE a.fName = 'Alice' RETURN length(r), b.*, a.* ---- 7 -1|{_ID: 0:1, _LABEL: person, ID: 2, fName: Bob, gender: 2, isStudent: True, isWorker: False, age: 30, eyeSight: 5.100000, birthdate: 1900-01-01, registerTime: 2008-11-03 15:25:30.000526, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [12,8], usedNames: [Bobby], courseScoresPerTerm: [[8,9],[9,10]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} -1|{_ID: 0:2, _LABEL: person, ID: 3, fName: Carol, gender: 1, isStudent: False, isWorker: True, age: 45, eyeSight: 5.000000, birthdate: 1940-06-22, registerTime: 1911-08-20 02:32:21, lastJobDuration: 48:24:11, workedHours: [4,5], usedNames: [Carmen,Fred], courseScoresPerTerm: [[8,10]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} -1|{_ID: 0:3, _LABEL: person, ID: 5, fName: Dan, gender: 2, isStudent: False, isWorker: True, age: 20, eyeSight: 4.800000, birthdate: 1950-07-23, registerTime: 2031-11-30 12:25:30, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1,9], usedNames: [Wolfeschlegelstein,Daniel], courseScoresPerTerm: [[7,4],[8,8],[9]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} -2|{_ID: 0:4, _LABEL: person, ID: 7, fName: Elizabeth, gender: 1, isStudent: False, isWorker: True, age: 20, eyeSight: 4.700000, birthdate: 1980-10-26, registerTime: 1976-12-23 11:21:42, lastJobDuration: 48:24:11, workedHours: [2], usedNames: [Ein], courseScoresPerTerm: [[6],[7],[8]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} -3|{_ID: 0:5, _LABEL: person, ID: 8, fName: Farooq, gender: 2, isStudent: True, isWorker: False, age: 25, eyeSight: 4.500000, birthdate: 1980-10-26, registerTime: 1972-07-31 13:22:30.678559, lastJobDuration: 00:18:00.024, workedHours: [3,4,5,6,7], usedNames: [Fesdwe], courseScoresPerTerm: [[8]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} -3|{_ID: 0:6, _LABEL: person, ID: 9, fName: Greg, gender: 2, isStudent: False, isWorker: False, age: 40, eyeSight: 4.900000, birthdate: 1980-10-26, registerTime: 1976-12-23 04:41:42, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1], usedNames: [Grad], courseScoresPerTerm: [[10]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} -3|{_ID: 0:7, _LABEL: person, ID: 10, fName: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff, gender: 2, isStudent: False, isWorker: True, age: 83, eyeSight: 4.900000, birthdate: 1990-11-27, registerTime: 2023-02-21 13:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,11,12,3,4,5,6,7], usedNames: [Ad,De,Hi,Kye,Orlan], courseScoresPerTerm: [[7],[10],[6,7]]}|{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]]} +1|2|Bob|2|True|False|30|5.100000|1900-01-01|2008-11-03 15:25:30.000526|10 years 5 months 13:00:00|[12,8]|[Bobby]|[[8,9],[9,10]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] +1|3|Carol|1|False|True|45|5.000000|1940-06-22|1911-08-20 02:32:21|48:24:11|[4,5]|[Carmen,Fred]|[[8,10]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] +1|5|Dan|2|False|True|20|4.800000|1950-07-23|2031-11-30 12:25:30|10 years 5 months 13:00:00|[1,9]|[Wolfeschlegelstein,Daniel]|[[7,4],[8,8],[9]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] +2|7|Elizabeth|1|False|True|20|4.700000|1980-10-26|1976-12-23 11:21:42|48:24:11|[2]|[Ein]|[[6],[7],[8]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] +3|10|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|2|False|True|83|4.900000|1990-11-27|2023-02-21 13:25:30|3 years 2 days 13:02:00|[10,11,12,3,4,5,6,7]|[Ad,De,Hi,Kye,Orlan]|[[7],[10],[6,7]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] +3|8|Farooq|2|True|False|25|4.500000|1980-10-26|1972-07-31 13:22:30.678559|00:18:00.024|[3,4,5,6,7]|[Fesdwe]|[[8]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] +3|9|Greg|2|False|False|40|4.900000|1980-10-26|1976-12-23 04:41:42|10 years 5 months 13:00:00|[1]|[Grad]|[[10]]|0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]] -LOG SingleSourceSingleDestination -STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE a.fName = 'Alice' AND b.fName = 'Bob' RETURN a.fName, b.fName, length(r) @@ -44,13 +43,13 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|Alice|[(0:0)-{_LABEL: knows, _ Alice|Bob|1 -LOG SingleSourceAllDestinations2 --STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..2]->(b:person) WHERE a.fName = 'Elizabeth' RETURN a.fName, b.fName, rels(r), properties(nodes(r), '_Label') +-STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..2]->(b:person) WHERE a.fName = 'Elizabeth' RETURN a.fName, b.fName, properties(nodes(r), '_Label') ---- 5 -Elizabeth|Alice|[(0:4)-{_LABEL: knows, _ID: 1:15}->(0:7),(0:7)-{_LABEL: knows, _ID: 1:20}->(0:0)]|[person] -Elizabeth|Dan|[(0:4)-{_LABEL: knows, _ID: 1:15}->(0:7),(0:7)-{_LABEL: knows, _ID: 1:21}->(0:3)]|[person] -Elizabeth|Farooq|[(0:4)-{_LABEL: knows, _ID: 1:13}->(0:5)]|[] -Elizabeth|Greg|[(0:4)-{_LABEL: knows, _ID: 1:14}->(0:6)]|[] -Elizabeth|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|[(0:4)-{_LABEL: knows, _ID: 1:15}->(0:7)]|[] +Elizabeth|Alice|[person] +Elizabeth|Dan|[person] +Elizabeth|Farooq|[] +Elizabeth|Greg|[] +Elizabeth|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|[] -LOG SingleSourceUnreachableDestination -STATEMENT MATCH (a:person)-[r:knows* SHORTEST 1..30]->(b:person) WHERE a.fName = 'Alice' AND b.fName = 'Alice11' RETURN a.fName, b.fName, r diff --git a/test/test_files/tck/expressions/list/List1.test b/test/test_files/tck/expressions/list/List1.test index fe1608680f5..e2f393bfa90 100644 --- a/test/test_files/tck/expressions/list/List1.test +++ b/test/test_files/tck/expressions/list/List1.test @@ -80,21 +80,21 @@ # RETURN list[idx]; #---- error #Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(BOOL,INT64). Supported inputs are -#(VAR_LIST,INT64) -> ANY +#(LIST,INT64) -> ANY #(STRING,INT64) -> STRING -STATEMENT WITH 123 AS list, 0 AS idx RETURN list[idx]; ---- error Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(INT64,INT64). Supported inputs are -(VAR_LIST,INT64) -> ANY +(LIST,INT64) -> ANY (STRING,INT64) -> STRING -STATEMENT WITH 4.7 AS list, 0 AS idx RETURN list[idx]; ---- error Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(DOUBLE,INT64). Supported inputs are -(VAR_LIST,INT64) -> ANY +(LIST,INT64) -> ANY (STRING,INT64) -> STRING # Fail when indexing with a non-integer #Example: boolean @@ -103,34 +103,39 @@ Binder exception: Cannot match a built-in function for given function LIST_EXTRA -STATEMENT WITH [1, 2, 3, 4, 5] AS list, true AS idx RETURN list[idx]; ---- error -Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(VAR_LIST,BOOL). Supported inputs are -(VAR_LIST,INT64) -> ANY +Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(INT64[],BOOL). Supported inputs are +(LIST,INT64) -> ANY (STRING,INT64) -> STRING +(ARRAY,INT64) -> ANY -STATEMENT WITH [1, 2, 3, 4, 5] AS list, 4.7 AS idx RETURN list[idx]; ---- error -Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(VAR_LIST,DOUBLE). Supported inputs are -(VAR_LIST,INT64) -> ANY +Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(INT64[],DOUBLE). Supported inputs are +(LIST,INT64) -> ANY (STRING,INT64) -> STRING +(ARRAY,INT64) -> ANY -STATEMENT WITH [1, 2, 3, 4, 5] AS list, '1' AS idx RETURN list[idx]; ---- error -Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(VAR_LIST,STRING). Supported inputs are -(VAR_LIST,INT64) -> ANY +Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(INT64[],STRING). Supported inputs are +(LIST,INT64) -> ANY (STRING,INT64) -> STRING +(ARRAY,INT64) -> ANY -STATEMENT WITH [1, 2, 3, 4, 5] AS list, [1] AS idx RETURN list[idx]; ---- error -Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(VAR_LIST,VAR_LIST). Supported inputs are -(VAR_LIST,INT64) -> ANY +Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(INT64[],INT64[]). Supported inputs are +(LIST,INT64) -> ANY (STRING,INT64) -> STRING +(ARRAY,INT64) -> ANY -STATEMENT WITH [1, 2, 3, 4, 5] AS list, {x: 3} AS idx RETURN list[idx]; ---- error -Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(VAR_LIST,STRUCT). Supported inputs are -(VAR_LIST,INT64) -> ANY +Binder exception: Cannot match a built-in function for given function LIST_EXTRACT(INT64[],STRUCT(x:INT64)). Supported inputs are +(LIST,INT64) -> ANY (STRING,INT64) -> STRING +(ARRAY,INT64) -> ANY diff --git a/test/test_files/tck/expressions/list/List11.test b/test/test_files/tck/expressions/list/List11.test index 1e8e2cbb04e..5e617174f41 100644 --- a/test/test_files/tck/expressions/list/List11.test +++ b/test/test_files/tck/expressions/list/List11.test @@ -200,294 +200,294 @@ Runtime exception: Step of range cannot be 0. ## Outcome: an Error should be raised at runtime: InvalidArgumentType ---- error Binder exception: Cannot match a built-in function for given function RANGE(BOOL,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, true, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,BOOL,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1, true); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,BOOL). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(-1.1, 1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(DOUBLE,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(-0.0, 1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(DOUBLE,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0.0, 1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(DOUBLE,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(1.1, 1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(DOUBLE,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, -1.1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,DOUBLE,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, -0.0, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,DOUBLE,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 0.0, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,DOUBLE,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1.1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,DOUBLE,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1, -1.1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,DOUBLE). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1, 1.1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,DOUBLE). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range('xyz', 1, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(STRING,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 'xyz', 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,STRING,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1, 'xyz'); ---- error Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,STRING). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range([0], 1, 1); ---- error -Binder exception: Cannot match a built-in function for given function RANGE(VAR_LIST,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +Binder exception: Cannot match a built-in function for given function RANGE(INT64[],INT64,INT64). Supported inputs are +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, [1], 1); ---- error -Binder exception: Cannot match a built-in function for given function RANGE(INT64,VAR_LIST,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64[],INT64). Supported inputs are +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1, [1]); ---- error -Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,VAR_LIST). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,INT64[]). Supported inputs are +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range({start: 0}, 1, 1); ---- error -Binder exception: Cannot match a built-in function for given function RANGE(STRUCT,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +Binder exception: Cannot match a built-in function for given function RANGE(STRUCT(start:INT64),INT64,INT64). Supported inputs are +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(0, 1, {step: 1}); ---- error -Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,STRUCT). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +Binder exception: Cannot match a built-in function for given function RANGE(INT64,INT64,STRUCT(step:INT64)). Supported inputs are +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST diff --git a/test/test_files/tck/match/match2.test b/test/test_files/tck/match/match2.test index e8eb7d79f33..4c06b5229e4 100644 --- a/test/test_files/tck/match/match2.test +++ b/test/test_files/tck/match/match2.test @@ -380,7 +380,7 @@ Binder exception: r has data type DOUBLE but (REL) was expected. Binder exception: r has data type STRING but (REL) was expected. -STATEMENT WITH [10] AS r MATCH ()-[r]-() RETURN r; ---- error -Binder exception: r has data type VAR_LIST but (REL) was expected. +Binder exception: r has data type LIST but (REL) was expected. -STATEMENT WITH {x: 1} AS r MATCH ()-[r]-() RETURN r; ---- error Binder exception: r has data type STRUCT but (REL) was expected. diff --git a/test/test_files/tck/match/match4.test b/test/test_files/tck/match/match4.test index dcc2c42d620..9802b38c3ca 100644 --- a/test/test_files/tck/match/match4.test +++ b/test/test_files/tck/match/match4.test @@ -66,7 +66,7 @@ ---- ok -STATEMENT CREATE REL TABLE T(FROM A TO A); ---- ok -# indexing on varlist causes segmentaion fault +# indexing on list causes segmentaion fault -STATEMENT CREATE (a {var: -2}), (b {var: 0}) WITH * UNWIND range(1, 20) AS i @@ -160,7 +160,7 @@ Binder exception: Bind relationship r to relationship with same name is not supp MATCH (first)-[rs*]->(second) RETURN first, second; ---- error -Binder exception: rs has data type VAR_LIST but (RECURSIVE_REL) was expected. +Binder exception: rs has data type LIST but (RECURSIVE_REL) was expected. # Fail when asterisk operator is missing # Fail on negative bound diff --git a/test/test_files/tinysnb/agg/hash.test b/test/test_files/tinysnb/agg/hash.test index 34721c83a4f..4bcb6eaa913 100644 --- a/test/test_files/tinysnb/agg/hash.test +++ b/test/test_files/tinysnb/agg/hash.test @@ -5,6 +5,16 @@ -CASE AggHash +-STATEMENT MATCH (a:person) OPTIONAL MATCH (a)-[:knows]->(b:person) WHERE b.ID > 3 WITH a.fName AS n, COLLECT(b) AS b_list RETURN n, size(b_list) +---- 8 +Alice|1 +Bob|1 +Carol|1 +Dan| +Elizabeth|2 +Farooq| +Greg| +Hubert Blaine Wolfeschlegelsteinhausenbergerdorff| -STATEMENT MATCH (a:person)-[r:knows]->(b:person) WHERE a.ID=0 RETURN r, COUNT(*) -ENUMERATE ---- 3 @@ -343,7 +353,7 @@ True|\xAB\xCD {_ID: 0:2, _LABEL: person, ID: 3, fName: Carol, gender: 1, isStudent: False, isWorker: True, age: 45, eyeSight: 5.000000, birthdate: 1940-06-22, registerTime: 1911-08-20 02:32:21, lastJobDuration: 48:24:11, workedHours: [4,5], usedNames: [Carmen,Fred], courseScoresPerTerm: [[8,10]], grades: [91,75,21,95], height: 1.000000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13}|9 {_ID: 0:3, _LABEL: person, ID: 5, fName: Dan, gender: 2, isStudent: False, isWorker: True, age: 20, eyeSight: 4.800000, birthdate: 1950-07-23, registerTime: 2031-11-30 12:25:30, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1,9], usedNames: [Wolfeschlegelstein,Daniel], courseScoresPerTerm: [[7,4],[8,8],[9]], grades: [76,88,99,89], height: 1.300000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14}|9 --CASE VarListHashTest +-CASE ListHashTest -STATEMENT CREATE (:person {ID: 17, usedNames: ['Alice'], workedHours: [1,2,3], courseScoresPerTerm: [[1,2],[3,4]]}) ---- ok -STATEMENT CREATE (:person {ID: 25, usedNames: ['Carmen'], workedHours: [10, 5], courseScoresPerTerm: [[1,2],[3,4]]}) @@ -546,3 +556,30 @@ True|2 {rating: 7.000000, stars: 10, views: 982, release: 2018-11-13 13:33:11, release_ns: 2018-11-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2018-11-13 13:33:11, release_tz: 2018-11-13 13:33:11.123456+00, film: 2014-09-12, u8: 12, u16: 120, u32: 55, u64: 1, hugedata: -1844674407370955161511}|2 {rating: 1223.000000, stars: 100, views: 10003, release: 2011-02-11 16:44:22, release_ns: 2011-02-11 16:44:22.123456, release_ms: 2011-02-11 16:44:22.123, release_sec: 2011-02-11 16:44:22, release_tz: 2011-02-11 16:44:22.123456+00, film: 2013-02-22, u8: 1, u16: 15, u32: 200, u64: 4, hugedata: -15}|2 {rating: 55.000000, stars: 2, views: 88, release: 2022-01-22 00:00:00, release_ns: 2025-01-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2011-01-11 00:00:00, release_tz: 2011-11-11 00:00:00+00, film: 2022-01-11, u8: 3, u16: 22, u32: 22, u64: 56, hugedata: 999999}|1 + +-LOG HashOnListOfStruct +-STATEMENT CREATE (:organisation {ID: 22}) +---- ok +-STATEMENT MATCH (o:organisation) RETURN [o.state], count(*) +---- 5 +[{revenue: 138, location: ['toronto','montr,eal'], stock: {price: [96,56], volume: 1000}}]|2 +[{revenue: 152, location: ["vanco,uver north area"], stock: {price: [15,78,671], volume: 432}}]|1 +[{revenue: 55, location: ['toronto'], stock: {price: [22,33], volume: 28}}]|1 +[{revenue: 558, location: ['very long city name','new york'], stock: {price: [22], volume: 99}}]|2 +[]|1 +-STATEMENT MATCH (m:movies) RETURN [m.description], count(*) +---- 4 +[{rating: 5.300000, stars: 2, views: 152, release: 2011-08-20 11:25:30, release_ns: 2011-08-20 11:25:30.123456, release_ms: 2011-08-20 11:25:30.123, release_sec: 2011-08-20 11:25:30, release_tz: 2011-08-20 11:25:30.123456+00, film: 2012-05-11, u8: 220, u16: 20, u32: 1, u64: 180, hugedata: 1844674407370955161811111111}]|1 +[{rating: 7.000000, stars: 10, views: 982, release: 2018-11-13 13:33:11, release_ns: 2018-11-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2018-11-13 13:33:11, release_tz: 2018-11-13 13:33:11.123456+00, film: 2014-09-12, u8: 12, u16: 120, u32: 55, u64: 1, hugedata: -1844674407370955161511}]|2 +[{rating: 1223.000000, stars: 100, views: 10003, release: 2011-02-11 16:44:22, release_ns: 2011-02-11 16:44:22.123456, release_ms: 2011-02-11 16:44:22.123, release_sec: 2011-02-11 16:44:22, release_tz: 2011-02-11 16:44:22.123456+00, film: 2013-02-22, u8: 1, u16: 15, u32: 200, u64: 4, hugedata: -15}]|2 +[{rating: 55.000000, stars: 2, views: 88, release: 2022-01-22 00:00:00, release_ns: 2025-01-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2011-01-11 00:00:00, release_tz: 2011-11-11 00:00:00+00, film: 2022-01-11, u8: 3, u16: 22, u32: 22, u64: 56, hugedata: 999999}]|1 +-STATEMENT MATCH (o:organisation) RETURN distinct [o.state]; +---- 5 +[{revenue: 138, location: ['toronto','montr,eal'], stock: {price: [96,56], volume: 1000}}] +[{revenue: 152, location: ["vanco,uver north area"], stock: {price: [15,78,671], volume: 432}}] +[{revenue: 55, location: ['toronto'], stock: {price: [22,33], volume: 28}}] +[{revenue: 558, location: ['very long city name','new york'], stock: {price: [22], volume: 99}}] +[] +-STATEMENT MATCH (p:person) return distinct collect(p); +---- 1 +[{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:1, _LABEL: person, ID: 2, fName: Bob, gender: 2, isStudent: True, isWorker: False, age: 30, eyeSight: 5.100000, birthdate: 1900-01-01, registerTime: 2008-11-03 15:25:30.000526, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [12,8], usedNames: [Bobby], courseScoresPerTerm: [[8,9],[9,10]], grades: [98,42,93,88], height: 0.990000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12},{_ID: 0:2, _LABEL: person, ID: 3, fName: Carol, gender: 1, isStudent: False, isWorker: True, age: 45, eyeSight: 5.000000, birthdate: 1940-06-22, registerTime: 1911-08-20 02:32:21, lastJobDuration: 48:24:11, workedHours: [4,5], usedNames: [Carmen,Fred], courseScoresPerTerm: [[8,10]], grades: [91,75,21,95], height: 1.000000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13},{_ID: 0:3, _LABEL: person, ID: 5, fName: Dan, gender: 2, isStudent: False, isWorker: True, age: 20, eyeSight: 4.800000, birthdate: 1950-07-23, registerTime: 2031-11-30 12:25:30, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1,9], usedNames: [Wolfeschlegelstein,Daniel], courseScoresPerTerm: [[7,4],[8,8],[9]], grades: [76,88,99,89], height: 1.300000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14},{_ID: 0:4, _LABEL: person, ID: 7, fName: Elizabeth, gender: 1, isStudent: False, isWorker: True, age: 20, eyeSight: 4.700000, birthdate: 1980-10-26, registerTime: 1976-12-23 11:21:42, lastJobDuration: 48:24:11, workedHours: [2], usedNames: [Ein], courseScoresPerTerm: [[6],[7],[8]], grades: [96,59,65,88], height: 1.463000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15},{_ID: 0:5, _LABEL: person, ID: 8, fName: Farooq, gender: 2, isStudent: True, isWorker: False, age: 25, eyeSight: 4.500000, birthdate: 1980-10-26, registerTime: 1972-07-31 13:22:30.678559, lastJobDuration: 00:18:00.024, workedHours: [3,4,5,6,7], usedNames: [Fesdwe], courseScoresPerTerm: [[8]], grades: [80,78,34,83], height: 1.510000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16},{_ID: 0:6, _LABEL: person, ID: 9, fName: Greg, gender: 2, isStudent: False, isWorker: False, age: 40, eyeSight: 4.900000, birthdate: 1980-10-26, registerTime: 1976-12-23 04:41:42, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1], usedNames: [Grad], courseScoresPerTerm: [[10]], grades: [43,83,67,43], height: 1.600000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17},{_ID: 0:7, _LABEL: person, ID: 10, fName: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff, gender: 2, isStudent: False, isWorker: True, age: 83, eyeSight: 4.900000, birthdate: 1990-11-27, registerTime: 2023-02-21 13:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,11,12,3,4,5,6,7], usedNames: [Ad,De,Hi,Kye,Orlan], courseScoresPerTerm: [[7],[10],[6,7]], grades: [77,64,100,54], height: 1.323000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18}] diff --git a/test/test_files/tinysnb/call/call.test b/test/test_files/tinysnb/call/call.test index f484e75a1c6..a57978c3d25 100644 --- a/test/test_files/tinysnb/call/call.test +++ b/test/test_files/tinysnb/call/call.test @@ -42,6 +42,30 @@ Binder exception: Upper bound of rel exceeds maximum: 10. ---- 1 354290 +-LOG SetGetProgressBar +-STATEMENT CALL progress_bar=true +---- ok +-STATEMENT CALL current_setting('progress_bar') RETURN * +---- 1 +True +-STATEMENT CALL progress_bar=false +---- ok +-STATEMENT CALL current_setting('progress_bar') RETURN * +---- 1 +False + +-LOG SetGetProgressBarTime +-STATEMENT CALL progress_bar_time=4000 +---- ok +-STATEMENT CALL current_setting('progress_bar_time') RETURN * +---- 1 +4000 +-STATEMENT CALL progress_bar_time=0 +---- ok +-STATEMENT CALL current_setting('progress_bar_time') RETURN * +---- 1 +0 + -LOG disableSemihMaskOptimization -STATEMENT CALL enable_semi_mask=true ---- ok @@ -195,10 +219,10 @@ Binder exception: Cannot evaluate a.fName as a literal. 8 -STATEMENT CALL storage_info('person') RETURN COUNT(*) ---- 1 -37 +38 -STATEMENT CALL storage_info('knows') RETURN COUNT(*) ---- 1 -82 +80 -STATEMENT CALL storage_info('workAt') RETURN COUNT(*) ---- 1 22 diff --git a/test/test_files/tinysnb/cast/cast_error.test b/test/test_files/tinysnb/cast/cast_error.test index 7d2f1998bf0..74cbc2b7be6 100644 --- a/test/test_files/tinysnb/cast/cast_error.test +++ b/test/test_files/tinysnb/cast/cast_error.test @@ -581,24 +581,24 @@ Conversion exception: Cast failed. bool is not in INT64[] range. Conversion exception: Cast failed. [[231|4324] is not in INT64[][] range. -CASE CastStringToNestedError --STATEMENT LOAD WITH HEADERS (list STRING[][]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/delim_error.csv" (DELIM="|", ESCAPE="~", QUOTE="'") RETURN * ; +-STATEMENT LOAD WITH HEADERS (list STRING[][]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/delim_error.csv" (DELIM="|", ESCAPE="~", QUOTE="'") RETURN * ; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/delim_error.csv on line 1: Conversion exception: Cast failed. "[[hello],[bdfadf],]" is not in STRING[][] range. --STATEMENT LOAD WITH HEADERS (list STRING[][]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/bracket_error.csv" (DELIM="|", ESCAPE="~") RETURN * ; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/delim_error.csv on line 1: Conversion exception: Cast failed. "[[hello],[bdfadf],]" is not in STRING[][] range. +-STATEMENT LOAD WITH HEADERS (list STRING[][]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/bracket_error.csv" (DELIM="|", ESCAPE="~") RETURN * ; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/bracket_error.csv on line 1: Conversion exception: Cast failed. [[] is not in STRING[][] range. --STATEMENT LOAD WITH HEADERS (list STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/single_quote.csv" RETURN *; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/bracket_error.csv on line 1: Conversion exception: Cast failed. [[] is not in STRING[][] range. +-STATEMENT LOAD WITH HEADERS (list STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/single_quote.csv" RETURN *; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/single_quote.csv on line 1: Conversion exception: Cast failed. ['fdsfdsfe werw] is not in STRING[] range. --STATEMENT LOAD WITH HEADERS (list STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/single_quote2.csv" RETURN *; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/single_quote.csv on line 1: Conversion exception: Cast failed. ['fdsfdsfe werw] is not in STRING[] range. +-STATEMENT LOAD WITH HEADERS (list STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/single_quote2.csv" RETURN *; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/single_quote2.csv on line 1: Conversion exception: Cast failed. [[' this is a signle quote]] is not in STRING[] range. --STATEMENT LOAD WITH HEADERS (list UINT8[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/single_struct_bracket.csv" RETURN *; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/single_quote2.csv on line 1: Conversion exception: Cast failed. [[' this is a signle quote]] is not in STRING[] range. +-STATEMENT LOAD WITH HEADERS (list UINT8[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/single_struct_bracket.csv" RETURN *; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/single_struct_bracket.csv on line 1: Conversion exception: Cast failed. [{32, 32] is not in UINT8[] range. --STATEMENT LOAD WITH HEADERS (list UINT8[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/conversion_error.csv" RETURN *; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/single_struct_bracket.csv on line 1: Conversion exception: Cast failed. [{32, 32] is not in UINT8[] range. +-STATEMENT LOAD WITH HEADERS (list UINT8[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/conversion_error.csv" RETURN *; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/conversion_error.csv on line 1: Conversion exception: Cast failed. Could not convert "432412" to UINT8. +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/conversion_error.csv on line 1: Conversion exception: Cast failed. Could not convert "432412" to UINT8. -STATEMENT LOAD WITH HEADERS (q STRUCT(a STRUCT(b STRING))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/struct/struct_bracket_error1.csv" RETURN *; ---- error Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/struct/struct_bracket_error1.csv on line 1: Conversion exception: Cast failed. {a: {b: fsdf is not in STRUCT(a:STRUCT(b:STRING)) range. @@ -641,30 +641,18 @@ Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/map/ -STATEMENT LOAD WITH HEADERS (a MAP(UINT16, UINT16[])) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/map/map_no_closing4.csv" RETURN *; ---- error Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/map/map_no_closing4.csv on line 1: Conversion exception: Cast failed. {432=[432,432} is not in MAP(UINT16: UINT16[]) range. --STATEMENT LOAD WITH HEADERS (a INT64[4]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/incorrect_num.csv" RETURN *; +-STATEMENT LOAD WITH HEADERS (a INT64[4]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/incorrect_num.csv" RETURN *; ---- error -Copy exception: Each fixed list should have fixed number of elements. Expected: 4, Actual: 2. --STATEMENT LOAD WITH HEADERS (a STRING[2]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/unsupported_type.csv" RETURN *; +Copy exception: Each array should have fixed number of elements. Expected: 4, Actual: 2. +-STATEMENT LOAD WITH HEADERS (a INT16[1]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/error_conversion.csv" RETURN *; ---- error -Binder exception: The child type of a fixed list must be a numeric type. Given: STRING. --STATEMENT LOAD WITH HEADERS (a INT16[1]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/error_conversion.csv" RETURN *; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/error_conversion.csv on line 1: Conversion exception: Cast failed. Could not convert "4324234543543534534524" to INT16. +-STATEMENT LOAD WITH HEADERS (a INT64[2]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/error_conversion2.csv" RETURN *; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/error_conversion.csv on line 1: Conversion exception: Cast failed. Could not convert "4324234543543534534524" to INT16. --STATEMENT LOAD WITH HEADERS (a INT64[2]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/error_conversion2.csv" RETURN *; +Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/error_conversion2.csv on line 1: Conversion exception: Cast failed. [4324, 432] fewrew is not in INT64[2] range. +-STATEMENT LOAD WITH HEADERS (array INT64[0]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/zero_ele.csv" RETURN *; ---- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/error_conversion2.csv on line 1: Conversion exception: Cast failed. [4324, 432] fewrew is not in INT64[2] range. --STATEMENT LOAD WITH HEADERS (fixedList INT64[0]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/zero_ele.csv" RETURN *; ----- error -Binder exception: The number of elements in a fixed list must be greater than 0. Given: 0. --STATEMENT LOAD WITH HEADERS (fixedList UINT8[1]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/unsupported_type2.csv" RETURN *; ----- error -Unsupported data type: Function::castStringToFixedList --STATEMENT LOAD WITH HEADERS (fixedList INT64[1]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_null.csv" RETURN *; ----- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_null.csv on line 1: Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. --STATEMENT LOAD WITH HEADERS (fixedList INT64[2]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_null2.csv" RETURN *; ----- error -Copy exception: Error in file ${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_null2.csv on line 1: Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. +Binder exception: The number of elements in an array must be greater than 0. Given: 0. -STATEMENT LOAD WITH HEADERS (a UNION(v1 INT64, v2 STRING)) FROM "${KUZU_ROOT_DIRECTORY}/dataset/copy-fault-tests/invalid-utf8/invalid-utf8.csv" RETURN *; ---- error Copy exception: Invalid UTF8-encoded string. @@ -679,13 +667,13 @@ Conversion exception: Cast failed. Could not convert "-32769" to INT16. Conversion exception: Cast failed. [42, 42] fdaf is not in INT64[2] range. -STATEMENT RETURN cast("[42|42]", "DOUBLE[2]"); ---- error -Copy exception: Each fixed list should have fixed number of elements. Expected: 2, Actual: 1. +Copy exception: Each array should have fixed number of elements. Expected: 2, Actual: 1. -STATEMENT RETURN cast("[42,42", "FLOAT[2]"); ---- error -Copy exception: Each fixed list should have fixed number of elements. Expected: 2, Actual: 1. +Copy exception: Each array should have fixed number of elements. Expected: 2, Actual: 1. -STATEMENT RETURN cast("(42,42)", "INT32[2]"); ---- error -Copy exception: Each fixed list should have fixed number of elements. Expected: 2, Actual: 0. +Copy exception: Each array should have fixed number of elements. Expected: 2, Actual: 0. -LOG InvalidCastTypeError -STATEMENT RETURN cast("dfsa", "INTERNAL_ID"); @@ -704,16 +692,16 @@ Conversion exception: Unsupported casting function from REL to TIMESTAMP. ---- error Conversion exception: Unsupported casting function from RECURSIVE_REL to INT64. --LOG InvalidVarListToVarList +-LOG InvalidListToList -STATEMENT RETURN cast([31231], "INT64[][]"); ---- error -Conversion exception: Unsupported casting function from INT64 to VAR_LIST. +Conversion exception: Unsupported casting function from INT64 to LIST. -STATEMENT RETURN cast([-1], "UINT8[]"); ---- error Overflow exception: Value -1 is not within UINT8 range -STATEMENT RETURN cast([[1, 1]], "UINT8[]"); ---- error -Conversion exception: Unsupported casting function from VAR_LIST to UINT8. +Conversion exception: Unsupported casting function from LIST to UINT8. -LOG InvalidMapToMap -STATEMENT RETURN cast(cast("{-1=3}", "MAP(INT64, INT64)"), "MAP(UINT8, UINT8)"); @@ -749,67 +737,49 @@ Conversion exception: Unsupported casting function from STRUCT(a:STRING, b:STRIN ---- error Conversion exception: Unsupported casting function from STRUCT to MAP. --LOG InvalidFixedListToList +-LOG InvalidArrayToList -STATEMENT RETURN cast(cast("[1, -1]", "INT64[2]"), "UINT8[]"); ---- error Overflow exception: Value -1 is not within UINT8 range -STATEMENT RETURN cast(cast("[[1, 2], [3, 4]]", "INT64[2][]"), "INT8[]"); ---- error -Conversion exception: Unsupported casting function from FIXED_LIST to INT8. +Conversion exception: Unsupported casting function from ARRAY to INT8. --LOG InvalidListToFixedList +-LOG InvalidListToArray -STATEMENT RETURN cast([1000000000000000000], "INT16[1]"); ---- error Overflow exception: Value 1000000000000000000 is not within INT16 range -STATEMENT RETURN cast([43121], "INT8[1]") ---- error -Runtime exception: Unsupported FIXED_LIST type: Function::getFixedListChildCastFunc +Overflow exception: Value 43121 is not within INT8 range -STATEMENT RETURN cast([[1000000000000000000]], "INT64[1]"); ---- error -Conversion exception: Unsupported casting function from VAR_LIST to numerical type. --STATEMENT RETURN cast([NULL], "DOUBLE[1]"); ----- error -Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. --STATEMENT RETURN cast([NULL, 2], "DOUBLE[2]"); ----- error -Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. +Conversion exception: Unsupported casting function from LIST to INT64. -STATEMENT RETURN cast([1, 2], "DOUBLE[100]"); ---- error -Conversion exception: Unsupported casting VAR_LIST with incorrect list entry to FIXED_LIST. Expected: 100, Actual: 2. +Conversion exception: Unsupported casting LIST with incorrect list entry to ARRAY. Expected: 100, Actual: 2. -STATEMENT RETURN cast([[1, 2], [1, 4], [2, 4, 5], [1, 2]], "INT64[2][]"); ---- error -Conversion exception: Unsupported casting VAR_LIST with incorrect list entry to FIXED_LIST. Expected: 2, Actual: 3. --STATEMENT RETURN cast([[1, 2], [1, 4], [1, NULL], [1, 2]], "INT64[2][]"); ----- error -Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. --STATEMENT RETURN cast({a: 12, b: {a: [[NULL]]}, c: 2132}, "STRUCT(a INT64, b STRUCT(a INT64[1][]), c INT64)"); ----- error -Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. +Conversion exception: Unsupported casting LIST with incorrect list entry to ARRAY. Expected: 2, Actual: 3. -STATEMENT RETURN cast(cast("{3={}, 3= {a: 12}, 3={a:32, b:[1, 2, 3]}}", "MAP(STRING, STRUCT(a INT64, b INT64[]))"), "MAP(STRING, STRUCT(a INT64, b INT64[1]))"); ---- error -Conversion exception: Unsupported casting VAR_LIST with incorrect list entry to FIXED_LIST. Expected: 1, Actual: 3. +Conversion exception: Unsupported casting LIST with incorrect list entry to ARRAY. Expected: 1, Actual: 3. --LOG InvalidFixedListToList +-LOG InvalidArrayToArray -STATEMENT RETURN cast(cast([4, 1], "INT16[2]"), "FLOAT[3]"); ---- error Conversion exception: Unsupported casting function from INT16[2] to FLOAT[3]. -STATEMENT RETURN cast(cast([4, 1], "INT16[2]"), "FLOAT[1]"); ---- error Conversion exception: Unsupported casting function from INT16[2] to FLOAT[1]. --STATEMENT RETURN cast(cast([4, 1], "INT16[2]"), "UINT8[2]"); ----- error -Runtime exception: Unsupported FIXED_LIST type: Function::getFixedListChildCastFunc -LOG InvalidNestedCast -STATEMENT RETURN cast({a: {b: {c: [[1, 3, 4]], d: "str"}}, e: [1, 9, NULL]}, "STRUCT(a STRUCT(b STRUCT(c INT64[2][], d STRING)), e INT128[3])"); ---- error -Conversion exception: Unsupported casting VAR_LIST with incorrect list entry to FIXED_LIST. Expected: 2, Actual: 3. --STATEMENT RETURN cast({a: {b: {c: [[1, 3, 4]], d: "str"}}, e: [1, 9, NULL]}, "STRUCT(a STRUCT(b STRUCT(c INT64[3][], d STRING)), e INT128[3])"); ----- error -Conversion exception: Cast failed. NULL is not allowed for FIXED_LIST. +Conversion exception: Unsupported casting LIST with incorrect list entry to ARRAY. Expected: 2, Actual: 3. -STATEMENT RETURN cast(cast("{a: {b: {c: [[1, 3, 4]], d: {18=[3, 2]}}}, e: [1, 9, 3]}", "STRUCT(a STRUCT(b STRUCT(c INT64[3][], d MAP(INT32,INT32[]))), e FLOAT[3])"), "STRUCT(a STRUCT(b STRUCT(c INT64[3][], d MAP(INT32,INT32[5]))), e INT32[3])"); ---- error -Conversion exception: Unsupported casting VAR_LIST with incorrect list entry to FIXED_LIST. Expected: 5, Actual: 2. +Conversion exception: Unsupported casting LIST with incorrect list entry to ARRAY. Expected: 5, Actual: 2. -LOG InvalidNameCast -STATEMENT RETURN cast("nop", "STRUCT()"); diff --git a/test/test_files/tinysnb/cast/cast_to_nested_types.test b/test/test_files/tinysnb/cast/cast_to_nested_types.test index e9122469f74..e33e3c39254 100644 --- a/test/test_files/tinysnb/cast/cast_to_nested_types.test +++ b/test/test_files/tinysnb/cast/cast_to_nested_types.test @@ -3,8 +3,8 @@ -- --CASE CastStringToList --STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), fixedList INT16[3]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/should_pass.csv" RETURN *; +-CASE CastToNestedTypes +-STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), array INT16[3]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/should_pass.csv" RETURN *; ---- 10 [[1,3,423,124,43242],[432]]|{num: -423432, str: this is a string []}|[255,254,43] [[1,3,423,124,43242],[432]]|{num: 3423423, str: this is a string}|[250,249,21] @@ -16,7 +16,7 @@ []||[111,0,0] ||[0,111,12] |{num: , str: }|[0,0,0] --STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/change_config.csv" (HEADER=true, DELIM="|", DELIM="|", ESCAPE="~", QUOTE="'") RETURN * ; +-STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/change_config.csv" (HEADER=true, DELIM="|", DELIM="|", ESCAPE="~", QUOTE="'") RETURN * ; ---- 3 [escape,is escape success? ~]| ' [ ] do not need to escape sepeical | []|{a: {b: }} [this,is a word,normal not escape,' [ ] | , ~ ']|try escape ~|{a: {b: {c: [3432423,-43423,31231,]}}} @@ -43,10 +43,10 @@ {{}={}} {=} {} --STATEMENT LOAD WITH HEADERS (fixedList INT32[92]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/long_fixed_list2.csv" (QUOTE="'") RETURN *; +-STATEMENT LOAD WITH HEADERS (array INT32[92]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/long_array2.csv" (QUOTE="'") RETURN *; ---- 1 [32131,0,0,43243,12313,432432,4324,1312,43241,432432,2342,13412,43242,23432,43242,43242,12313,32131,43243,12313,432432,4324,1312,43241,432432,2342,13412,43242,23432,43242,43242,12313,32131,43243,12313,432432,4324,1312,43241,432432,2342,13412,43242,23432,43242,43242,12313,32131,43243,12313,432432,4324,1312,43241,432432,2342,13412,43242,23432,43242,43242,12313,32131,43243,12313,432432,4324,1312,43241,432432,2342,13412,43242,23432,43242,43242,12313,32131,43243,12313,432432,4324,1312,43241,432432,2342,13412,43242,23432,43242,43242,12313] --STATEMENT LOAD WITH HEADERS (fixedList FLOAT[1], bool BOOLEAN, intv INTERVAL) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_correct.csv" RETURN *; +-STATEMENT LOAD WITH HEADERS (array FLOAT[1], bool BOOLEAN, intv INTERVAL) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_correct.csv" RETURN *; ---- 6 [23123.433594]|True|1 month 2 days [-4321312.500000]|True|1 year 3 days @@ -54,12 +54,12 @@ [43213123584.000000]|False|12 years 3 months 30 days [-4212.423340]|False| [-2.000000]|True|10 months --STATEMENT LOAD WITH HEADERS (fixedList INT64[3], date DATE, timestamp TIMESTAMP) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_int64.csv" RETURN *; +-STATEMENT LOAD WITH HEADERS (array INT64[3], date DATE, timestamp TIMESTAMP) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_int64.csv" RETURN *; ---- 3 [4234234,4234535,-3242342]|2022-06-06|2022-11-22 15:12:22 [4234234,4234535,0]|2013-02-21|1970-01-01 10:00:00.004666 [4234234,0,-3242342]|2019-12-30|1970-01-01 00:00:00.004666 --STATEMENT LOAD WITH HEADERS (fixedList DOUBLE[83]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/long_fixed_list.csv" RETURN *; +-STATEMENT LOAD WITH HEADERS (array DOUBLE[83]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/long_array.csv" RETURN *; ---- 1 [4123.120000,0.000000,0.000000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,4123.120000,42432.120000,435435.231000,432423.123340,43424.213400,4325245.130000,432423.123000,3242.123000,543523442342.434326] -STATEMENT LOAD WITH HEADERS (u UNION(v1 INT64, v2 BOOLEAN), u2 UNION(v1 UINT32, v2 INT32, v3 DATE), u3 UNION(v1 UINT8, v2 UINT16, v3 TIMESTAMP, v4 FLOAT), u4 UNION(v1 UINT64, v2 INT8, v3 INT16, v4 DOUBLE), u5 UNION(v1 STRING)) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/union/union_correct.csv" RETURN *; @@ -74,7 +74,7 @@ True|2022-06-06|4324.123047|-32768| 0|0|2014-05-12 12:11:59|4324254534123134124032.000000|fsaf False|-4325||18446744073709551616.000000| dfsa --LOG CastToVarList +-LOG CastToList -STATEMENT RETURN cast(" [ [ 1 ,3, 423 , 124,43242 ] , [ 432 ]]", "INT64[][]"); ---- 1 [[1,3,423,124,43242],[432]] @@ -101,8 +101,8 @@ False|-4325||18446744073709551616.000000| dfsa [1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1.000000,2.000000,3.000000]|[1.000000,2.000000,3.000000] # timestamp/date/... list --LOG CastToFixedList --STATEMENT LOAD WITH HEADERS (fixedList STRING, bool BOOLEAN, intv INTERVAL) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_correct.csv" RETURN cast(fixedList, "FLOAT[1]"); +-LOG CastToArray +-STATEMENT LOAD WITH HEADERS (array STRING, bool BOOLEAN, intv INTERVAL) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_correct.csv" RETURN cast(array, "FLOAT[1]"); ---- 6 [23123.433594] [-4321312.500000] @@ -110,12 +110,12 @@ False|-4325||18446744073709551616.000000| dfsa [43213123584.000000] [-4212.423340] [-2.000000] --STATEMENT LOAD WITH HEADERS (stockPrice STRING) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_with_null.csv" RETURN cast(stockPrice, "DOUBLE[3]"); +-STATEMENT LOAD WITH HEADERS (stockPrice STRING) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_with_null.csv" RETURN cast(stockPrice, "DOUBLE[3]"); ---- 3 [3324.123000,342423.437500,432.123000] [1.000000,4231.000000,432.123000] --STATEMENT LOAD WITH HEADERS (stockPrice STRING) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_with_null.csv" where size(stockPrice) > 10 RETURN cast(stockPrice, "FLOAT[3]"); +-STATEMENT LOAD WITH HEADERS (stockPrice STRING) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_with_null.csv" where size(stockPrice) > 10 RETURN cast(stockPrice, "FLOAT[3]"); ---- 2 [3324.123047,342423.437500,432.122986] [1.000000,4231.000000,432.122986] @@ -125,6 +125,18 @@ False|-4325||18446744073709551616.000000| dfsa -STATEMENT Return cast(cast(-4324324, "int128"), "int64") ---- 1 -4324324 +-STATEMENT LOAD WITH HEADERS (array INT64[1]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_null.csv" RETURN *; +---- 1 +[] +-STATEMENT LOAD WITH HEADERS (array INT64[2]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_null2.csv" RETURN *; +---- 1 +[,432423] +-STATEMENT LOAD WITH HEADERS (a STRING[2]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_string.csv" RETURN *; +---- 1 +[fsdaf,sfadfwer] +-STATEMENT LOAD WITH HEADERS (array UINT8[1]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_uint8.csv" RETURN *; +---- 1 +[4] -LOG CastToMap -STATEMENT RETURN cast(" { c= {a = 3423 }, b = { g = 3421 } } ", "MAP(STRING, MAP(STRING, INT16))"), cast("{}", "MAP(STRING, MAP(STRING, INT16))"), cast("{d = {}}", "MAP(STRING, MAP(STRING, INT16))"); @@ -170,7 +182,7 @@ True|2019-03-19|-12.343200|32768| 0|0|2014-05-12 12:11:59|4324254534123134124032.000000|fsaf False|-4325|14|18446744073709551616.000000| dfsa --LOG CastVarListToVarList +-LOG CastListToList -STATEMENT RETURN cast([321, 432], "DOUBLE[]"), cast([321, 432], "FLOAT[]"), cast([321, 432], "INT128[]"), cast([321, 432], "INT64[]"), cast([321, 432], "INT32[]"), cast([321, 432], "INT16[]"), cast([-1, -43], "INT8[]"), cast([0, 23], "UINT8[]"), cast([0, 23], "UINT16[]"), cast([0, 23], "UINT32[]"), cast([0, 23], "UINT64[]"), cast([5435234412435123, -432425341231], "STRING[]"); ---- 1 [321.000000,432.000000]|[321.000000,432.000000]|[321,432]|[321,432]|[321,432]|[321,432]|[-1,-43]|[0,23]|[0,23]|[0,23]|[0,23]|[5435234412435123,-432425341231] @@ -178,7 +190,7 @@ False|-4325|14|18446744073709551616.000000| dfsa ---- 1 []|[,]||[,432124,0,] --LOG CastNestedVarListToNestedVarList +-LOG CastNestedListToNestedList -STATEMENT RETURN cast([[4324.2312, 432.321, 43242.543], [31214.59,4132.72], NULL, [NULL,,4324.32]], "INT64[][]"); ---- 1 [[4324,432,43243],[31215,4133],,[,,4324]] @@ -237,7 +249,7 @@ False|-4325|14|18446744073709551616.000000| dfsa -STATEMENT RETURN cast(cast(cast("{a: 12, b: 0}", "STRUCT(a STRING, b STRING, c STRING)"), "STRUCT(a INT128, b INT128, c INT128)"), "STRUCT(a INT64, b INT64, c INT64)"), cast(cast(cast("{a: 15}", "STRUCT(a STRING, b STRING)"), "STRUCT(a INT32, b INT32)"), "STRUCT(a INT16, b INT16)"), cast(cast(cast("{b: 15}", "STRUCT(a STRING, b STRING)"), "STRUCT(a INT8, b INT8)"), "STRUCT(a UINT16, b UINT16)"), cast(cast(cast("{}", "STRUCT(a STRING, b STRING)"), "STRUCT(a UINT32, b UINT32)"), "STRUCT(a UINT64, b UINT64)"), cast(cast("{a: 12, b: 0}", "STRUCT(a STRING, b STRING)"), "STRUCT(a DOUBLE, b DOUBLE)"), cast(cast("{a: 12, b: 0}", "STRUCT(a STRING, b STRING)"), "STRUCT(a FLOAT, b FLOAT)"); ---- 1 {a: 12, b: 0, c: }|{a: 15, b: }|{a: , b: 15}|{a: , b: }|{a: 12.000000, b: 0.000000}|{a: 12.000000, b: 0.000000} --STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), fixedList INT16[3]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/should_pass.csv" RETURN cast(a, "struct(num INT64, str STRING)"), cast(a, "struct(num INT128, str STRING)"), cast(a, "struct(num STRING, str STRING)"), cast(a, "struct(num DOUBLE, str STRING)"), cast(a, "struct(num FLOAT, str STRING)"); +-STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), array INT16[3]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/should_pass.csv" RETURN cast(a, "struct(num INT64, str STRING)"), cast(a, "struct(num INT128, str STRING)"), cast(a, "struct(num STRING, str STRING)"), cast(a, "struct(num DOUBLE, str STRING)"), cast(a, "struct(num FLOAT, str STRING)"); ---- 10 {num: -423432, str: this is a string []}|{num: -423432, str: this is a string []}|{num: -423432, str: this is a string []}|{num: -423432.000000, str: this is a string []}|{num: -423432.000000, str: this is a string []} {num: 0, str: this is a string}|{num: 0, str: this is a string}|{num: 0, str: this is a string}|{num: 0.000000, str: this is a string}|{num: 0.000000, str: this is a string} @@ -251,7 +263,7 @@ False|-4325|14|18446744073709551616.000000| dfsa |||| -LOG CastNestedStructToStruct --STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/change_config.csv" (HEADER=true, DELIM="|", DELIM="|", ESCAPE="~", QUOTE="'") RETURN cast(struct, "STRUCT(a STRUCT(b STRUCT(c INT128[])))"), cast(struct, "STRUCT(a STRUCT(b STRUCT(c DOUBLE[])))"), cast(struct, "STRUCT(a STRUCT(b STRUCT(c STRING)))"), cast(struct, "STRUCT(a STRUCT(b STRING))"), cast(struct, "STRUCT(a STRING)"); +-STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/change_config.csv" (HEADER=true, DELIM="|", DELIM="|", ESCAPE="~", QUOTE="'") RETURN cast(struct, "STRUCT(a STRUCT(b STRUCT(c INT128[])))"), cast(struct, "STRUCT(a STRUCT(b STRUCT(c DOUBLE[])))"), cast(struct, "STRUCT(a STRUCT(b STRUCT(c STRING)))"), cast(struct, "STRUCT(a STRUCT(b STRING))"), cast(struct, "STRUCT(a STRING)"); ---- 3 {a: {b: {c: [3432423,-43423,31231,]}}}|{a: {b: {c: [3432423.000000,-43423.000000,31231.000000,]}}}|{a: {b: {c: [3432423,-43423,31231,]}}}|{a: {b: {c: [3432423,-43423,31231,]}}}|{a: {b: {c: [3432423,-43423,31231,]}}} {a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}} @@ -267,11 +279,11 @@ False|-4325|14|18446744073709551616.000000| dfsa ---- 1 {[,,]={a: -1, b: 1.000000, c: }} --LOG CastFixedListToList +-LOG CastArrayToList -STATEMENT RETURN cast(cast("[1,2,3]", "INT64[3]"), "INT128[]"), cast(cast("[1,2,3]", "INT64[3]"), "INT64[]"), cast(cast("[1,2,3]", "INT64[3]"), "INT32[]"), cast(cast("[1,2,3]", "INT64[3]"), "INT16[]"), cast(cast("[1,2,3]", "INT64[3]"), "INT8[]"), cast(cast("[1,2,3]", "INT64[3]"), "UINT64[]"), cast(cast("[1,2,3]", "INT64[3]"), "UINT32[]"), cast(cast("[1,2,3]", "INT64[3]"), "UINT16[]"), cast(cast("[1,2,3]", "INT64[3]"), "UINT8[]"), cast(cast("[1,2,3]", "INT64[3]"), "DOUBLE[]"), cast(cast("[1,2,3]", "INT64[3]"), "STRING[]"), cast(cast("[1,2,3]", "INT64[3]"), "FLOAT[]"); ---- 1 [1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1,2,3]|[1.000000,2.000000,3.000000]|[1,2,3]|[1.000000,2.000000,3.000000] --STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), fixedList INT16[3]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/should_pass.csv" RETURN cast(cast(cast(fixedList, "DOUBLE[]"), "STRING[]"), "FLOAT[]"); +-STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), array INT16[3]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/should_pass.csv" RETURN cast(cast(cast(array, "DOUBLE[]"), "STRING[]"), "FLOAT[]"); ---- 10 @@ -284,16 +296,16 @@ False|-4325|14|18446744073709551616.000000| dfsa [255.000000,254.000000,43.000000] [29.000000,21.000000,1.000000] --LOG CastNestedFixedListToList +-LOG CastNestedArrayToList -STATEMENT RETURN cast(cast("[NULL, [0, -1, 1], NULL, [1, 2, -2], NULL]", "FLOAT[3][]"), "INT64[][]"), cast(cast("[NULL, NULL]", "FLOAT[3][]"), "INT32[][]"), cast(cast("[[1, 1, 1], NULL]", "FLOAT[3][]"), "INT16[][]"), cast(cast("[NULL, [1, 1, 1]]", "FLOAT[3][]"), "INT8[][]"); ---- 1 [,[0,-1,1],,[1,2,-2],]|[,]|[[1,1,1],]|[,[1,1,1]] --LOG CastListToFixedList +-LOG CastListToArray -STATEMENT RETURN cast([1], "INT64[1]"), cast([1], "INT32[1]"), cast([1], "INT16[1]"), cast([1], "DOUBLE[1]"), cast([1], "FLOAT[1]"), cast(NULL, "INT64[15]"); ---- 1 [1]|[1]|[1]|[1.000000]|[1.000000]| --STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), fixedList STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/should_pass.csv" RETURN cast(cast(cast(fixedList, "INT16[3]"), "STRING[]"), "FLOAT[3]"); +-STATEMENT LOAD WITH HEADERS (list INT64[][], a struct(num INT64, str STRING), array STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/list/should_pass.csv" RETURN cast(cast(cast(array, "INT16[3]"), "STRING[]"), "FLOAT[3]"); ---- 10 @@ -305,7 +317,7 @@ False|-4325|14|18446744073709551616.000000| dfsa [250.000000,249.000000,21.000000] [255.000000,254.000000,43.000000] [29.000000,21.000000,1.000000] --STATEMENT LOAD WITH HEADERS (stockPrice STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/fixed_list/fixed_list_with_null.csv" RETURN cast(stockPrice, "DOUBLE[3]"); +-STATEMENT LOAD WITH HEADERS (stockPrice STRING[]) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/array/array_with_null.csv" RETURN cast(stockPrice, "DOUBLE[3]"); ---- 3 [3324.123000,342423.437500,432.123000] @@ -314,31 +326,61 @@ False|-4325|14|18446744073709551616.000000| dfsa ---- 1 [1,2,3]|[4,5,6]|[7,8,9]|[10,11,12]|[13,14,15]|[16,17,18]|[0,-1,-2]|[-3,-4,-5]|[-6,-7,-8] --LOG CastNestedListToFixedList +-LOG CastNestedListToArray -STATEMENT RETURN cast([[1,2], [3, 4], [5, 6]], "INT32[2][]"); ---- 1 [[1,2],[3,4],[5,6]] -STATEMENT RETURN cast([NULL, [1]], "INT64[1][]"), cast([NULL], "INT64[1][]"), cast([[1], NULL], "INT64[1][]"), cast([NULL], "INT64[1][][]"), cast([[NULL]], "INT64[1][][]"), cast([[[2], NULL], [NULL, [1]]], "INT64[1][][]"), cast([NULL, [NULL, [1]]], "INT64[1][][]"); ---- 1 [,[1]]|[]|[[1],]|[]|[[]]|[[[2],],[,[1]]]|[,[,[1]]] --STATEMENT LOAD WITH HEADERS (struct STRUCT(a INT64, b MAP(INT64[][][], STRING))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/struct/struct_with_fixed_list.csv" where struct_extract(struct, 'a') > 0 RETURN cast(struct, "STRUCT(a INT64,b MAP(INT64[1][][], STRING))"); +-STATEMENT LOAD WITH HEADERS (struct STRUCT(a INT64, b MAP(INT64[][][], STRING))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/struct/struct_with_array.csv" where struct_extract(struct, 'a') > 0 RETURN cast(struct, "STRUCT(a INT64,b MAP(INT64[1][][], STRING))"); ---- 4 {a: 1999, b: {[[[1],[2],[3]]]=true}} {a: 1999, b: {[[]]=true}} {a: 1999, b: {[]=true}} {a: 2341, b: {[,[,[1],[2],[3],,[4]],[[8],,[7]],,[,[5]],[[6],],]=true}} --LOG CastFixedListToFixedList +-LOG CastArrayToArray -STATEMENT Return cast(Cast([1,2,3], "INT32[3]"), "INT64[3]"), cast(Cast([1,2,3], "INT32[3]"), "INT32[3]"), cast(Cast([1,2,3], "INT32[3]"), "INT16[3]"), cast(Cast([1,2,3], "INT32[3]"), "DOUBLE[3]"), cast(Cast([1,2,3], "INT32[3]"), "FLOAT[3]"); ---- 1 [1,2,3]|[1,2,3]|[1,2,3]|[1.000000,2.000000,3.000000]|[1.000000,2.000000,3.000000] -STATEMENT Return cast(cast(cast(cast(Cast([0,-1,1], "INT32[3]"), "INT64[3]"), "INT16[3]"), "DOUBLE[3]"), "FLOAT[3]"); ---- 1 [0.000000,-1.000000,1.000000] --STATEMENT LOAD WITH HEADERS (struct STRUCT(a INT64, b MAP(INT64[][][], STRING))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/struct/struct_with_fixed_list.csv" where struct_extract(struct, 'a') > 0 RETURN cast(cast(struct, "STRUCT(a INT64,b MAP(DOUBLE[1][][], STRING))"), "STRUCT(a INT64,b MAP(INT16[1][][], STRING))"); +-STATEMENT LOAD WITH HEADERS (struct STRUCT(a INT64, b MAP(INT64[][][], STRING))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/struct/struct_with_array.csv" where struct_extract(struct, 'a') > 0 RETURN cast(cast(struct, "STRUCT(a INT64,b MAP(DOUBLE[1][][], STRING))"), "STRUCT(a INT64,b MAP(INT16[1][][], STRING))"); ---- 4 {a: 1999, b: {[[[1],[2],[3]]]=true}} {a: 1999, b: {[[]]=true}} {a: 1999, b: {[]=true}} {a: 2341, b: {[,[,[1],[2],[3],,[4]],[[8],,[7]],,[,[5]],[[6],],]=true}} +-LOG CastToArrayWithNull +-STATEMENT RETURN cast([NULL, 2], "DOUBLE[2]"); +---- 1 +[,2.000000] +-STATEMENT RETURN cast([[1, 2], [1, 4], [1, NULL], [1, 2]], "INT64[2][]"); +---- 1 +[[1,2],[1,4],[1,],[1,2]] +-STATEMENT RETURN cast({a: 12, b: {a: [[NULL]]}, c: 2132}, "STRUCT(a INT64, b STRUCT(a INT64[1][]), c INT64)"); +---- 1 +{a: 12, b: {a: [[]]}, c: 2132} +-STATEMENT RETURN cast({a: {b: {c: [[1, 3, 4]], d: "str"}}, e: [1, 9, NULL]}, "STRUCT(a STRUCT(b STRUCT(c INT64[3][], d STRING)), e INT128[3])"); +---- 1 +{a: {b: {c: [[1,3,4]], d: str}}, e: [1,9,]} + +-LOG CastToArrayOfNestedTypes +-STATEMENT RETURN cast([map(['a', 'b'], [1, 2]), map(['c'], [3])], "MAP(STRING, INT64)[2]"); +---- 1 +[{a=1, b=2},{c=3}] +-STATEMENT RETURN cast([{a: 1, b: 2}, {a: 0, b: 11}, {a: 20, b: 21}], "STRUCT(a INT64, b INT64)[3]"); +---- 1 +[{a: 1, b: 2},{a: 0, b: 11},{a: 20, b: 21}] +-STATEMENT RETURN cast("[12, abcd, 1.75]", "UNION(a INT64, b STRING, c FLOAT)[3]"); +---- 1 +[12,abcd,1.75] +-STATEMENT RETURN cast("[[1], [2, 3], [4, 5, 6], []]", "INT64[][4]"); +---- 1 +[[1],[2,3],[4,5,6],[]] +-STATEMENT RETURN cast([[[1, 2, 3], [3, 4, 5]], [[5, 6, 7], [7, 8, 9]]], "INT64[3][2][2]"); +---- 1 +[[[1,2,3],[3,4,5]],[[5,6,7],[7,8,9]]] diff --git a/test/test_files/tinysnb/copy/copy_from.test b/test/test_files/tinysnb/copy/copy_from.test new file mode 100644 index 00000000000..77e90572c62 --- /dev/null +++ b/test/test_files/tinysnb/copy/copy_from.test @@ -0,0 +1,88 @@ +-GROUP TinySnbReadTest +-DATASET CSV tinysnb + +-- + +-CASE CopyFromSubquery + +-STATEMENT CREATE NODE TABLE A(name STRING, PRIMARY KEY (name)); +---- ok +-STATEMENT COPY A FROM (MATCH (a:person) RETURN a.ID, a.fName); +---- error +Binder exception: Query returns 2 columns but 1 columns were expected. +-STATEMENT COPY A FROM (MATCH (a:person) RETURN a.ID); +---- error +Binder exception: a.ID has data type INT64 but STRING was expected. +-STATEMENT COPY A FROM x; +---- error +Binder exception: Scan from external object x is not supported. +-STATEMENT COPY A FROM (MATCH (a:person) RETURN a.fName); +---- ok +-STATEMENT MATCH (a:A) RETURN a.*; +---- 8 +Alice +Bob +Carol +Dan +Elizabeth +Farooq +Greg +Hubert Blaine Wolfeschlegelsteinhausenbergerdorff +-STATEMENT CREATE REL TABLE R(FROM A TO A); +---- ok +-STATEMENT COPY R FROM (MATCH (a:person)-[r:knows]->(b:person) RETURN a.fName, b.fName); +---- ok +-STATEMENT MATCH (a:A)-[r:R]->(b:A) RETURN a.name, b.name; +---- 14 +Alice|Bob +Alice|Carol +Alice|Dan +Bob|Alice +Bob|Carol +Bob|Dan +Carol|Alice +Carol|Bob +Carol|Dan +Dan|Alice +Dan|Bob +Dan|Carol +Elizabeth|Farooq +Elizabeth|Greg +-STATEMENT create node table person2 (ID INt64, fName StRING, gender INT64, isStudent BoOLEAN, isWorker BOOLEAN, age INT64, eyeSight DOUBLE, birthdate DATE, registerTime TIMESTAMP, lastJobDuration interval, workedHours INT64[], usedNames STRING[], courseScoresPerTerm INT64[][], grades INT64[4], height float, u UUID, PRIMARY KEY (ID)); +---- ok +-STATEMENT copy person2 from (MATCH (a:person) RETURN a.*); +---- ok +-STATEMENT MATCH (a:person2) RETURN a.*; +---- 8 +0|Alice|1|True|False|35|5.000000|1900-01-01|2011-08-20 11:25:30|3 years 2 days 13:02:00|[10,5]|[Aida]|[[10,8],[6,7,8]]|[96,54,86,92]|1.731000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 +10|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|2|False|True|83|4.900000|1990-11-27|2023-02-21 13:25:30|3 years 2 days 13:02:00|[10,11,12,3,4,5,6,7]|[Ad,De,Hi,Kye,Orlan]|[[7],[10],[6,7]]|[77,64,100,54]|1.323000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18 +2|Bob|2|True|False|30|5.100000|1900-01-01|2008-11-03 15:25:30.000526|10 years 5 months 13:00:00.000024|[12,8]|[Bobby]|[[8,9],[9,10]]|[98,42,93,88]|0.990000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12 +3|Carol|1|False|True|45|5.000000|1940-06-22|1911-08-20 02:32:21|48:24:11|[4,5]|[Carmen,Fred]|[[8,10]]|[91,75,21,95]|1.000000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13 +5|Dan|2|False|True|20|4.800000|1950-07-23|2031-11-30 12:25:30|10 years 5 months 13:00:00.000024|[1,9]|[Wolfeschlegelstein,Daniel]|[[7,4],[8,8],[9]]|[76,88,99,89]|1.300000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14 +7|Elizabeth|1|False|True|20|4.700000|1980-10-26|1976-12-23 11:21:42|48:24:11|[2]|[Ein]|[[6],[7],[8]]|[96,59,65,88]|1.463000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15 +8|Farooq|2|True|False|25|4.500000|1980-10-26|1972-07-31 13:22:30.678559|00:18:00.024|[3,4,5,6,7]|[Fesdwe]|[[8]]|[80,78,34,83]|1.510000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16 +9|Greg|2|False|False|40|4.900000|1980-10-26|1976-12-23 04:41:42|10 years 5 months 13:00:00.000024|[1]|[Grad]|[[10]]|[43,83,67,43]|1.600000|a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17 +-STATEMENT create rel table knows2 (FROM person2 TO person2, date DATE, meetTime TIMESTAMP, validInterval INTERVAL, comments STRING[], summary STRUCT(locations STRING[], transfer STRUCT(day DATE, amount INT64[])), notes UNION(firstmet DATE, type INT16, comment STRING), someMap MAP(STRING, STRING), MANY_MANY); +---- ok +-STATEMENT copy knows2 from (MATCH (a:person)-[r:knows]->(b:person) RETURN a.ID, b.ID, r.*); +---- ok +-STATEMENT MATCH (a:person2)-[r:knows2]->(b:person2) RETURN a.fName, b.fName, r.*; +---- 14 +Alice|Bob|2021-06-30|1986-10-21 21:08:31.521|10 years 5 months 13:00:00.000024|[rnme,m8sihsdnf2990nfiwf]|{locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}|1|{a=b} +Alice|Carol|2021-06-30|1946-08-25 19:07:22|20 years 30 days 48:00:00|[njnojppo9u0jkmf,fjiojioh9h9h89hph]|{locations: , transfer: }|2020-10-10|{c=d, e=f, 1=2} +Alice|Dan|2021-06-30|2012-12-11 20:07:22|10 days|[ioji232,jifhe8w99u43434]|{locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}}|nice weather| +Bob|Alice|2021-06-30|1946-08-25 19:07:22|10 years 5 months 13:00:00.000024|[2huh9y89fsfw23,23nsihufhw723]|{locations: ['paris'], transfer: {day: 2000-01-01, amount: [20,5000]}}|4| +Bob|Carol|1950-05-14|1946-08-25 19:07:22|00:23:00|[fwehu9h9832wewew,23u9h989sdfsss]|{locations: ['paris'], transfer: {day: 2011-05-01, amount: [2000,5340]}}|cool stuff found| +Bob|Dan|1950-05-14|2012-12-11 20:07:22|20 years 30 days 48:00:00|[fwh9y81232uisuiehuf,ewnuihxy8dyf232]|{locations: ['vancouver'], transfer: {day: 2020-01-01, amount: [120,50]}}|matthew perry| +Carol|Alice|2021-06-30|2002-07-31 11:42:53.12342|40 days 30:00:00|[fnioh8323aeweae34d,osd89e2ejshuih12]|{locations: ['london','toronto'], transfer: {day: 2012-11-21, amount: [223,5230]}}|10| +Carol|Bob|1950-05-14|2007-02-12 12:11:42.123|00:28:00.03|[fwh983-sdjisdfji,ioh89y32r2huir]|{locations: ['paris','beijing'], transfer: {day: 2011-03-11, amount: [2323,50]}}|1| +Carol|Dan|2000-01-01|1998-10-02 13:09:22.423|00:00:00.3|[psh989823oaaioe,nuiuah1nosndfisf]|{locations: [], transfer: {day: 1980-11-21, amount: [20,5]}}|2| +Dan|Alice|2021-06-30|1936-11-02 11:02:01|00:00:00.00048|[fwewe]|{locations: ['shanghai','nanjing'], transfer: {day: 1998-11-12, amount: [22,53240]}}|15| +Dan|Bob|1950-05-14|1982-11-11 13:12:05.123|00:23:00|[fewh9182912e3,h9y8y89soidfsf,nuhudf78w78efw,hioshe0f9023sdsd]|{locations: ['paris'], transfer: {day: 2000-01-01, amount: [20,5000]}}|happy new year| +Dan|Carol|2000-01-01|1999-04-21 15:12:11.42|48:00:00.052|[23h9sdslnfowhu2932,shuhf98922323sf]|{locations: ['paris'], transfer: {day: 2000-01-01, amount: [20,5000]}}|4| +Elizabeth|Farooq|1905-12-12|2025-01-01 11:22:33.52|00:47:58|[ahu2333333333333,12weeeeeeeeeeeeeeeeee]|{locations: ['toronto','thisisalongcityname'], transfer: {day: 1930-11-22, amount: [18,323]}}|8| +Elizabeth|Greg|1905-12-12|2020-03-01 12:11:41.6552|00:47:58|[peweeeeeeeeeeeeeeeee,kowje9w0eweeeeeeeee]|{locations: ['waterloo'], transfer: {day: 2000-01-01, amount: [1000,5000]}}|10| + +-STATEMENT LOAD FROM (MATCH (a) RETURN a.ID) RETURN *; +---- error +Binder exception: LOAD FROM subquery is not supported. diff --git a/test/test_files/tinysnb/exception/list.test b/test/test_files/tinysnb/exception/list.test index 59b3e743568..30a1f6eb010 100644 --- a/test/test_files/tinysnb/exception/list.test +++ b/test/test_files/tinysnb/exception/list.test @@ -3,28 +3,25 @@ -- --CASE SetListPropertyError +-CASE ListFunctionException + -STATEMENT MATCH (a:person) SET a.workedHours=['A', 'B'] ---- error Binder exception: Expression LIST_CREATION(A,B) has data type STRING[] but expected INT64[]. Implicit cast is not supported. --CASE ListFunctionMatchError1 -STATEMENT MATCH (a:person) RETURN array_concat(a.workedHours, a.age) ---- error -Binder exception: Cannot match a built-in function for given function ARRAY_CONCAT(VAR_LIST,INT64). Supported inputs are -(VAR_LIST,VAR_LIST) -> VAR_LIST +Binder exception: Cannot match a built-in function for given function ARRAY_CONCAT(INT64[],INT64). Supported inputs are +(LIST,LIST) -> LIST --CASE ListFunctionMatchError2 -STATEMENT MATCH (a:person) RETURN array_concat(a.workedHours, ['A']) ---- error Binder exception: Cannot bind LIST_CONCAT with parameter type INT64[] and STRING[]. --CASE ListFunctionMatchError3 -STATEMENT MATCH (a:person) RETURN [a.age, a.fName] ---- error Binder exception: Cannot bind LIST_CREATION with parameter type INT64 and STRING. --CASE ListPrepareError -STATEMENT MATCH (a:person) RETURN list_sort($1) ---- error Binder exception: Cannot resolve recursive data type for expression $1. diff --git a/test/test_files/tinysnb/exception/relation.test b/test/test_files/tinysnb/exception/relation.test index 78191ab81d9..e9c8c64093f 100644 --- a/test/test_files/tinysnb/exception/relation.test +++ b/test/test_files/tinysnb/exception/relation.test @@ -3,17 +3,20 @@ -- --CASE ReadVarlengthRelPropertyTest1 +-CASE ReadVarlengthRelPropertyTest + -STATEMENT MATCH (a:person)-[e:knows*1..3]->(b:person) RETURN e.age ---- error Binder exception: e has data type RECURSIVE_REL but (NODE,REL,STRUCT) was expected. --CASE ReadVarlengthRelPropertyTest2 + -STATEMENT MATCH (a:person)-[e:knows*1..3]->(b:person) WHERE ID(e) = 0 RETURN COUNT(*) ---- error -Binder exception: e has data type RECURSIVE_REL but (NODE,REL,STRUCT) was expected. +Binder exception: Cannot match a built-in function for given function ID(RECURSIVE_REL). Supported inputs are +(NODE) +(REL) +(STRUCT) --CASE AccessRelInternalIDTest -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE e._id > 1 RETURN COUNT(*) ---- error Binder exception: _id is reserved for system usage. External access is not allowed. diff --git a/test/test_files/tinysnb/function/array.test b/test/test_files/tinysnb/function/array.test new file mode 100644 index 00000000000..5b54403acac --- /dev/null +++ b/test/test_files/tinysnb/function/array.test @@ -0,0 +1,121 @@ +-GROUP TinySnbReadTest +-DATASET CSV tinysnb + +-- + +-CASE ArrayValue + +-LOG CreateArrayValue +-STATEMENT RETURN ARRAY_VALUE(3.2, 5.4, 7.2, 32.3) +---- 1 +[3.200000,5.400000,7.200000,32.300000] + +-LOG CreateArrayValueWithNull +-STATEMENT RETURN ARRAY_VALUE(2, 7, NULL, 256, 32, NULL) +---- 1 +[2,7,,256,32,] + +-LOG CreateEmptyArray +-STATEMENT RETURN ARRAY_VALUE() +---- 1 +[] + +-LOG CreateArrayRecursively +-STATEMENT RETURN ARRAY_VALUE(ARRAY_VALUE(3,2), ARRAY_VALUE(4,7), ARRAY_VALUE(-2,3)) +---- 1 +[[3,2],[4,7],[-2,3]] + +-CASE ArrayCrossProduct +-LOG ArrayCrossProductINT128 +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE(to_int128(1), to_int128(2), to_int128(3)), ARRAY_VALUE(to_int128(4), to_int128(5), to_int128(6))) +---- 1 +[-3,6,-3] + +-LOG ArrayCrossProductINT64 +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE(to_int64(148), to_int64(176), to_int64(112)), ARRAY_VALUE(to_int64(182), to_int64(187), to_int64(190))) +---- 1 +[12496,-7736,-4356] + +-LOG ArrayCrossProductINT32 +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE(to_int32(195), to_int32(894), to_int32(539)), ARRAY_VALUE(to_int32(823), to_int32(158), to_int32(177))) +---- 1 +[73076,409082,-704952] + +-LOG ArrayCrossProductINT16 +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE(to_int16(463), to_int16(184), to_int16(189)), ARRAY_VALUE(to_int16(94), to_int16(161), to_int16(410))) +---- 1 +[-20525,24544,-8289] + +-LOG ArrayCrossProductINT8 +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE(to_int8(12), to_int8(7), to_int8(6)), ARRAY_VALUE(to_int8(3), to_int8(4), to_int8(5))) +---- 1 +[11,-42,27] + +-LOG ArrayCrossProductFLOAT +-STATEMENT RETURN round(ARRAY_CROSS_PRODUCT(ARRAY_VALUE(TO_FLOAT(3.5), TO_FLOAT(2.55), TO_FLOAT(6.2)), ARRAY_VALUE(TO_FLOAT(4.2), TO_FLOAT(7.8), TO_FLOAT(9.254)))[1],2) +---- 1 +-24.760000 + +-LOG ArrayCrossProductDOUBLE +-STATEMENT RETURN round(ARRAY_CROSS_PRODUCT(ARRAY_VALUE(TO_DOUBLE(12.62), TO_DOUBLE(7.54), TO_DOUBLE(6.13)), ARRAY_VALUE(TO_DOUBLE(3.23), TO_DOUBLE(4.56), TO_DOUBLE(5.34)))[1],2) +---- 1 +12.310000 + +-LOG ArrayCrossProductTypeError +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE('test','test1'), ARRAY_VALUE('test2', 'test3')) +---- error +Binder exception: ARRAY_CROSS_PRODUCT can only be applied on array of floating points or integers + +-LOG ArrayCrossProductInCorrectSize +-STATEMENT RETURN ARRAY_CROSS_PRODUCT(ARRAY_VALUE(32, 54, 77), ARRAY_VALUE(31, 24)) +---- error +Binder exception: ARRAY_CROSS_PRODUCT requires both arrays to have the same element type and size of 3 + +-LOG ArrayCosineSimilarity +-STATEMENT MATCH (p:person)-[e:meets]->(p1:person) return round(ARRAY_COSINE_SIMILARITY(e.location, array_value(to_float(3.4), to_float(2.7))),2) +---- 7 +0.790000 +0.880000 +0.930000 +0.930000 +0.950000 +0.950000 +0.970000 + +-LOG ArrayCosineSimilarityWrongType +-STATEMENT MATCH (p:person) return ARRAY_COSINE_SIMILARITY(p.grades, p.grades) +---- error +Binder exception: ARRAY_COSINE_SIMILARITY requires argument type of FLOAT or DOUBLE. + +-LOG ArrayDistance +-STATEMENT MATCH (p:person)-[e:meets]->(p1:person) return round(ARRAY_DISTANCE(e.location, array_value(to_float(3.4), to_float(2.7))),2) +---- 7 +1.350000 +1.600000 +1.620000 +2.530000 +4.500000 +5.750000 +6.410000 + +-LOG ArrayInnerProduct +-STATEMENT MATCH (p:person)-[e:meets]->(p1:person) return round(ARRAY_INNER_PRODUCT(e.location, array_value(to_float(3.4), to_float(2.7))),2) +---- 7 +14.870000 +15.540000 +21.180000 +24.240000 +31.780000 +35.200000 +36.150000 + +-LOG ArrayDotProduct +-STATEMENT MATCH (p:person)-[e:meets]->(p1:person) return round(ARRAY_DOT_PRODUCT(e.location, array_value(to_float(5.6), to_float(2.1))),2) +---- 7 +18.330000 +21.910000 +24.950000 +27.720000 +31.220000 +38.160000 +51.230000 diff --git a/test/test_files/tinysnb/function/cast.test b/test/test_files/tinysnb/function/cast.test index 80064432e55..54e1bf514f3 100644 --- a/test/test_files/tinysnb/function/cast.test +++ b/test/test_files/tinysnb/function/cast.test @@ -484,7 +484,7 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff [4,5] [10,11,12,3,4,5,6,7] --LOG CastListOfIntsToFixedList +-LOG CastListOfIntsToArray -STATEMENT MATCH (p:person) WHERE size(p.workedHours) = 2 RETURN cast(p.workedHours, "INT64[2]"), cast(p.workedHours, "INT32[2]"), cast(p.workedHours, "INT16[2]"), cast(p.workedHours, "DOUBLE[2]"), cast(p.workedHours, "FLOAT[2]"); ---- 4 [1,9]|[1,9]|[1,9]|[1.000000,9.000000]|[1.000000,9.000000] @@ -547,7 +547,7 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff [[6],[7],[8]] [[7],[10],[6,7]] --LOG CastListOfListOfIntsToListOfFixedList +-LOG CastListOfListOfIntsToListOfArray -STATEMENT MATCH (p:person) WHERE p.ID > 6 and p.ID < 10 RETURN cast(cast(p.courseScoresPerTerm, "INT128[][]"), "INT16[1][]"); ---- 3 [[6],[7],[8]] @@ -555,7 +555,7 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff [[10]] --LOG CastFixedListToString +-LOG CastArrayToString -STATEMENT MATCH (p:person) where p.ID > 1 RETURN string(p.grades) ---- 8 @@ -578,7 +578,7 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff [43,83,67,43] [77,64,100,54] --LOG CastFixedListToList +-LOG CastArrayToList -STATEMENT MATCH(p:person) where p.ID > 4 RETURN cast(p.grades, "UINT64[]"), cast(p.grades, "UINT32[]"), cast(p.grades, "UINT16[]"), cast(p.grades, "UINT8[]"), cast(p.grades, "INT8[]"), cast(p.grades, "INT16[]"), cast(p.grades, "INT32[]"), cast(p.grades, "INT64[]"), cast(p.grades, "INT128[]"), cast(p.grades, "STRING[]"), cast(p.grades, "DOUBLE[]"), cast(p.grades, "FLOAT[]"); ---- 6 [43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43.000000,83.000000,67.000000,43.000000]|[43.000000,83.000000,67.000000,43.000000] @@ -588,7 +588,7 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff [96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96,59,65,88]|[96.000000,59.000000,65.000000,88.000000]|[96.000000,59.000000,65.000000,88.000000] ||||||||||| --LOG CastFixedListToFixedList +-LOG CastArrayToArray -STATEMENT MATCH(p:person) where p.ID > 8 RETURN cast(p.grades, "UINT64[]"), cast(p.grades, "UINT32[]"), cast(p.grades, "UINT16[]"), cast(p.grades, "UINT8[]"), cast(p.grades, "INT8[]"), cast(p.grades, "INT16[]"), cast(p.grades, "INT32[]"), cast(p.grades, "INT64[]"), cast(p.grades, "INT128[]"), cast(p.grades, "STRING[]"), cast(p.grades, "DOUBLE[]"), cast(p.grades, "FLOAT[]"); ---- 3 [43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43,83,67,43]|[43.000000,83.000000,67.000000,43.000000]|[43.000000,83.000000,67.000000,43.000000] diff --git a/test/test_files/tinysnb/function/list.test b/test/test_files/tinysnb/function/list.test index ebb76b551a7..2a09e64c1a7 100644 --- a/test/test_files/tinysnb/function/list.test +++ b/test/test_files/tinysnb/function/list.test @@ -26,13 +26,13 @@ list_reverse(cast([interval('1 days'), interval('2 days'), interval('3 days')], 'INTERVAL[]')), list_reverse(['long string 1', 'long string 2']), list_reverse(cast(['long string 1', 'long string 2'], 'BLOB[]')), - list_reverse(cast(['123', '345'], 'UUID[]')), + list_reverse(cast(['47c256ed-b2c4-40a0-8135-98d9c25329f7', '374a9e4a-632e-47b5-9e3d-d37b08b7980b'], 'UUID[]')), list_reverse([[1,2,3], [5,6], [7,8,9]]), list_reverse([map([1,2,3], [11,22,33]), map([5,6], [55,66])]), list_reverse([{a:1, b:2}, {c:3, d:4}]), list_reverse([union_value(a:=1), union_value(a:=2)]); ---- 1 -[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3.100000,2.100000,1.100000]|[3.100000,2.100000,1.100000]|[2020-01-03,2020-01-02,2020-01-01]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00+00,2020-01-02 00:00:00+00,2020-01-01 00:00:00+00]|[3 days,2 days,1 day]|[long string 2,long string 1]|[long string 2,long string 1]|[00000000-0000-0345-0000-000000000000,00000000-0000-0123-0000-000000000000]|[[7,8,9],[5,6],[1,2,3]]|[{5=55, 6=66},{1=11, 2=22, 3=33}]|[{a: 3, b: 4},{a: 1, b: 2}]|[2,1] +[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3,2,1]|[3.100000,2.100000,1.100000]|[3.100000,2.100000,1.100000]|[2020-01-03,2020-01-02,2020-01-01]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00,2020-01-02 00:00:00,2020-01-01 00:00:00]|[2020-01-03 00:00:00+00,2020-01-02 00:00:00+00,2020-01-01 00:00:00+00]|[3 days,2 days,1 day]|[long string 2,long string 1]|[long string 2,long string 1]|[374a9e4a-632e-47b5-9e3d-d37b08b7980b,47c256ed-b2c4-40a0-8135-98d9c25329f7]|[[7,8,9],[5,6],[1,2,3]]|[{5=55, 6=66},{1=11, 2=22, 3=33}]|[{a: 3, b: 4},{a: 1, b: 2}]|[2,1] -STATEMENT MATCH p = (a:person)-[:knows*1]->(b:person) WHERE a.ID=0 RETURN list_reverse(nodes(p)), list_reverse(rels(p)), list_reverse(properties(nodes(p), 'fName')) ; ---- 3 diff --git a/test/test_files/tinysnb/function/map.test b/test/test_files/tinysnb/function/map.test index 24f09b0ac0b..ce02c8288fc 100644 --- a/test/test_files/tinysnb/function/map.test +++ b/test/test_files/tinysnb/function/map.test @@ -35,7 +35,7 @@ ---- 1 [3.200000] --LOG MapExtractVarList +-LOG MapExtractList -STATEMENT RETURN element_at(map([1, 88], [[4,5], [2,3,1]]), 1) ---- 1 [[4,5]] diff --git a/test/test_files/tinysnb/function/null.test b/test/test_files/tinysnb/function/null.test index 28e7068c1f0..8f68b4fcd80 100644 --- a/test/test_files/tinysnb/function/null.test +++ b/test/test_files/tinysnb/function/null.test @@ -1,9 +1,16 @@ -GROUP TinySnbReadTest --DATASET CSV EMPTY +-DATASET CSV tinysnb -- -CASE NullTest + +-STATEMENT MATCH (a)-[:knows]->(b:person) WHERE a.ID = 2 RETURN a.ID, a.name, a.name IS NULL; +---- 3 +2||True +2||True +2||True + -STATEMENT RETURN NULL IS NULL ---- 1 True diff --git a/test/test_files/tinysnb/function/range.test b/test/test_files/tinysnb/function/range.test index 48c45a21d70..cb2a815a003 100644 --- a/test/test_files/tinysnb/function/range.test +++ b/test/test_files/tinysnb/function/range.test @@ -55,16 +55,16 @@ Runtime exception: Step of range cannot be 0. -STATEMENT MATCH (a) RETURN range(a.NAME, 4, 1); ---- error Binder exception: Cannot match a built-in function for given function RANGE(STRING,INT64,INT64). Supported inputs are -(INT64,INT64) -> VAR_LIST -(INT64,INT64,INT64) -> VAR_LIST -(INT32,INT32) -> VAR_LIST -(INT32,INT32,INT32) -> VAR_LIST -(INT16,INT16) -> VAR_LIST -(INT16,INT16,INT16) -> VAR_LIST -(INT8,INT8) -> VAR_LIST -(INT8,INT8,INT8) -> VAR_LIST -(SERIAL,SERIAL) -> VAR_LIST -(SERIAL,SERIAL,SERIAL) -> VAR_LIST +(INT64,INT64) -> LIST +(INT64,INT64,INT64) -> LIST +(INT32,INT32) -> LIST +(INT32,INT32,INT32) -> LIST +(INT16,INT16) -> LIST +(INT16,INT16,INT16) -> LIST +(INT8,INT8) -> LIST +(INT8,INT8,INT8) -> LIST +(SERIAL,SERIAL) -> LIST +(SERIAL,SERIAL,SERIAL) -> LIST -STATEMENT RETURN range(4, 3); ---- 1 [] diff --git a/test/test_files/tinysnb/function/string.test b/test/test_files/tinysnb/function/string.test index f52449f78e2..39e87705a8f 100644 --- a/test/test_files/tinysnb/function/string.test +++ b/test/test_files/tinysnb/function/string.test @@ -627,3 +627,45 @@ hellolongstringtest -STATEMENT return levenshtein('horse', 'ros'); ---- 1 3 + +-LOG ConcatMultipleStrings +-STATEMENT match (p:person) return concat("name: ", p.fName, ' ,age: ', "5"); +---- 8 +name: Alice ,age: 5 +name: Bob ,age: 5 +name: Carol ,age: 5 +name: Dan ,age: 5 +name: Elizabeth ,age: 5 +name: Farooq ,age: 5 +name: Greg ,age: 5 +name: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff ,age: 5 +-STATEMENT match (p:person)-[:knows]->(p1:person) return concat("From: ", p.fName, ', To: ', p1.fName); +---- 14 +From: Alice, To: Bob +From: Alice, To: Carol +From: Alice, To: Dan +From: Bob, To: Alice +From: Bob, To: Carol +From: Bob, To: Dan +From: Carol, To: Alice +From: Carol, To: Bob +From: Carol, To: Dan +From: Dan, To: Alice +From: Dan, To: Bob +From: Dan, To: Carol +From: Elizabeth, To: Farooq +From: Elizabeth, To: Greg + +-LOG InitCapStrings +-STATEMENT match (o:organisation) return initcap(o.name); +---- 3 +Abfsuni +Cswork +Deswork + +-LOG InitCapUTF8String +-STATEMENT match (m:movies) return initcap(m.name); +---- 3 +Sóló cón tu párejâ +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie +Roma diff --git a/test/test_files/tinysnb/function/uuid.test b/test/test_files/tinysnb/function/uuid.test index 548bec415f7..faf235a3c92 100644 --- a/test/test_files/tinysnb/function/uuid.test +++ b/test/test_files/tinysnb/function/uuid.test @@ -96,3 +96,11 @@ ffffffff-ffff-ffff-ffff-ffffffffffff -STATEMENT MATCH (a:Person) RETURN collect(a.u) ---- 1 [a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11,47183823-2574-4bfd-b411-99ed177d3e43,10203040-5060-7080-0102-030405060708,a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12,47183823-2574-4bfd-b411-99ed177d3e43,10203040-5060-7080-0102-030405060708,00000000-0000-0000-0000-000000000000,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000000,00000000-0000-0000-0000-000000000000,80000000-0000-0000-8fff-ffffffffffff,80000000-0000-0000-ffff-ffffffffffff,8fffffff-ffff-ffff-0000-000000000000,8fffffff-ffff-ffff-8000-000000000000,8fffffff-ffff-ffff-8fff-ffffffffffff,8fffffff-ffff-ffff-ffff-ffffffffffff,ffffffff-ffff-ffff-ffff-ffffffffffff] + +-STATEMENT RETURN UUID("11111111111111111"); +---- error +Conversion exception: Invalid UUID: 11111111111111111 + +-STATEMENT RETURN UUID("0"); +---- error +Conversion exception: Invalid UUID: 0 diff --git a/test/test_files/tinysnb/generic_hash_join/basic.test b/test/test_files/tinysnb/generic_hash_join/basic.test index ecdd6debce5..2164a780b9f 100644 --- a/test/test_files/tinysnb/generic_hash_join/basic.test +++ b/test/test_files/tinysnb/generic_hash_join/basic.test @@ -57,4 +57,37 @@ Hubert Blaine Wolfeschlegelsteinhausenbergerdorff|Hubert Blaine Wolfeschlegelste {rating: 5.300000, stars: 2, views: 152, release: 2011-08-20 11:25:30, release_ns: 2011-08-20 11:25:30.123456, release_ms: 2011-08-20 11:25:30.123, release_sec: 2011-08-20 11:25:30, release_tz: 2011-08-20 11:25:30.123456+00, film: 2012-05-11, u8: 220, u16: 20, u32: 1, u64: 180, hugedata: 1844674407370955161811111111}|{rating: 5.300000, stars: 2, views: 152, release: 2011-08-20 11:25:30, release_ns: 2011-08-20 11:25:30.123456, release_ms: 2011-08-20 11:25:30.123, release_sec: 2011-08-20 11:25:30, release_tz: 2011-08-20 11:25:30.123456+00, film: 2012-05-11, u8: 220, u16: 20, u32: 1, u64: 180, hugedata: 1844674407370955161811111111} {rating: 7.000000, stars: 10, views: 982, release: 2018-11-13 13:33:11, release_ns: 2018-11-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2018-11-13 13:33:11, release_tz: 2018-11-13 13:33:11.123456+00, film: 2014-09-12, u8: 12, u16: 120, u32: 55, u64: 1, hugedata: -1844674407370955161511}|{rating: 7.000000, stars: 10, views: 982, release: 2018-11-13 13:33:11, release_ns: 2018-11-13 13:33:11.123456, release_ms: 2018-11-13 13:33:11.123, release_sec: 2018-11-13 13:33:11, release_tz: 2018-11-13 13:33:11.123456+00, film: 2014-09-12, u8: 12, u16: 120, u32: 55, u64: 1, hugedata: -1844674407370955161511} +-STATEMENT MATCH (a:person), (b:person) WHERE a.workedHours = b.workedHours RETURN a.ID, b.ID +---- 8 +0|0 +10|10 +2|2 +3|3 +5|5 +7|7 +8|8 +9|9 +-STATEMENT MATCH (a:person), (b:person) WHERE a.courseScoresPerTerm = b.courseScoresPerTerm AND a.ID = b.ID RETURN SUM(a.ID) +---- 1 +44 + +-STATEMENT MATCH (a:person), (b:person) WHERE a.grades = b.grades AND a.ID = 2 RETURN a.age +---- 1 +30 + +-STATEMENT MATCH (a:person), (b:person) WHERE a.u = b.u AND a.ID = 0 RETURN a.ID +---- 1 +0 + +-STATEMENT MATCH (o:organisation), (o1:organisation) WHERE o.state = o1.state RETURN o.name +---- 3 +ABFsUni +CsWork +DEsWork + +-STATEMENT MATCH (v1:movies), (v2:movies) WHERE v1.audience = v2.audience RETURN v1.name +---- 3 +Roma +Sóló cón tu párejâ +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie diff --git a/test/test_files/tinysnb/union/union.test b/test/test_files/tinysnb/nested_types/nested_types.test similarity index 53% rename from test/test_files/tinysnb/union/union.test rename to test/test_files/tinysnb/nested_types/nested_types.test index 1521a3791a0..f03a887af3a 100644 --- a/test/test_files/tinysnb/union/union.test +++ b/test/test_files/tinysnb/nested_types/nested_types.test @@ -1,10 +1,7 @@ -GROUP TinySnbReadTest -DATASET CSV tinysnb - -- - -CASE Union - -LOG UnionAllTwoQueriesTest -STATEMENT MATCH (p:person) RETURN p.age UNION ALL MATCH (p1:person) RETURN p1.age -PARALLELISM 8 @@ -25,7 +22,6 @@ 45 83 83 - -LOG UnionAllMultipleQueriesTest -STATEMENT MATCH (p:person) RETURN p.age UNION ALL MATCH (p1:person) RETURN p1.age UNION ALL MATCH (p2:person) RETURN p2.age -PARALLELISM 2 @@ -54,7 +50,6 @@ 83 83 83 - -LOG UnionAllMultipleColumnsTest -STATEMENT MATCH (p:person) RETURN p.age, p.eyeSight UNION ALL MATCH (p1:person) RETURN p1.age, p1.eyeSight -PARALLELISM 3 @@ -75,7 +70,6 @@ 45|5.000000 83|4.900000 83|4.900000 - -LOG UnionTwoQueriesTest -STATEMENT MATCH (a:person) RETURN a.age UNION MATCH (p:person) RETURN p.age ---- 7 @@ -86,7 +80,6 @@ 40 45 83 - # If an expression to union has different flat/unflat state in different single queries, we need to flatten that # expression in all the single queries. -LOG UnionAllFlatAndUnFlatColTest @@ -135,7 +128,6 @@ 45 45 45 - -LOG UnionAllWithTest -STATEMENT MATCH (a:person)-[:knows]->(b:person) with b return b.age + 3 UNION ALL MATCH (a:person)-[e:knows]->(b:person) with a RETURN a.age -ENUMERATE @@ -168,7 +160,6 @@ 48 48 48 - -LOG UnionAllThreeHopsTest -STATEMENT MATCH (a:person)-[e1:knows]->(b:person)-[e2:knows]->(c:person)-[e3:knows]->(d:person) RETURN a.fName order by d.age desc, c.age asc, b.age asc, a.age desc limit 10 UNION ALL MATCH (p:person) RETURN p.fName -ENUMERATE @@ -191,7 +182,77 @@ Elizabeth Farooq Greg Hubert Blaine Wolfeschlegelsteinhausenbergerdorff - - -STATEMENT MATCH (a) RETURN a.* UNION ALL MATCH (b) RETURN b.* ---- ok + +-CASE RelList +-STATEMENT MATCH (a:person)-[r:knows]->(b:person) RETURN r.comments +---- 14 +[rnme,m8sihsdnf2990nfiwf] +[njnojppo9u0jkmf,fjiojioh9h9h89hph] +[ioji232,jifhe8w99u43434] +[2huh9y89fsfw23,23nsihufhw723] +[fwehu9h9832wewew,23u9h989sdfsss] +[fwh9y81232uisuiehuf,ewnuihxy8dyf232] +[fnioh8323aeweae34d,osd89e2ejshuih12] +[fwh983-sdjisdfji,ioh89y32r2huir] +[psh989823oaaioe,nuiuah1nosndfisf] +[fwewe] +[fewh9182912e3,h9y8y89soidfsf,nuhudf78w78efw,hioshe0f9023sdsd] +[23h9sdslnfowhu2932,shuhf98922323sf] +[ahu2333333333333,12weeeeeeeeeeeeeeeeee] +[peweeeeeeeeeeeeeeeee,kowje9w0eweeeeeeeee] + +-CASE RelStruct +-STATEMENT MATCH (a:person)-[r:knows]->(b:person) RETURN r.summary +---- 14 +{locations: , transfer: } +{locations: ['london','toronto'], transfer: {day: 2012-11-21, amount: [223,5230]}} +{locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}} +{locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}} +{locations: ['paris'], transfer: {day: 2000-01-01, amount: [20,5000]}} +{locations: ['paris'], transfer: {day: 2011-05-01, amount: [2000,5340]}} +{locations: ['vancouver'], transfer: {day: 2020-01-01, amount: [120,50]}} +{locations: ['paris','beijing'], transfer: {day: 2011-03-11, amount: [2323,50]}} +{locations: [], transfer: {day: 1980-11-21, amount: [20,5]}} +{locations: ['shanghai','nanjing'], transfer: {day: 1998-11-12, amount: [22,53240]}} +{locations: ['paris'], transfer: {day: 2000-01-01, amount: [20,5000]}} +{locations: ['paris'], transfer: {day: 2000-01-01, amount: [20,5000]}} +{locations: ['toronto','thisisalongcityname'], transfer: {day: 1930-11-22, amount: [18,323]}} +{locations: ['waterloo'], transfer: {day: 2000-01-01, amount: [1000,5000]}} + +-CASE RelMap +-STATEMENT MATCH (a:person)-[r:knows]->(b:person) RETURN r.someMap +---- 14 +{a=b} +{c=d, e=f, 1=2} + + + + + + + + + + + + + +-CASE RelUnion +-STATEMENT MATCH (a:person)-[r:knows]->(b:person) RETURN r.notes +---- 14 +1 +1 +10 +10 +15 +2 +2020-10-10 +4 +4 +8 +nice weather +cool stuff found +matthew perry +happy new year diff --git a/test/test_files/tinysnb/parquet/tinysnb_parquet.test b/test/test_files/tinysnb/parquet/tinysnb_parquet.test index 18378e4dab3..bff6331e0e4 100644 --- a/test/test_files/tinysnb/parquet/tinysnb_parquet.test +++ b/test/test_files/tinysnb/parquet/tinysnb_parquet.test @@ -1,9 +1,7 @@ -# one sample from each tinysnb csv test CSV_TO_PARQUET -# https://github.com/kuzudb/kuzu/issues/1627 +# This test group is currently disabled since exporting fixed-list to parquet is not supported yet -GROUP TinySnbParquet --SKIP -DATASET PARQUET CSV_TO_PARQUET(tinysnb) - +-SKIP -- -CASE TinySnbParquet diff --git a/test/test_files/tinysnb/path/path.test b/test/test_files/tinysnb/path/path.test index b1f8ab146a2..62d81362978 100644 --- a/test/test_files/tinysnb/path/path.test +++ b/test/test_files/tinysnb/path/path.test @@ -83,18 +83,18 @@ -STATEMENT MATCH p = (a:person)-[e:knows*1..2]->(b:person) RETURN size(a) ---- error Binder exception: Cannot match a built-in function for given function SIZE(NODE). Supported inputs are -(VAR_LIST) -> INT64 +(LIST) -> INT64 (MAP) -> INT64 (STRING) -> INT64 -STATEMENT MATCH p = (a:person)-[e:knows*1..2]->(b:person) RETURN size(p) ---- error Binder exception: Cannot match a built-in function for given function SIZE(RECURSIVE_REL). Supported inputs are -(VAR_LIST) -> INT64 +(LIST) -> INT64 (MAP) -> INT64 (STRING) -> INT64 -STATEMENT MATCH p = (a:person)-[e:knows]->(b:person) RETURN size(e) ---- error Binder exception: Cannot match a built-in function for given function SIZE(REL). Supported inputs are -(VAR_LIST) -> INT64 +(LIST) -> INT64 (MAP) -> INT64 (STRING) -> INT64 diff --git a/test/test_files/tinysnb/projection/single_label.test b/test/test_files/tinysnb/projection/single_label.test index bdae8cc6060..1b7af024e9b 100644 --- a/test/test_files/tinysnb/projection/single_label.test +++ b/test/test_files/tinysnb/projection/single_label.test @@ -395,7 +395,7 @@ Dan|Carol #(0:2)-{_LABEL: marries, _ID: 7:1, address: [2,5], note: long long long string}->(0:3) #(0:4)-{_LABEL: marries, _ID: 7:2, usedAddress: [], address: [3,9], note: short str}->(0:5) --LOG ReturnFixedListNodeProp +-LOG ReturnArrayNodeProp -STATEMENT MATCH (a:person) RETURN a.grades ---- 8 [96,54,86,92] @@ -407,7 +407,7 @@ Dan|Carol [43,83,67,43] [77,64,100,54] --LOG ReturnFixedListRelProp +-LOG ReturnArrayRelProp -STATEMENT MATCH (a:person)-[e:workAt]->(o:organisation) RETURN e.grading ---- 3 [2.100000,4.400000] @@ -433,7 +433,7 @@ Dan|Carol 7.600000 9.200000 --LOG ReturnFixedListFloatRelProp +-LOG ReturnArrayFloatRelProp -STATEMENT MATCH (a:person)-[e:meets]->(b:person) RETURN e.location ---- 7 [7.820000,3.540000] @@ -458,7 +458,7 @@ Dan|Carol 55 22 --LOG ReturnFixedListInt16RelProp +-LOG ReturnArrayInt16RelProp -STATEMENT MATCH (a:person)-[e:marries]->(b:person) RETURN e.address ---- 3 [4,5] diff --git a/test/test_files/tinysnb/projection/skip_limit.test b/test/test_files/tinysnb/projection/skip_limit.test index 7102700791f..70adf7ba082 100644 --- a/test/test_files/tinysnb/projection/skip_limit.test +++ b/test/test_files/tinysnb/projection/skip_limit.test @@ -106,14 +106,14 @@ Dan ---- 1 Bob --LOG LimitFixedListNodeProp +-LOG LimitArrayNodeProp -STATEMENT MATCH (a:person) RETURN a.grades LIMIT 3 ---- 3 [96,54,86,92] [98,42,93,88] [91,75,21,95] --LOG LimitFixedListRelProp +-LOG LimitArrayRelProp -STATEMENT MATCH (a:person)-[e:workAt]->(o:organisation) RETURN e.grading LIMIT 2 ---- 2 [2.100000,4.400000] diff --git a/test/test_files/tinysnb/unwind/unwind.test b/test/test_files/tinysnb/unwind/unwind.test index a71c54fd679..1c0e2c27fd7 100644 --- a/test/test_files/tinysnb/unwind/unwind.test +++ b/test/test_files/tinysnb/unwind/unwind.test @@ -17,10 +17,10 @@ Binder exception: Cannot set expression n with type VARIABLE. Expect node or rel Binder exception: Cannot delete expression n with type VARIABLE. Expect node or rel pattern. -STATEMENT UNWIND 1 AS a RETURN a; ---- error -Binder exception: Expression 1 has data type INT64 but expected VAR_LIST. Implicit cast is not supported. +Binder exception: 1 has data type INT64 but LIST was expected. -STATEMENT MATCH p = (a:person)-[e:knows*1..2]->(b:person) UNWIND p AS x RETURN x; ---- error -Binder exception: Expression p has data type RECURSIVE_REL but expected VAR_LIST. Implicit cast is not supported. +Binder exception: p has data type RECURSIVE_REL but LIST was expected. -STATEMENT MATCH p = (a:person)-[e:knows*1..1]->(b:person) UNWIND nodes(p) AS x RETURN x.fName, COUNT(*); ---- 7 Alice|6 diff --git a/test/test_files/tinysnb/unwind/unwind_list_node.test b/test/test_files/tinysnb/unwind/unwind_list_node.test new file mode 100644 index 00000000000..7b70ab2b1c1 --- /dev/null +++ b/test/test_files/tinysnb/unwind/unwind_list_node.test @@ -0,0 +1,75 @@ +-GROUP TinySnbReadTest +-DATASET CSV tinysnb + +-- + +-CASE UnwindListOfNodes + +-STATEMENT MATCH (a:person) WHERE a.ID < 4 WITH collect(a) AS list_a UNWIND list_a AS a RETURN a.fName; +---- 3 +Alice +Bob +Carol + +-STATEMENT MATCH (a:person) WHERE a.ID < 4 WITH collect(a) AS list_a UNWIND list_a AS a MATCH (a)-[:knows]->(b:person) RETURN a.fName, b.fName +---- 9 +Alice|Bob +Alice|Carol +Alice|Dan +Bob|Alice +Bob|Carol +Bob|Dan +Carol|Alice +Carol|Bob +Carol|Dan + +-STATEMENT CREATE NODE TABLE PPT (id UUID, type STRING, PRIMARY KEY(id)); +---- ok +-STATEMENT CREATE NODE TABLE PPI (id SERIAL, task_id UUID, di STRING, name STRING, PRIMARY KEY(id)); +---- ok +-STATEMENT CREATE REL TABLE PPHT (FROM PPT TO PPI); +---- ok +-STATEMENT CREATE REL TABLE PPPI (FROM person TO PPI); +---- ok +-STATEMENT CREATE REL TABLE OPPI (FROM organisation TO PPI); +---- ok +-STATEMENT MATCH (a:person)-[e:knows]->(b:person)-[:studyAt]->(o:organisation) + WHERE a.ID =0 AND b.ID = 2 + WITH + a, o, collect(b) AS list_b + WITH + *, gen_random_uuid() AS task_id + CREATE (:PPT { + id: task_id, + type: 'p_install' + })-[:PPHT]->(t:PPI { + task_id: task_id, + di: o.name, + name: a.fName + }), + (a)-[:PPPI]->(t), + (o)-[:OPPI]->(t) + WITH t, list_b + UNWIND list_b AS b + CREATE (b)-[e:PPPI]->(t) + RETURN t.di, t.name, b.fName; +---- 1 +ABFsUni|Alice|Bob +# Check update result +-STATEMENT MATCH (a:PPT) RETURN a.type; +---- 1 +p_install +-STATEMENT MATCH (a:PPI) RETURN a.di, a.name; +---- 1 +ABFsUni|Alice +-STATEMENT MATCH (a:PPT)-[:PPHT]->(t:PPI) RETURN a.type, t.di, t.name; +---- 1 +p_install|ABFsUni|Alice +-STATEMENT MATCH (a:person)-[:PPPI]->(t:PPI)<-[:OPPI]-(b:organisation) RETURN a.fName, b.name; +---- 2 +Alice|ABFsUni +Bob|ABFsUni + +-STATEMENT MATCH p = (a:person)-[:knows]->(b:person) UNWIND nodes(p) AS n MATCH (n)-[]->() RETURN COUNT(*); +---- error +Binder exception: Cannot bind n as node pattern. diff --git a/test/test_files/update_node/create_empty.test b/test/test_files/update_node/create_empty.test index b2abd0f580c..74f7b552b7e 100644 --- a/test/test_files/update_node/create_empty.test +++ b/test/test_files/update_node/create_empty.test @@ -36,7 +36,7 @@ -STATEMENT COMMIT ---- ok --CASE CreateVarList +-CASE CreateList -STATEMENT CREATE NODE TABLE test(id INT64, prop STRING[], PRIMARY KEY(id)); ---- ok -STATEMENT CREATE (a:test {id:1, prop:['A', 'B', 'C', 'This is a long string for test']}) diff --git a/test/test_files/update_node/create_random_int.test b/test/test_files/update_node/create_random_int.test new file mode 100644 index 00000000000..8af6cf3c0a0 --- /dev/null +++ b/test/test_files/update_node/create_random_int.test @@ -0,0 +1,20010 @@ +-GROUP CreateRandomInt +-DATASET CSV empty +-- +-CASE Seed10 +-SKIP_32BIT +-STATEMENT CREATE NODE TABLE test(id SERIAL, prop INT64, PRIMARY KEY(id)); +---- ok +-STATEMENT CREATE (t:test {prop: 599159}); +---- ok +-STATEMENT CREATE (t:test {prop: 34167}); +---- ok +-STATEMENT CREATE (t:test {prop: 449722}); +---- ok +-STATEMENT CREATE (t:test {prop: 506002}); +---- ok +-STATEMENT CREATE (t:test {prop: 606172}); +---- ok +-STATEMENT CREATE (t:test {prop: 15552}); +---- ok +-STATEMENT CREATE (t:test {prop: 216109}); +---- ok +-STATEMENT CREATE (t:test {prop: 485050}); +---- ok +-STATEMENT CREATE (t:test {prop: 852829}); +---- ok +-STATEMENT CREATE (t:test {prop: 515161}); +---- ok +-STATEMENT CREATE (t:test {prop: 863595}); +---- ok +-STATEMENT CREATE (t:test {prop: 291001}); +---- ok +-STATEMENT CREATE (t:test {prop: 685215}); +---- ok +-STATEMENT CREATE (t:test {prop: 849995}); +---- ok +-STATEMENT CREATE (t:test {prop: 168012}); +---- ok +-STATEMENT CREATE (t:test {prop: 36074}); +---- ok +-STATEMENT CREATE (t:test {prop: 545961}); +---- ok +-STATEMENT CREATE (t:test {prop: 513891}); +---- ok +-STATEMENT CREATE (t:test {prop: 343694}); +---- ok +-STATEMENT CREATE (t:test {prop: 79785}); +---- ok +-STATEMENT CREATE (t:test {prop: 262140}); +---- ok +-STATEMENT CREATE (t:test {prop: 998662}); +---- ok +-STATEMENT CREATE (t:test {prop: 999100}); +---- ok +-STATEMENT CREATE (t:test {prop: 781762}); +---- ok +-STATEMENT CREATE (t:test {prop: 378702}); +---- ok +-STATEMENT CREATE (t:test {prop: 46720}); +---- ok +-STATEMENT CREATE (t:test {prop: 440817}); +---- ok +-STATEMENT CREATE (t:test {prop: 901944}); +---- ok +-STATEMENT CREATE (t:test {prop: 145426}); +---- ok +-STATEMENT CREATE (t:test {prop: 632491}); +---- ok +-STATEMENT CREATE (t:test {prop: 372330}); +---- ok +-STATEMENT CREATE (t:test {prop: 400142}); +---- ok +-STATEMENT CREATE (t:test {prop: 441727}); +---- ok +-STATEMENT CREATE (t:test {prop: 297395}); +---- ok +-STATEMENT CREATE (t:test {prop: 867013}); +---- ok +-STATEMENT CREATE (t:test {prop: 707751}); +---- ok +-STATEMENT CREATE (t:test {prop: 275063}); +---- ok +-STATEMENT CREATE (t:test {prop: 479022}); +---- ok +-STATEMENT CREATE (t:test {prop: 183155}); +---- ok +-STATEMENT CREATE (t:test {prop: 719177}); +---- ok +-STATEMENT CREATE (t:test {prop: 317828}); +---- ok +-STATEMENT CREATE (t:test {prop: 693996}); +---- ok +-STATEMENT CREATE (t:test {prop: 380200}); +---- ok +-STATEMENT CREATE (t:test {prop: 139437}); +---- ok +-STATEMENT CREATE (t:test {prop: 479124}); +---- ok +-STATEMENT CREATE (t:test {prop: 805136}); +---- ok +-STATEMENT CREATE (t:test {prop: 901826}); +---- ok +-STATEMENT CREATE (t:test {prop: 251008}); +---- ok +-STATEMENT CREATE (t:test {prop: 461004}); +---- ok +-STATEMENT CREATE (t:test {prop: 643119}); +---- ok +-STATEMENT CREATE (t:test {prop: 393470}); +---- ok +-STATEMENT CREATE (t:test {prop: 46410}); +---- ok +-STATEMENT CREATE (t:test {prop: 611248}); +---- ok +-STATEMENT CREATE (t:test {prop: 4252}); +---- ok +-STATEMENT CREATE (t:test {prop: 247101}); +---- ok +-STATEMENT CREATE (t:test {prop: 140480}); +---- ok +-STATEMENT CREATE (t:test {prop: 204423}); +---- ok +-STATEMENT CREATE (t:test {prop: 986712}); +---- ok +-STATEMENT CREATE (t:test {prop: 953772}); +---- ok +-STATEMENT CREATE (t:test {prop: 317572}); +---- ok +-STATEMENT CREATE (t:test {prop: 562398}); +---- ok +-STATEMENT CREATE (t:test {prop: 383931}); +---- ok +-STATEMENT CREATE (t:test {prop: 809558}); +---- ok +-STATEMENT CREATE (t:test {prop: 941827}); +---- ok +-STATEMENT CREATE (t:test {prop: 251849}); +---- ok +-STATEMENT CREATE (t:test {prop: 329634}); +---- ok +-STATEMENT CREATE (t:test {prop: 699075}); +---- ok +-STATEMENT CREATE (t:test {prop: 575649}); +---- ok +-STATEMENT CREATE (t:test {prop: 472512}); +---- ok +-STATEMENT CREATE (t:test {prop: 457211}); +---- ok +-STATEMENT CREATE (t:test {prop: 492803}); +---- ok +-STATEMENT CREATE (t:test {prop: 68151}); +---- ok +-STATEMENT CREATE (t:test {prop: 684696}); +---- ok +-STATEMENT CREATE (t:test {prop: 612941}); +---- ok +-STATEMENT CREATE (t:test {prop: 340460}); +---- ok +-STATEMENT CREATE (t:test {prop: 885069}); +---- ok +-STATEMENT CREATE (t:test {prop: 526298}); +---- ok +-STATEMENT CREATE (t:test {prop: 164017}); +---- ok +-STATEMENT CREATE (t:test {prop: 883084}); +---- ok +-STATEMENT CREATE (t:test {prop: 235194}); +---- ok +-STATEMENT CREATE (t:test {prop: 432925}); +---- ok +-STATEMENT CREATE (t:test {prop: 249953}); +---- ok +-STATEMENT CREATE (t:test {prop: 38718}); +---- ok +-STATEMENT CREATE (t:test {prop: 33288}); +---- ok +-STATEMENT CREATE (t:test {prop: 520726}); +---- ok +-STATEMENT CREATE (t:test {prop: 315793}); +---- ok +-STATEMENT CREATE (t:test {prop: 857717}); +---- ok +-STATEMENT CREATE (t:test {prop: 636147}); +---- ok +-STATEMENT CREATE (t:test {prop: 689848}); +---- ok +-STATEMENT CREATE (t:test {prop: 75533}); +---- ok +-STATEMENT CREATE (t:test {prop: 559398}); +---- ok +-STATEMENT CREATE (t:test {prop: 969164}); +---- ok +-STATEMENT CREATE (t:test {prop: 896664}); +---- ok +-STATEMENT CREATE (t:test {prop: 84881}); +---- ok +-STATEMENT CREATE (t:test {prop: 156959}); +---- ok +-STATEMENT CREATE (t:test {prop: 403092}); +---- ok +-STATEMENT CREATE (t:test {prop: 594789}); +---- ok +-STATEMENT CREATE (t:test {prop: 991496}); +---- ok +-STATEMENT CREATE (t:test {prop: 392350}); +---- ok +-STATEMENT CREATE (t:test {prop: 957310}); +---- ok +-STATEMENT CREATE (t:test {prop: 630513}); +---- ok +-STATEMENT CREATE (t:test {prop: 156931}); +---- ok +-STATEMENT CREATE (t:test {prop: 118400}); +---- ok +-STATEMENT CREATE (t:test {prop: 813184}); +---- ok +-STATEMENT CREATE (t:test {prop: 810694}); +---- ok +-STATEMENT CREATE (t:test {prop: 101298}); +---- ok +-STATEMENT CREATE (t:test {prop: 462999}); +---- ok +-STATEMENT CREATE (t:test {prop: 174445}); +---- ok +-STATEMENT CREATE (t:test {prop: 846672}); +---- ok +-STATEMENT CREATE (t:test {prop: 200200}); +---- ok +-STATEMENT CREATE (t:test {prop: 993729}); +---- ok +-STATEMENT CREATE (t:test {prop: 365618}); +---- ok +-STATEMENT CREATE (t:test {prop: 454276}); +---- ok +-STATEMENT CREATE (t:test {prop: 434195}); +---- ok +-STATEMENT CREATE (t:test {prop: 467253}); +---- ok +-STATEMENT CREATE (t:test {prop: 257406}); +---- ok +-STATEMENT CREATE (t:test {prop: 713859}); +---- ok +-STATEMENT CREATE (t:test {prop: 288047}); +---- ok +-STATEMENT CREATE (t:test {prop: 150484}); +---- ok +-STATEMENT CREATE (t:test {prop: 647236}); +---- ok +-STATEMENT CREATE (t:test {prop: 547206}); +---- ok +-STATEMENT CREATE (t:test {prop: 187129}); +---- ok +-STATEMENT CREATE (t:test {prop: 906895}); +---- ok +-STATEMENT CREATE (t:test {prop: 125286}); +---- ok +-STATEMENT CREATE (t:test {prop: 279998}); +---- ok +-STATEMENT CREATE (t:test {prop: 477872}); +---- ok +-STATEMENT CREATE (t:test {prop: 317267}); +---- ok +-STATEMENT CREATE (t:test {prop: 172949}); +---- ok +-STATEMENT CREATE (t:test {prop: 692502}); +---- ok +-STATEMENT CREATE (t:test {prop: 680237}); +---- ok +-STATEMENT CREATE (t:test {prop: 988833}); +---- ok +-STATEMENT CREATE (t:test {prop: 860939}); +---- ok +-STATEMENT CREATE (t:test {prop: 182775}); +---- ok +-STATEMENT CREATE (t:test {prop: 815279}); +---- ok +-STATEMENT CREATE (t:test {prop: 184643}); +---- ok +-STATEMENT CREATE (t:test {prop: 503456}); +---- ok +-STATEMENT CREATE (t:test {prop: 810391}); +---- ok +-STATEMENT CREATE (t:test {prop: 364454}); +---- ok +-STATEMENT CREATE (t:test {prop: 343999}); +---- ok +-STATEMENT CREATE (t:test {prop: 455827}); +---- ok +-STATEMENT CREATE (t:test {prop: 234530}); +---- ok +-STATEMENT CREATE (t:test {prop: 5251}); +---- ok +-STATEMENT CREATE (t:test {prop: 571317}); +---- ok +-STATEMENT CREATE (t:test {prop: 747187}); +---- ok +-STATEMENT CREATE (t:test {prop: 45794}); +---- ok +-STATEMENT CREATE (t:test {prop: 347767}); +---- ok +-STATEMENT CREATE (t:test {prop: 940495}); +---- ok +-STATEMENT CREATE (t:test {prop: 334939}); +---- ok +-STATEMENT CREATE (t:test {prop: 254408}); +---- ok +-STATEMENT CREATE (t:test {prop: 83807}); +---- ok +-STATEMENT CREATE (t:test {prop: 274482}); +---- ok +-STATEMENT CREATE (t:test {prop: 469820}); +---- ok +-STATEMENT CREATE (t:test {prop: 424455}); +---- ok +-STATEMENT CREATE (t:test {prop: 611161}); +---- ok +-STATEMENT CREATE (t:test {prop: 165918}); +---- ok +-STATEMENT CREATE (t:test {prop: 409560}); +---- ok +-STATEMENT CREATE (t:test {prop: 965340}); +---- ok +-STATEMENT CREATE (t:test {prop: 911784}); +---- ok +-STATEMENT CREATE (t:test {prop: 519842}); +---- ok +-STATEMENT CREATE (t:test {prop: 706062}); +---- ok +-STATEMENT CREATE (t:test {prop: 936878}); +---- ok +-STATEMENT CREATE (t:test {prop: 253134}); +---- ok +-STATEMENT CREATE (t:test {prop: 772088}); +---- ok +-STATEMENT CREATE (t:test {prop: 550873}); +---- ok +-STATEMENT CREATE (t:test {prop: 954763}); +---- ok +-STATEMENT CREATE (t:test {prop: 284890}); +---- ok +-STATEMENT CREATE (t:test {prop: 545374}); +---- ok +-STATEMENT CREATE (t:test {prop: 506037}); +---- ok +-STATEMENT CREATE (t:test {prop: 631352}); +---- ok +-STATEMENT CREATE (t:test {prop: 524162}); +---- ok +-STATEMENT CREATE (t:test {prop: 65822}); +---- ok +-STATEMENT CREATE (t:test {prop: 174387}); +---- ok +-STATEMENT CREATE (t:test {prop: 513158}); +---- ok +-STATEMENT CREATE (t:test {prop: 707049}); +---- ok +-STATEMENT CREATE (t:test {prop: 483856}); +---- ok +-STATEMENT CREATE (t:test {prop: 941609}); +---- ok +-STATEMENT CREATE (t:test {prop: 420615}); +---- ok +-STATEMENT CREATE (t:test {prop: 142355}); +---- ok +-STATEMENT CREATE (t:test {prop: 440858}); +---- ok +-STATEMENT CREATE (t:test {prop: 567586}); +---- ok +-STATEMENT CREATE (t:test {prop: 613348}); +---- ok +-STATEMENT CREATE (t:test {prop: 366194}); +---- ok +-STATEMENT CREATE (t:test {prop: 564833}); +---- ok +-STATEMENT CREATE (t:test {prop: 406659}); +---- ok +-STATEMENT CREATE (t:test {prop: 513692}); +---- ok +-STATEMENT CREATE (t:test {prop: 735843}); +---- ok +-STATEMENT CREATE (t:test {prop: 173850}); +---- ok +-STATEMENT CREATE (t:test {prop: 585860}); +---- ok +-STATEMENT CREATE (t:test {prop: 462785}); +---- ok +-STATEMENT CREATE (t:test {prop: 103443}); +---- ok +-STATEMENT CREATE (t:test {prop: 435341}); +---- ok +-STATEMENT CREATE (t:test {prop: 869339}); +---- ok +-STATEMENT CREATE (t:test {prop: 37033}); +---- ok +-STATEMENT CREATE (t:test {prop: 914372}); +---- ok +-STATEMENT CREATE (t:test {prop: 2967}); +---- ok +-STATEMENT CREATE (t:test {prop: 459882}); +---- ok +-STATEMENT CREATE (t:test {prop: 561426}); +---- ok +-STATEMENT CREATE (t:test {prop: 68095}); +---- ok +-STATEMENT CREATE (t:test {prop: 53029}); +---- ok +-STATEMENT CREATE (t:test {prop: 366621}); +---- ok +-STATEMENT CREATE (t:test {prop: 97248}); +---- ok +-STATEMENT CREATE (t:test {prop: 159396}); +---- ok +-STATEMENT CREATE (t:test {prop: 114039}); +---- ok +-STATEMENT CREATE (t:test {prop: 637767}); +---- ok +-STATEMENT CREATE (t:test {prop: 476135}); +---- ok +-STATEMENT CREATE (t:test {prop: 873937}); +---- ok +-STATEMENT CREATE (t:test {prop: 838363}); +---- ok +-STATEMENT CREATE (t:test {prop: 508617}); +---- ok +-STATEMENT CREATE (t:test {prop: 146066}); +---- ok +-STATEMENT CREATE (t:test {prop: 480919}); +---- ok +-STATEMENT CREATE (t:test {prop: 903910}); +---- ok +-STATEMENT CREATE (t:test {prop: 457714}); +---- ok +-STATEMENT CREATE (t:test {prop: 812228}); +---- ok +-STATEMENT CREATE (t:test {prop: 525454}); +---- ok +-STATEMENT CREATE (t:test {prop: 967461}); +---- ok +-STATEMENT CREATE (t:test {prop: 468805}); +---- ok +-STATEMENT CREATE (t:test {prop: 359902}); +---- ok +-STATEMENT CREATE (t:test {prop: 761491}); +---- ok +-STATEMENT CREATE (t:test {prop: 271708}); +---- ok +-STATEMENT CREATE (t:test {prop: 941559}); +---- ok +-STATEMENT CREATE (t:test {prop: 827043}); +---- ok +-STATEMENT CREATE (t:test {prop: 731770}); +---- ok +-STATEMENT CREATE (t:test {prop: 480505}); +---- ok +-STATEMENT CREATE (t:test {prop: 443873}); +---- ok +-STATEMENT CREATE (t:test {prop: 344326}); +---- ok +-STATEMENT CREATE (t:test {prop: 681080}); +---- ok +-STATEMENT CREATE (t:test {prop: 544907}); +---- ok +-STATEMENT CREATE (t:test {prop: 953722}); +---- ok +-STATEMENT CREATE (t:test {prop: 548813}); +---- ok +-STATEMENT CREATE (t:test {prop: 161089}); +---- ok +-STATEMENT CREATE (t:test {prop: 775570}); +---- ok +-STATEMENT CREATE (t:test {prop: 248871}); +---- ok +-STATEMENT CREATE (t:test {prop: 338754}); +---- ok +-STATEMENT CREATE (t:test {prop: 649185}); +---- ok +-STATEMENT CREATE (t:test {prop: 34497}); +---- ok +-STATEMENT CREATE (t:test {prop: 720392}); +---- ok +-STATEMENT CREATE (t:test {prop: 205078}); +---- ok +-STATEMENT CREATE (t:test {prop: 673815}); +---- ok +-STATEMENT CREATE (t:test {prop: 948614}); +---- ok +-STATEMENT CREATE (t:test {prop: 617116}); +---- ok +-STATEMENT CREATE (t:test {prop: 603265}); +---- ok +-STATEMENT CREATE (t:test {prop: 869713}); +---- ok +-STATEMENT CREATE (t:test {prop: 658955}); +---- ok +-STATEMENT CREATE (t:test {prop: 502208}); +---- ok +-STATEMENT CREATE (t:test {prop: 26112}); +---- ok +-STATEMENT CREATE (t:test {prop: 846818}); +---- ok +-STATEMENT CREATE (t:test {prop: 122028}); +---- ok +-STATEMENT CREATE (t:test {prop: 310672}); +---- ok +-STATEMENT CREATE (t:test {prop: 456504}); +---- ok +-STATEMENT CREATE (t:test {prop: 892563}); +---- ok +-STATEMENT CREATE (t:test {prop: 900564}); +---- ok +-STATEMENT CREATE (t:test {prop: 258516}); +---- ok +-STATEMENT CREATE (t:test {prop: 753131}); +---- ok +-STATEMENT CREATE (t:test {prop: 303364}); +---- ok +-STATEMENT CREATE (t:test {prop: 931850}); +---- ok +-STATEMENT CREATE (t:test {prop: 93372}); +---- ok +-STATEMENT CREATE (t:test {prop: 48481}); +---- ok +-STATEMENT CREATE (t:test {prop: 626257}); +---- ok +-STATEMENT CREATE (t:test {prop: 957453}); +---- ok +-STATEMENT CREATE (t:test {prop: 577367}); +---- ok +-STATEMENT CREATE (t:test {prop: 804088}); +---- ok +-STATEMENT CREATE (t:test {prop: 110733}); +---- ok +-STATEMENT CREATE (t:test {prop: 856386}); +---- ok +-STATEMENT CREATE (t:test {prop: 299353}); +---- ok +-STATEMENT CREATE (t:test {prop: 170533}); +---- ok +-STATEMENT CREATE (t:test {prop: 702547}); +---- ok +-STATEMENT CREATE (t:test {prop: 500512}); +---- ok +-STATEMENT CREATE (t:test {prop: 148136}); +---- ok +-STATEMENT CREATE (t:test {prop: 378519}); +---- ok +-STATEMENT CREATE (t:test {prop: 624041}); +---- ok +-STATEMENT CREATE (t:test {prop: 420132}); +---- ok +-STATEMENT CREATE (t:test {prop: 964249}); +---- ok +-STATEMENT CREATE (t:test {prop: 825071}); +---- ok +-STATEMENT CREATE (t:test {prop: 201298}); +---- ok +-STATEMENT CREATE (t:test {prop: 366863}); +---- ok +-STATEMENT CREATE (t:test {prop: 191411}); +---- ok +-STATEMENT CREATE (t:test {prop: 83619}); +---- ok +-STATEMENT CREATE (t:test {prop: 620205}); +---- ok +-STATEMENT CREATE (t:test {prop: 204111}); +---- ok +-STATEMENT CREATE (t:test {prop: 447476}); +---- ok +-STATEMENT CREATE (t:test {prop: 217792}); +---- ok +-STATEMENT CREATE (t:test {prop: 100664}); +---- ok +-STATEMENT CREATE (t:test {prop: 717620}); +---- ok +-STATEMENT CREATE (t:test {prop: 323489}); +---- ok +-STATEMENT CREATE (t:test {prop: 930646}); +---- ok +-STATEMENT CREATE (t:test {prop: 486287}); +---- ok +-STATEMENT CREATE (t:test {prop: 905102}); +---- ok +-STATEMENT CREATE (t:test {prop: 779828}); +---- ok +-STATEMENT CREATE (t:test {prop: 787912}); +---- ok +-STATEMENT CREATE (t:test {prop: 729008}); +---- ok +-STATEMENT CREATE (t:test {prop: 867525}); +---- ok +-STATEMENT CREATE (t:test {prop: 547833}); +---- ok +-STATEMENT CREATE (t:test {prop: 757569}); +---- ok +-STATEMENT CREATE (t:test {prop: 444058}); +---- ok +-STATEMENT CREATE (t:test {prop: 469366}); +---- ok +-STATEMENT CREATE (t:test {prop: 696331}); +---- ok +-STATEMENT CREATE (t:test {prop: 779558}); +---- ok +-STATEMENT CREATE (t:test {prop: 582504}); +---- ok +-STATEMENT CREATE (t:test {prop: 218635}); +---- ok +-STATEMENT CREATE (t:test {prop: 278805}); +---- ok +-STATEMENT CREATE (t:test {prop: 626556}); +---- ok +-STATEMENT CREATE (t:test {prop: 382023}); +---- ok +-STATEMENT CREATE (t:test {prop: 121558}); +---- ok +-STATEMENT CREATE (t:test {prop: 657736}); +---- ok +-STATEMENT CREATE (t:test {prop: 820788}); +---- ok +-STATEMENT CREATE (t:test {prop: 657592}); +---- ok +-STATEMENT CREATE (t:test {prop: 8123}); +---- ok +-STATEMENT CREATE (t:test {prop: 219774}); +---- ok +-STATEMENT CREATE (t:test {prop: 444468}); +---- ok +-STATEMENT CREATE (t:test {prop: 639393}); +---- ok +-STATEMENT CREATE (t:test {prop: 428304}); +---- ok +-STATEMENT CREATE (t:test {prop: 917429}); +---- ok +-STATEMENT CREATE (t:test {prop: 400391}); +---- ok +-STATEMENT CREATE (t:test {prop: 913663}); +---- ok +-STATEMENT CREATE (t:test {prop: 851563}); +---- ok +-STATEMENT CREATE (t:test {prop: 683947}); +---- ok +-STATEMENT CREATE (t:test {prop: 209443}); +---- ok +-STATEMENT CREATE (t:test {prop: 73581}); +---- ok +-STATEMENT CREATE (t:test {prop: 809790}); +---- ok +-STATEMENT CREATE (t:test {prop: 444090}); +---- ok +-STATEMENT CREATE (t:test {prop: 835840}); +---- ok +-STATEMENT CREATE (t:test {prop: 93346}); +---- ok +-STATEMENT CREATE (t:test {prop: 863907}); +---- ok +-STATEMENT CREATE (t:test {prop: 57933}); +---- ok +-STATEMENT CREATE (t:test {prop: 364909}); +---- ok +-STATEMENT CREATE (t:test {prop: 267070}); +---- ok +-STATEMENT CREATE (t:test {prop: 377720}); +---- ok +-STATEMENT CREATE (t:test {prop: 479066}); +---- ok +-STATEMENT CREATE (t:test {prop: 444775}); +---- ok +-STATEMENT CREATE (t:test {prop: 796288}); +---- ok +-STATEMENT CREATE (t:test {prop: 203025}); +---- ok +-STATEMENT CREATE (t:test {prop: 659388}); +---- ok +-STATEMENT CREATE (t:test {prop: 785851}); +---- ok +-STATEMENT CREATE (t:test {prop: 296206}); +---- ok +-STATEMENT CREATE (t:test {prop: 489350}); +---- ok +-STATEMENT CREATE (t:test {prop: 728832}); +---- ok +-STATEMENT CREATE (t:test {prop: 308282}); +---- ok +-STATEMENT CREATE (t:test {prop: 531111}); +---- ok +-STATEMENT CREATE (t:test {prop: 523649}); +---- ok +-STATEMENT CREATE (t:test {prop: 532183}); +---- ok +-STATEMENT CREATE (t:test {prop: 952145}); +---- ok +-STATEMENT CREATE (t:test {prop: 276427}); +---- ok +-STATEMENT CREATE (t:test {prop: 424211}); +---- ok +-STATEMENT CREATE (t:test {prop: 463099}); +---- ok +-STATEMENT CREATE (t:test {prop: 670563}); +---- ok +-STATEMENT CREATE (t:test {prop: 358115}); +---- ok +-STATEMENT CREATE (t:test {prop: 365931}); +---- ok +-STATEMENT CREATE (t:test {prop: 761839}); +---- ok +-STATEMENT CREATE (t:test {prop: 290519}); +---- ok +-STATEMENT CREATE (t:test {prop: 506039}); +---- ok +-STATEMENT CREATE (t:test {prop: 949999}); +---- ok +-STATEMENT CREATE (t:test {prop: 468467}); +---- ok +-STATEMENT CREATE (t:test {prop: 894725}); +---- ok +-STATEMENT CREATE (t:test {prop: 500179}); +---- ok +-STATEMENT CREATE (t:test {prop: 615710}); +---- ok +-STATEMENT CREATE (t:test {prop: 503223}); +---- ok +-STATEMENT CREATE (t:test {prop: 88027}); +---- ok +-STATEMENT CREATE (t:test {prop: 723138}); +---- ok +-STATEMENT CREATE (t:test {prop: 566028}); +---- ok +-STATEMENT CREATE (t:test {prop: 754815}); +---- ok +-STATEMENT CREATE (t:test {prop: 384846}); +---- ok +-STATEMENT CREATE (t:test {prop: 840011}); +---- ok +-STATEMENT CREATE (t:test {prop: 757150}); +---- ok +-STATEMENT CREATE (t:test {prop: 424942}); +---- ok +-STATEMENT CREATE (t:test {prop: 955124}); +---- ok +-STATEMENT CREATE (t:test {prop: 832086}); +---- ok +-STATEMENT CREATE (t:test {prop: 176694}); +---- ok +-STATEMENT CREATE (t:test {prop: 632210}); +---- ok +-STATEMENT CREATE (t:test {prop: 435939}); +---- ok +-STATEMENT CREATE (t:test {prop: 755662}); +---- ok +-STATEMENT CREATE (t:test {prop: 591647}); +---- ok +-STATEMENT CREATE (t:test {prop: 68669}); +---- ok +-STATEMENT CREATE (t:test {prop: 624462}); +---- ok +-STATEMENT CREATE (t:test {prop: 888444}); +---- ok +-STATEMENT CREATE (t:test {prop: 769181}); +---- ok +-STATEMENT CREATE (t:test {prop: 877088}); +---- ok +-STATEMENT CREATE (t:test {prop: 321046}); +---- ok +-STATEMENT CREATE (t:test {prop: 17110}); +---- ok +-STATEMENT CREATE (t:test {prop: 620518}); +---- ok +-STATEMENT CREATE (t:test {prop: 343582}); +---- ok +-STATEMENT CREATE (t:test {prop: 683102}); +---- ok +-STATEMENT CREATE (t:test {prop: 337743}); +---- ok +-STATEMENT CREATE (t:test {prop: 77457}); +---- ok +-STATEMENT CREATE (t:test {prop: 776409}); +---- ok +-STATEMENT CREATE (t:test {prop: 415797}); +---- ok +-STATEMENT CREATE (t:test {prop: 639952}); +---- ok +-STATEMENT CREATE (t:test {prop: 392149}); +---- ok +-STATEMENT CREATE (t:test {prop: 296036}); +---- ok +-STATEMENT CREATE (t:test {prop: 635165}); +---- ok +-STATEMENT CREATE (t:test {prop: 195418}); +---- ok +-STATEMENT CREATE (t:test {prop: 252546}); +---- ok +-STATEMENT CREATE (t:test {prop: 176716}); +---- ok +-STATEMENT CREATE (t:test {prop: 322671}); +---- ok +-STATEMENT CREATE (t:test {prop: 100089}); +---- ok +-STATEMENT CREATE (t:test {prop: 583120}); +---- ok +-STATEMENT CREATE (t:test {prop: 828975}); +---- ok +-STATEMENT CREATE (t:test {prop: 856824}); +---- ok +-STATEMENT CREATE (t:test {prop: 981190}); +---- ok +-STATEMENT CREATE (t:test {prop: 55908}); +---- ok +-STATEMENT CREATE (t:test {prop: 230557}); +---- ok +-STATEMENT CREATE (t:test {prop: 597718}); +---- ok +-STATEMENT CREATE (t:test {prop: 781097}); +---- ok +-STATEMENT CREATE (t:test {prop: 77478}); +---- ok +-STATEMENT CREATE (t:test {prop: 997346}); +---- ok +-STATEMENT CREATE (t:test {prop: 442137}); +---- ok +-STATEMENT CREATE (t:test {prop: 201040}); +---- ok +-STATEMENT CREATE (t:test {prop: 597194}); +---- ok +-STATEMENT CREATE (t:test {prop: 599674}); +---- ok +-STATEMENT CREATE (t:test {prop: 460652}); +---- ok +-STATEMENT CREATE (t:test {prop: 959357}); +---- ok +-STATEMENT CREATE (t:test {prop: 843635}); +---- ok +-STATEMENT CREATE (t:test {prop: 911833}); +---- ok +-STATEMENT CREATE (t:test {prop: 622263}); +---- ok +-STATEMENT CREATE (t:test {prop: 16827}); +---- ok +-STATEMENT CREATE (t:test {prop: 411544}); +---- ok +-STATEMENT CREATE (t:test {prop: 211106}); +---- ok +-STATEMENT CREATE (t:test {prop: 355828}); +---- ok +-STATEMENT CREATE (t:test {prop: 889175}); +---- ok +-STATEMENT CREATE (t:test {prop: 931173}); +---- ok +-STATEMENT CREATE (t:test {prop: 602135}); +---- ok +-STATEMENT CREATE (t:test {prop: 200053}); +---- ok +-STATEMENT CREATE (t:test {prop: 548215}); +---- ok +-STATEMENT CREATE (t:test {prop: 977941}); +---- ok +-STATEMENT CREATE (t:test {prop: 849151}); +---- ok +-STATEMENT CREATE (t:test {prop: 591471}); +---- ok +-STATEMENT CREATE (t:test {prop: 801155}); +---- ok +-STATEMENT CREATE (t:test {prop: 808210}); +---- ok +-STATEMENT CREATE (t:test {prop: 876189}); +---- ok +-STATEMENT CREATE (t:test {prop: 342567}); +---- ok +-STATEMENT CREATE (t:test {prop: 912517}); +---- ok +-STATEMENT CREATE (t:test {prop: 49968}); +---- ok +-STATEMENT CREATE (t:test {prop: 689579}); +---- ok +-STATEMENT CREATE (t:test {prop: 725911}); +---- ok +-STATEMENT CREATE (t:test {prop: 606346}); +---- ok +-STATEMENT CREATE (t:test {prop: 52573}); +---- ok +-STATEMENT CREATE (t:test {prop: 38326}); +---- ok +-STATEMENT CREATE (t:test {prop: 592633}); +---- ok +-STATEMENT CREATE (t:test {prop: 383743}); +---- ok +-STATEMENT CREATE (t:test {prop: 901498}); +---- ok +-STATEMENT CREATE (t:test {prop: 980599}); +---- ok +-STATEMENT CREATE (t:test {prop: 416314}); +---- ok +-STATEMENT CREATE (t:test {prop: 340327}); +---- ok +-STATEMENT CREATE (t:test {prop: 630360}); +---- ok +-STATEMENT CREATE (t:test {prop: 669366}); +---- ok +-STATEMENT CREATE (t:test {prop: 179757}); +---- ok +-STATEMENT CREATE (t:test {prop: 810249}); +---- ok +-STATEMENT CREATE (t:test {prop: 165397}); +---- ok +-STATEMENT CREATE (t:test {prop: 123118}); +---- ok +-STATEMENT CREATE (t:test {prop: 635494}); +---- ok +-STATEMENT CREATE (t:test {prop: 827664}); +---- ok +-STATEMENT CREATE (t:test {prop: 906476}); +---- ok +-STATEMENT CREATE (t:test {prop: 362181}); +---- ok +-STATEMENT CREATE (t:test {prop: 172257}); +---- ok +-STATEMENT CREATE (t:test {prop: 32651}); +---- ok +-STATEMENT CREATE (t:test {prop: 758027}); +---- ok +-STATEMENT CREATE (t:test {prop: 965719}); +---- ok +-STATEMENT CREATE (t:test {prop: 562768}); +---- ok +-STATEMENT CREATE (t:test {prop: 535946}); +---- ok +-STATEMENT CREATE (t:test {prop: 844596}); +---- ok +-STATEMENT CREATE (t:test {prop: 366325}); +---- ok +-STATEMENT CREATE (t:test {prop: 92491}); +---- ok +-STATEMENT CREATE (t:test {prop: 416719}); +---- ok +-STATEMENT CREATE (t:test {prop: 460579}); +---- ok +-STATEMENT CREATE (t:test {prop: 605961}); +---- ok +-STATEMENT CREATE (t:test {prop: 923698}); +---- ok +-STATEMENT CREATE (t:test {prop: 364586}); +---- ok +-STATEMENT CREATE (t:test {prop: 62554}); +---- ok +-STATEMENT CREATE (t:test {prop: 152577}); +---- ok +-STATEMENT CREATE (t:test {prop: 968857}); +---- ok +-STATEMENT CREATE (t:test {prop: 907609}); +---- ok +-STATEMENT CREATE (t:test {prop: 466347}); +---- ok +-STATEMENT CREATE (t:test {prop: 740807}); +---- ok +-STATEMENT CREATE (t:test {prop: 493678}); +---- ok +-STATEMENT CREATE (t:test {prop: 639479}); +---- ok +-STATEMENT CREATE (t:test {prop: 473553}); +---- ok +-STATEMENT CREATE (t:test {prop: 757658}); +---- ok +-STATEMENT CREATE (t:test {prop: 463381}); +---- ok +-STATEMENT CREATE (t:test {prop: 633516}); +---- ok +-STATEMENT CREATE (t:test {prop: 183598}); +---- ok +-STATEMENT CREATE (t:test {prop: 370971}); +---- ok +-STATEMENT CREATE (t:test {prop: 864203}); +---- ok +-STATEMENT CREATE (t:test {prop: 444155}); +---- ok +-STATEMENT CREATE (t:test {prop: 862248}); +---- ok +-STATEMENT CREATE (t:test {prop: 865018}); +---- ok +-STATEMENT CREATE (t:test {prop: 360026}); +---- ok +-STATEMENT CREATE (t:test {prop: 585919}); +---- ok +-STATEMENT CREATE (t:test {prop: 537725}); +---- ok +-STATEMENT CREATE (t:test {prop: 480662}); +---- ok +-STATEMENT CREATE (t:test {prop: 407098}); +---- ok +-STATEMENT CREATE (t:test {prop: 203776}); +---- ok +-STATEMENT CREATE (t:test {prop: 101745}); +---- ok +-STATEMENT CREATE (t:test {prop: 453926}); +---- ok +-STATEMENT CREATE (t:test {prop: 672298}); +---- ok +-STATEMENT CREATE (t:test {prop: 159969}); +---- ok +-STATEMENT CREATE (t:test {prop: 43352}); +---- ok +-STATEMENT CREATE (t:test {prop: 977485}); +---- ok +-STATEMENT CREATE (t:test {prop: 901942}); +---- ok +-STATEMENT CREATE (t:test {prop: 196569}); +---- ok +-STATEMENT CREATE (t:test {prop: 671145}); +---- ok +-STATEMENT CREATE (t:test {prop: 664672}); +---- ok +-STATEMENT CREATE (t:test {prop: 199363}); +---- ok +-STATEMENT CREATE (t:test {prop: 597701}); +---- ok +-STATEMENT CREATE (t:test {prop: 449595}); +---- ok +-STATEMENT CREATE (t:test {prop: 953694}); +---- ok +-STATEMENT CREATE (t:test {prop: 832147}); +---- ok +-STATEMENT CREATE (t:test {prop: 944717}); +---- ok +-STATEMENT CREATE (t:test {prop: 377687}); +---- ok +-STATEMENT CREATE (t:test {prop: 586276}); +---- ok +-STATEMENT CREATE (t:test {prop: 394386}); +---- ok +-STATEMENT CREATE (t:test {prop: 52321}); +---- ok +-STATEMENT CREATE (t:test {prop: 634813}); +---- ok +-STATEMENT CREATE (t:test {prop: 54355}); +---- ok +-STATEMENT CREATE (t:test {prop: 173532}); +---- ok +-STATEMENT CREATE (t:test {prop: 326079}); +---- ok +-STATEMENT CREATE (t:test {prop: 995969}); +---- ok +-STATEMENT CREATE (t:test {prop: 234166}); +---- ok +-STATEMENT CREATE (t:test {prop: 51948}); +---- ok +-STATEMENT CREATE (t:test {prop: 608172}); +---- ok +-STATEMENT CREATE (t:test {prop: 185328}); +---- ok +-STATEMENT CREATE (t:test {prop: 104482}); +---- ok +-STATEMENT CREATE (t:test {prop: 667089}); +---- ok +-STATEMENT CREATE (t:test {prop: 591982}); +---- ok +-STATEMENT CREATE (t:test {prop: 377971}); +---- ok +-STATEMENT CREATE (t:test {prop: 876579}); +---- ok +-STATEMENT CREATE (t:test {prop: 194591}); +---- ok +-STATEMENT CREATE (t:test {prop: 317335}); +---- ok +-STATEMENT CREATE (t:test {prop: 993405}); +---- ok +-STATEMENT CREATE (t:test {prop: 891615}); +---- ok +-STATEMENT CREATE (t:test {prop: 44846}); +---- ok +-STATEMENT CREATE (t:test {prop: 415034}); +---- ok +-STATEMENT CREATE (t:test {prop: 627110}); +---- ok +-STATEMENT CREATE (t:test {prop: 800511}); +---- ok +-STATEMENT CREATE (t:test {prop: 449596}); +---- ok +-STATEMENT CREATE (t:test {prop: 81517}); +---- ok +-STATEMENT CREATE (t:test {prop: 362113}); +---- ok +-STATEMENT CREATE (t:test {prop: 796435}); +---- ok +-STATEMENT CREATE (t:test {prop: 204399}); +---- ok +-STATEMENT CREATE (t:test {prop: 515548}); +---- ok +-STATEMENT CREATE (t:test {prop: 170718}); +---- ok +-STATEMENT CREATE (t:test {prop: 176556}); +---- ok +-STATEMENT CREATE (t:test {prop: 425331}); +---- ok +-STATEMENT CREATE (t:test {prop: 848136}); +---- ok +-STATEMENT CREATE (t:test {prop: 788891}); +---- ok +-STATEMENT CREATE (t:test {prop: 490971}); +---- ok +-STATEMENT CREATE (t:test {prop: 986809}); +---- ok +-STATEMENT CREATE (t:test {prop: 815075}); +---- ok +-STATEMENT CREATE (t:test {prop: 344196}); +---- ok +-STATEMENT CREATE (t:test {prop: 921344}); +---- ok +-STATEMENT CREATE (t:test {prop: 39136}); +---- ok +-STATEMENT CREATE (t:test {prop: 181515}); +---- ok +-STATEMENT CREATE (t:test {prop: 873843}); +---- ok +-STATEMENT CREATE (t:test {prop: 922381}); +---- ok +-STATEMENT CREATE (t:test {prop: 184757}); +---- ok +-STATEMENT CREATE (t:test {prop: 609645}); +---- ok +-STATEMENT CREATE (t:test {prop: 740488}); +---- ok +-STATEMENT CREATE (t:test {prop: 441070}); +---- ok +-STATEMENT CREATE (t:test {prop: 160573}); +---- ok +-STATEMENT CREATE (t:test {prop: 538292}); +---- ok +-STATEMENT CREATE (t:test {prop: 672933}); +---- ok +-STATEMENT CREATE (t:test {prop: 933197}); +---- ok +-STATEMENT CREATE (t:test {prop: 730701}); +---- ok +-STATEMENT CREATE (t:test {prop: 411005}); +---- ok +-STATEMENT CREATE (t:test {prop: 98873}); +---- ok +-STATEMENT CREATE (t:test {prop: 415870}); +---- ok +-STATEMENT CREATE (t:test {prop: 852666}); +---- ok +-STATEMENT CREATE (t:test {prop: 124128}); +---- ok +-STATEMENT CREATE (t:test {prop: 246464}); +---- ok +-STATEMENT CREATE (t:test {prop: 112016}); +---- ok +-STATEMENT CREATE (t:test {prop: 443182}); +---- ok +-STATEMENT CREATE (t:test {prop: 756750}); +---- ok +-STATEMENT CREATE (t:test {prop: 669828}); +---- ok +-STATEMENT CREATE (t:test {prop: 325937}); +---- ok +-STATEMENT CREATE (t:test {prop: 758395}); +---- ok +-STATEMENT CREATE (t:test {prop: 304051}); +---- ok +-STATEMENT CREATE (t:test {prop: 559505}); +---- ok +-STATEMENT CREATE (t:test {prop: 681095}); +---- ok +-STATEMENT CREATE (t:test {prop: 890646}); +---- ok +-STATEMENT CREATE (t:test {prop: 934759}); +---- ok +-STATEMENT CREATE (t:test {prop: 103882}); +---- ok +-STATEMENT CREATE (t:test {prop: 362369}); +---- ok +-STATEMENT CREATE (t:test {prop: 874145}); +---- ok +-STATEMENT CREATE (t:test {prop: 951284}); +---- ok +-STATEMENT CREATE (t:test {prop: 547160}); +---- ok +-STATEMENT CREATE (t:test {prop: 649846}); +---- ok +-STATEMENT CREATE (t:test {prop: 498277}); +---- ok +-STATEMENT CREATE (t:test {prop: 637354}); +---- ok +-STATEMENT CREATE (t:test {prop: 256414}); +---- ok +-STATEMENT CREATE (t:test {prop: 558394}); +---- ok +-STATEMENT CREATE (t:test {prop: 304740}); +---- ok +-STATEMENT CREATE (t:test {prop: 12813}); +---- ok +-STATEMENT CREATE (t:test {prop: 697447}); +---- ok +-STATEMENT CREATE (t:test {prop: 165731}); +---- ok +-STATEMENT CREATE (t:test {prop: 709956}); +---- ok +-STATEMENT CREATE (t:test {prop: 405183}); +---- ok +-STATEMENT CREATE (t:test {prop: 727092}); +---- ok +-STATEMENT CREATE (t:test {prop: 240030}); +---- ok +-STATEMENT CREATE (t:test {prop: 101601}); +---- ok +-STATEMENT CREATE (t:test {prop: 535079}); +---- ok +-STATEMENT CREATE (t:test {prop: 667933}); +---- ok +-STATEMENT CREATE (t:test {prop: 799035}); +---- ok +-STATEMENT CREATE (t:test {prop: 497345}); +---- ok +-STATEMENT CREATE (t:test {prop: 104569}); +---- ok +-STATEMENT CREATE (t:test {prop: 604988}); +---- ok +-STATEMENT CREATE (t:test {prop: 949908}); +---- ok +-STATEMENT CREATE (t:test {prop: 418518}); +---- ok +-STATEMENT CREATE (t:test {prop: 611085}); +---- ok +-STATEMENT CREATE (t:test {prop: 228428}); +---- ok +-STATEMENT CREATE (t:test {prop: 301275}); +---- ok +-STATEMENT CREATE (t:test {prop: 372734}); +---- ok +-STATEMENT CREATE (t:test {prop: 73146}); +---- ok +-STATEMENT CREATE (t:test {prop: 925470}); +---- ok +-STATEMENT CREATE (t:test {prop: 197658}); +---- ok +-STATEMENT CREATE (t:test {prop: 652652}); +---- ok +-STATEMENT CREATE (t:test {prop: 904183}); +---- ok +-STATEMENT CREATE (t:test {prop: 585255}); +---- ok +-STATEMENT CREATE (t:test {prop: 557050}); +---- ok +-STATEMENT CREATE (t:test {prop: 27372}); +---- ok +-STATEMENT CREATE (t:test {prop: 78503}); +---- ok +-STATEMENT CREATE (t:test {prop: 419644}); +---- ok +-STATEMENT CREATE (t:test {prop: 850627}); +---- ok +-STATEMENT CREATE (t:test {prop: 32785}); +---- ok +-STATEMENT CREATE (t:test {prop: 18126}); +---- ok +-STATEMENT CREATE (t:test {prop: 684873}); +---- ok +-STATEMENT CREATE (t:test {prop: 877877}); +---- ok +-STATEMENT CREATE (t:test {prop: 451461}); +---- ok +-STATEMENT CREATE (t:test {prop: 354940}); +---- ok +-STATEMENT CREATE (t:test {prop: 874411}); +---- ok +-STATEMENT CREATE (t:test {prop: 963241}); +---- ok +-STATEMENT CREATE (t:test {prop: 186842}); +---- ok +-STATEMENT CREATE (t:test {prop: 762308}); +---- ok +-STATEMENT CREATE (t:test {prop: 49675}); +---- ok +-STATEMENT CREATE (t:test {prop: 375836}); +---- ok +-STATEMENT CREATE (t:test {prop: 340216}); +---- ok +-STATEMENT CREATE (t:test {prop: 655707}); +---- ok +-STATEMENT CREATE (t:test {prop: 499255}); +---- ok +-STATEMENT CREATE (t:test {prop: 825482}); +---- ok +-STATEMENT CREATE (t:test {prop: 179405}); +---- ok +-STATEMENT CREATE (t:test {prop: 19774}); +---- ok +-STATEMENT CREATE (t:test {prop: 215554}); +---- ok +-STATEMENT CREATE (t:test {prop: 133489}); +---- ok +-STATEMENT CREATE (t:test {prop: 303249}); +---- ok +-STATEMENT CREATE (t:test {prop: 860526}); +---- ok +-STATEMENT CREATE (t:test {prop: 211334}); +---- ok +-STATEMENT CREATE (t:test {prop: 258925}); +---- ok +-STATEMENT CREATE (t:test {prop: 950220}); +---- ok +-STATEMENT CREATE (t:test {prop: 258352}); +---- ok +-STATEMENT CREATE (t:test {prop: 405095}); +---- ok +-STATEMENT CREATE (t:test {prop: 644563}); +---- ok +-STATEMENT CREATE (t:test {prop: 571507}); +---- ok +-STATEMENT CREATE (t:test {prop: 612971}); +---- ok +-STATEMENT CREATE (t:test {prop: 624475}); +---- ok +-STATEMENT CREATE (t:test {prop: 439079}); +---- ok +-STATEMENT CREATE (t:test {prop: 916190}); +---- ok +-STATEMENT CREATE (t:test {prop: 577885}); +---- ok +-STATEMENT CREATE (t:test {prop: 797889}); +---- ok +-STATEMENT CREATE (t:test {prop: 32606}); +---- ok +-STATEMENT CREATE (t:test {prop: 131437}); +---- ok +-STATEMENT CREATE (t:test {prop: 5727}); +---- ok +-STATEMENT CREATE (t:test {prop: 129169}); +---- ok +-STATEMENT CREATE (t:test {prop: 29013}); +---- ok +-STATEMENT CREATE (t:test {prop: 879304}); +---- ok +-STATEMENT CREATE (t:test {prop: 57672}); +---- ok +-STATEMENT CREATE (t:test {prop: 718997}); +---- ok +-STATEMENT CREATE (t:test {prop: 808162}); +---- ok +-STATEMENT CREATE (t:test {prop: 804750}); +---- ok +-STATEMENT CREATE (t:test {prop: 186501}); +---- ok +-STATEMENT CREATE (t:test {prop: 130692}); +---- ok +-STATEMENT CREATE (t:test {prop: 726824}); +---- ok +-STATEMENT CREATE (t:test {prop: 403986}); +---- ok +-STATEMENT CREATE (t:test {prop: 70683}); +---- ok +-STATEMENT CREATE (t:test {prop: 15338}); +---- ok +-STATEMENT CREATE (t:test {prop: 694219}); +---- ok +-STATEMENT CREATE (t:test {prop: 455060}); +---- ok +-STATEMENT CREATE (t:test {prop: 774151}); +---- ok +-STATEMENT CREATE (t:test {prop: 693810}); +---- ok +-STATEMENT CREATE (t:test {prop: 191730}); +---- ok +-STATEMENT CREATE (t:test {prop: 654452}); +---- ok +-STATEMENT CREATE (t:test {prop: 442235}); +---- ok +-STATEMENT CREATE (t:test {prop: 945349}); +---- ok +-STATEMENT CREATE (t:test {prop: 50115}); +---- ok +-STATEMENT CREATE (t:test {prop: 578490}); +---- ok +-STATEMENT CREATE (t:test {prop: 177755}); +---- ok +-STATEMENT CREATE (t:test {prop: 55333}); +---- ok +-STATEMENT CREATE (t:test {prop: 736883}); +---- ok +-STATEMENT CREATE (t:test {prop: 394607}); +---- ok +-STATEMENT CREATE (t:test {prop: 606264}); +---- ok +-STATEMENT CREATE (t:test {prop: 481406}); +---- ok +-STATEMENT CREATE (t:test {prop: 477386}); +---- ok +-STATEMENT CREATE (t:test {prop: 352127}); +---- ok +-STATEMENT CREATE (t:test {prop: 194769}); +---- ok +-STATEMENT CREATE (t:test {prop: 36201}); +---- ok +-STATEMENT CREATE (t:test {prop: 418209}); +---- ok +-STATEMENT CREATE (t:test {prop: 657948}); +---- ok +-STATEMENT CREATE (t:test {prop: 482170}); +---- ok +-STATEMENT CREATE (t:test {prop: 512571}); +---- ok +-STATEMENT CREATE (t:test {prop: 998878}); +---- ok +-STATEMENT CREATE (t:test {prop: 743798}); +---- ok +-STATEMENT CREATE (t:test {prop: 747603}); +---- ok +-STATEMENT CREATE (t:test {prop: 382294}); +---- ok +-STATEMENT CREATE (t:test {prop: 698314}); +---- ok +-STATEMENT CREATE (t:test {prop: 73983}); +---- ok +-STATEMENT CREATE (t:test {prop: 145797}); +---- ok +-STATEMENT CREATE (t:test {prop: 278201}); +---- ok +-STATEMENT CREATE (t:test {prop: 265486}); +---- ok +-STATEMENT CREATE (t:test {prop: 184627}); +---- ok +-STATEMENT CREATE (t:test {prop: 95568}); +---- ok +-STATEMENT CREATE (t:test {prop: 483122}); +---- ok +-STATEMENT CREATE (t:test {prop: 13949}); +---- ok +-STATEMENT CREATE (t:test {prop: 161066}); +---- ok +-STATEMENT CREATE (t:test {prop: 291534}); +---- ok +-STATEMENT CREATE (t:test {prop: 82393}); +---- ok +-STATEMENT CREATE (t:test {prop: 953854}); +---- ok +-STATEMENT CREATE (t:test {prop: 550396}); +---- ok +-STATEMENT CREATE (t:test {prop: 323458}); +---- ok +-STATEMENT CREATE (t:test {prop: 147626}); +---- ok +-STATEMENT CREATE (t:test {prop: 804156}); +---- ok +-STATEMENT CREATE (t:test {prop: 109604}); +---- ok +-STATEMENT CREATE (t:test {prop: 563161}); +---- ok +-STATEMENT CREATE (t:test {prop: 126232}); +---- ok +-STATEMENT CREATE (t:test {prop: 301742}); +---- ok +-STATEMENT CREATE (t:test {prop: 739660}); +---- ok +-STATEMENT CREATE (t:test {prop: 648348}); +---- ok +-STATEMENT CREATE (t:test {prop: 845839}); +---- ok +-STATEMENT CREATE (t:test {prop: 350893}); +---- ok +-STATEMENT CREATE (t:test {prop: 849095}); +---- ok +-STATEMENT CREATE (t:test {prop: 3677}); +---- ok +-STATEMENT CREATE (t:test {prop: 603762}); +---- ok +-STATEMENT CREATE (t:test {prop: 272276}); +---- ok +-STATEMENT CREATE (t:test {prop: 666062}); +---- ok +-STATEMENT CREATE (t:test {prop: 978467}); +---- ok +-STATEMENT CREATE (t:test {prop: 790299}); +---- ok +-STATEMENT CREATE (t:test {prop: 542609}); +---- ok +-STATEMENT CREATE (t:test {prop: 448426}); +---- ok +-STATEMENT CREATE (t:test {prop: 918107}); +---- ok +-STATEMENT CREATE (t:test {prop: 534521}); +---- ok +-STATEMENT CREATE (t:test {prop: 153024}); +---- ok +-STATEMENT CREATE (t:test {prop: 747682}); +---- ok +-STATEMENT CREATE (t:test {prop: 62225}); +---- ok +-STATEMENT CREATE (t:test {prop: 664677}); +---- ok +-STATEMENT CREATE (t:test {prop: 59359}); +---- ok +-STATEMENT CREATE (t:test {prop: 638392}); +---- ok +-STATEMENT CREATE (t:test {prop: 63263}); +---- ok +-STATEMENT CREATE (t:test {prop: 677704}); +---- ok +-STATEMENT CREATE (t:test {prop: 221205}); +---- ok +-STATEMENT CREATE (t:test {prop: 561592}); +---- ok +-STATEMENT CREATE (t:test {prop: 15341}); +---- ok +-STATEMENT CREATE (t:test {prop: 224309}); +---- ok +-STATEMENT CREATE (t:test {prop: 153753}); +---- ok +-STATEMENT CREATE (t:test {prop: 320653}); +---- ok +-STATEMENT CREATE (t:test {prop: 902190}); +---- ok +-STATEMENT CREATE (t:test {prop: 724879}); +---- ok +-STATEMENT CREATE (t:test {prop: 882829}); +---- ok +-STATEMENT CREATE (t:test {prop: 439257}); +---- ok +-STATEMENT CREATE (t:test {prop: 158240}); +---- ok +-STATEMENT CREATE (t:test {prop: 900127}); +---- ok +-STATEMENT CREATE (t:test {prop: 28229}); +---- ok +-STATEMENT CREATE (t:test {prop: 392295}); +---- ok +-STATEMENT CREATE (t:test {prop: 541273}); +---- ok +-STATEMENT CREATE (t:test {prop: 701868}); +---- ok +-STATEMENT CREATE (t:test {prop: 744454}); +---- ok +-STATEMENT CREATE (t:test {prop: 121180}); +---- ok +-STATEMENT CREATE (t:test {prop: 501027}); +---- ok +-STATEMENT CREATE (t:test {prop: 314088}); +---- ok +-STATEMENT CREATE (t:test {prop: 486710}); +---- ok +-STATEMENT CREATE (t:test {prop: 892430}); +---- ok +-STATEMENT CREATE (t:test {prop: 486218}); +---- ok +-STATEMENT CREATE (t:test {prop: 184070}); +---- ok +-STATEMENT CREATE (t:test {prop: 948101}); +---- ok +-STATEMENT CREATE (t:test {prop: 656317}); +---- ok +-STATEMENT CREATE (t:test {prop: 147582}); +---- ok +-STATEMENT CREATE (t:test {prop: 29128}); +---- ok +-STATEMENT CREATE (t:test {prop: 422367}); +---- ok +-STATEMENT CREATE (t:test {prop: 638883}); +---- ok +-STATEMENT CREATE (t:test {prop: 161488}); +---- ok +-STATEMENT CREATE (t:test {prop: 473350}); +---- ok +-STATEMENT CREATE (t:test {prop: 688229}); +---- ok +-STATEMENT CREATE (t:test {prop: 943088}); +---- ok +-STATEMENT CREATE (t:test {prop: 734547}); +---- ok +-STATEMENT CREATE (t:test {prop: 865553}); +---- ok +-STATEMENT CREATE (t:test {prop: 857311}); +---- ok +-STATEMENT CREATE (t:test {prop: 810762}); +---- ok +-STATEMENT CREATE (t:test {prop: 187744}); +---- ok +-STATEMENT CREATE (t:test {prop: 355145}); +---- ok +-STATEMENT CREATE (t:test {prop: 531277}); +---- ok +-STATEMENT CREATE (t:test {prop: 701543}); +---- ok +-STATEMENT CREATE (t:test {prop: 492125}); +---- ok +-STATEMENT CREATE (t:test {prop: 162286}); +---- ok +-STATEMENT CREATE (t:test {prop: 45236}); +---- ok +-STATEMENT CREATE (t:test {prop: 513564}); +---- ok +-STATEMENT CREATE (t:test {prop: 619131}); +---- ok +-STATEMENT CREATE (t:test {prop: 408284}); +---- ok +-STATEMENT CREATE (t:test {prop: 174540}); +---- ok +-STATEMENT CREATE (t:test {prop: 492473}); +---- ok +-STATEMENT CREATE (t:test {prop: 736047}); +---- ok +-STATEMENT CREATE (t:test {prop: 287406}); +---- ok +-STATEMENT CREATE (t:test {prop: 222004}); +---- ok +-STATEMENT CREATE (t:test {prop: 518662}); +---- ok +-STATEMENT CREATE (t:test {prop: 545103}); +---- ok +-STATEMENT CREATE (t:test {prop: 370605}); +---- ok +-STATEMENT CREATE (t:test {prop: 685370}); +---- ok +-STATEMENT CREATE (t:test {prop: 590104}); +---- ok +-STATEMENT CREATE (t:test {prop: 806360}); +---- ok +-STATEMENT CREATE (t:test {prop: 999325}); +---- ok +-STATEMENT CREATE (t:test {prop: 896162}); +---- ok +-STATEMENT CREATE (t:test {prop: 583479}); +---- ok +-STATEMENT CREATE (t:test {prop: 398074}); +---- ok +-STATEMENT CREATE (t:test {prop: 156497}); +---- ok +-STATEMENT CREATE (t:test {prop: 934330}); +---- ok +-STATEMENT CREATE (t:test {prop: 672782}); +---- ok +-STATEMENT CREATE (t:test {prop: 998967}); +---- ok +-STATEMENT CREATE (t:test {prop: 331954}); +---- ok +-STATEMENT CREATE (t:test {prop: 774480}); +---- ok +-STATEMENT CREATE (t:test {prop: 984129}); +---- ok +-STATEMENT CREATE (t:test {prop: 332782}); +---- ok +-STATEMENT CREATE (t:test {prop: 136210}); +---- ok +-STATEMENT CREATE (t:test {prop: 57900}); +---- ok +-STATEMENT CREATE (t:test {prop: 479887}); +---- ok +-STATEMENT CREATE (t:test {prop: 55903}); +---- ok +-STATEMENT CREATE (t:test {prop: 706463}); +---- ok +-STATEMENT CREATE (t:test {prop: 350772}); +---- ok +-STATEMENT CREATE (t:test {prop: 553509}); +---- ok +-STATEMENT CREATE (t:test {prop: 547252}); +---- ok +-STATEMENT CREATE (t:test {prop: 50765}); +---- ok +-STATEMENT CREATE (t:test {prop: 398591}); +---- ok +-STATEMENT CREATE (t:test {prop: 639547}); +---- ok +-STATEMENT CREATE (t:test {prop: 814001}); +---- ok +-STATEMENT CREATE (t:test {prop: 964431}); +---- ok +-STATEMENT CREATE (t:test {prop: 825187}); +---- ok +-STATEMENT CREATE (t:test {prop: 85250}); +---- ok +-STATEMENT CREATE (t:test {prop: 958055}); +---- ok +-STATEMENT CREATE (t:test {prop: 731776}); +---- ok +-STATEMENT CREATE (t:test {prop: 756480}); +---- ok +-STATEMENT CREATE (t:test {prop: 37666}); +---- ok +-STATEMENT CREATE (t:test {prop: 133800}); +---- ok +-STATEMENT CREATE (t:test {prop: 34827}); +---- ok +-STATEMENT CREATE (t:test {prop: 10287}); +---- ok +-STATEMENT CREATE (t:test {prop: 975890}); +---- ok +-STATEMENT CREATE (t:test {prop: 383875}); +---- ok +-STATEMENT CREATE (t:test {prop: 456410}); +---- ok +-STATEMENT CREATE (t:test {prop: 232215}); +---- ok +-STATEMENT CREATE (t:test {prop: 691323}); +---- ok +-STATEMENT CREATE (t:test {prop: 500752}); +---- ok +-STATEMENT CREATE (t:test {prop: 874819}); +---- ok +-STATEMENT CREATE (t:test {prop: 593643}); +---- ok +-STATEMENT CREATE (t:test {prop: 961422}); +---- ok +-STATEMENT CREATE (t:test {prop: 694119}); +---- ok +-STATEMENT CREATE (t:test {prop: 758155}); +---- ok +-STATEMENT CREATE (t:test {prop: 981851}); +---- ok +-STATEMENT CREATE (t:test {prop: 94994}); +---- ok +-STATEMENT CREATE (t:test {prop: 107922}); +---- ok +-STATEMENT CREATE (t:test {prop: 71123}); +---- ok +-STATEMENT CREATE (t:test {prop: 384073}); +---- ok +-STATEMENT CREATE (t:test {prop: 847589}); +---- ok +-STATEMENT CREATE (t:test {prop: 478145}); +---- ok +-STATEMENT CREATE (t:test {prop: 448527}); +---- ok +-STATEMENT CREATE (t:test {prop: 326453}); +---- ok +-STATEMENT CREATE (t:test {prop: 186270}); +---- ok +-STATEMENT CREATE (t:test {prop: 785894}); +---- ok +-STATEMENT CREATE (t:test {prop: 132794}); +---- ok +-STATEMENT CREATE (t:test {prop: 800790}); +---- ok +-STATEMENT CREATE (t:test {prop: 660839}); +---- ok +-STATEMENT CREATE (t:test {prop: 419111}); +---- ok +-STATEMENT CREATE (t:test {prop: 569762}); +---- ok +-STATEMENT CREATE (t:test {prop: 731947}); +---- ok +-STATEMENT CREATE (t:test {prop: 566644}); +---- ok +-STATEMENT CREATE (t:test {prop: 201881}); +---- ok +-STATEMENT CREATE (t:test {prop: 713904}); +---- ok +-STATEMENT CREATE (t:test {prop: 997607}); +---- ok +-STATEMENT CREATE (t:test {prop: 781870}); +---- ok +-STATEMENT CREATE (t:test {prop: 253208}); +---- ok +-STATEMENT CREATE (t:test {prop: 754319}); +---- ok +-STATEMENT CREATE (t:test {prop: 163814}); +---- ok +-STATEMENT CREATE (t:test {prop: 879091}); +---- ok +-STATEMENT CREATE (t:test {prop: 400716}); +---- ok +-STATEMENT CREATE (t:test {prop: 228783}); +---- ok +-STATEMENT CREATE (t:test {prop: 904972}); +---- ok +-STATEMENT CREATE (t:test {prop: 540661}); +---- ok +-STATEMENT CREATE (t:test {prop: 627295}); +---- ok +-STATEMENT CREATE (t:test {prop: 513212}); +---- ok +-STATEMENT CREATE (t:test {prop: 719437}); +---- ok +-STATEMENT CREATE (t:test {prop: 870009}); +---- ok +-STATEMENT CREATE (t:test {prop: 858028}); +---- ok +-STATEMENT CREATE (t:test {prop: 695664}); +---- ok +-STATEMENT CREATE (t:test {prop: 404652}); +---- ok +-STATEMENT CREATE (t:test {prop: 826506}); +---- ok +-STATEMENT CREATE (t:test {prop: 199974}); +---- ok +-STATEMENT CREATE (t:test {prop: 71220}); +---- ok +-STATEMENT CREATE (t:test {prop: 561168}); +---- ok +-STATEMENT CREATE (t:test {prop: 764924}); +---- ok +-STATEMENT CREATE (t:test {prop: 785767}); +---- ok +-STATEMENT CREATE (t:test {prop: 162438}); +---- ok +-STATEMENT CREATE (t:test {prop: 895235}); +---- ok +-STATEMENT CREATE (t:test {prop: 635621}); +---- ok +-STATEMENT CREATE (t:test {prop: 620379}); +---- ok +-STATEMENT CREATE (t:test {prop: 564272}); +---- ok +-STATEMENT CREATE (t:test {prop: 136518}); +---- ok +-STATEMENT CREATE (t:test {prop: 74913}); +---- ok +-STATEMENT CREATE (t:test {prop: 688709}); +---- ok +-STATEMENT CREATE (t:test {prop: 415266}); +---- ok +-STATEMENT CREATE (t:test {prop: 477838}); +---- ok +-STATEMENT CREATE (t:test {prop: 93047}); +---- ok +-STATEMENT CREATE (t:test {prop: 895744}); +---- ok +-STATEMENT CREATE (t:test {prop: 994791}); +---- ok +-STATEMENT CREATE (t:test {prop: 219421}); +---- ok +-STATEMENT CREATE (t:test {prop: 983378}); +---- ok +-STATEMENT CREATE (t:test {prop: 12348}); +---- ok +-STATEMENT CREATE (t:test {prop: 476223}); +---- ok +-STATEMENT CREATE (t:test {prop: 187526}); +---- ok +-STATEMENT CREATE (t:test {prop: 696350}); +---- ok +-STATEMENT CREATE (t:test {prop: 179101}); +---- ok +-STATEMENT CREATE (t:test {prop: 384801}); +---- ok +-STATEMENT CREATE (t:test {prop: 402977}); +---- ok +-STATEMENT CREATE (t:test {prop: 662560}); +---- ok +-STATEMENT CREATE (t:test {prop: 217890}); +---- ok +-STATEMENT CREATE (t:test {prop: 259935}); +---- ok +-STATEMENT CREATE (t:test {prop: 350184}); +---- ok +-STATEMENT CREATE (t:test {prop: 313616}); +---- ok +-STATEMENT CREATE (t:test {prop: 617683}); +---- ok +-STATEMENT CREATE (t:test {prop: 271644}); +---- ok +-STATEMENT CREATE (t:test {prop: 162476}); +---- ok +-STATEMENT CREATE (t:test {prop: 62442}); +---- ok +-STATEMENT CREATE (t:test {prop: 508124}); +---- ok +-STATEMENT CREATE (t:test {prop: 436966}); +---- ok +-STATEMENT CREATE (t:test {prop: 372838}); +---- ok +-STATEMENT CREATE (t:test {prop: 358300}); +---- ok +-STATEMENT CREATE (t:test {prop: 5148}); +---- ok +-STATEMENT CREATE (t:test {prop: 341386}); +---- ok +-STATEMENT CREATE (t:test {prop: 706945}); +---- ok +-STATEMENT CREATE (t:test {prop: 307690}); +---- ok +-STATEMENT CREATE (t:test {prop: 525872}); +---- ok +-STATEMENT CREATE (t:test {prop: 941126}); +---- ok +-STATEMENT CREATE (t:test {prop: 813926}); +---- ok +-STATEMENT CREATE (t:test {prop: 732587}); +---- ok +-STATEMENT CREATE (t:test {prop: 919447}); +---- ok +-STATEMENT CREATE (t:test {prop: 616980}); +---- ok +-STATEMENT CREATE (t:test {prop: 50371}); +---- ok +-STATEMENT CREATE (t:test {prop: 426265}); +---- ok +-STATEMENT CREATE (t:test {prop: 748794}); +---- ok +-STATEMENT CREATE (t:test {prop: 297587}); +---- ok +-STATEMENT CREATE (t:test {prop: 481599}); +---- ok +-STATEMENT CREATE (t:test {prop: 178692}); +---- ok +-STATEMENT CREATE (t:test {prop: 916709}); +---- ok +-STATEMENT CREATE (t:test {prop: 864753}); +---- ok +-STATEMENT CREATE (t:test {prop: 121118}); +---- ok +-STATEMENT CREATE (t:test {prop: 934421}); +---- ok +-STATEMENT CREATE (t:test {prop: 879522}); +---- ok +-STATEMENT CREATE (t:test {prop: 438345}); +---- ok +-STATEMENT CREATE (t:test {prop: 450473}); +---- ok +-STATEMENT CREATE (t:test {prop: 97200}); +---- ok +-STATEMENT CREATE (t:test {prop: 126534}); +---- ok +-STATEMENT CREATE (t:test {prop: 484601}); +---- ok +-STATEMENT CREATE (t:test {prop: 169420}); +---- ok +-STATEMENT CREATE (t:test {prop: 919732}); +---- ok +-STATEMENT CREATE (t:test {prop: 831330}); +---- ok +-STATEMENT CREATE (t:test {prop: 77002}); +---- ok +-STATEMENT CREATE (t:test {prop: 859602}); +---- ok +-STATEMENT CREATE (t:test {prop: 397126}); +---- ok +-STATEMENT CREATE (t:test {prop: 557098}); +---- ok +-STATEMENT CREATE (t:test {prop: 83995}); +---- ok +-STATEMENT CREATE (t:test {prop: 7400}); +---- ok +-STATEMENT CREATE (t:test {prop: 545514}); +---- ok +-STATEMENT CREATE (t:test {prop: 866850}); +---- ok +-STATEMENT CREATE (t:test {prop: 759627}); +---- ok +-STATEMENT CREATE (t:test {prop: 577495}); +---- ok +-STATEMENT CREATE (t:test {prop: 272523}); +---- ok +-STATEMENT CREATE (t:test {prop: 598411}); +---- ok +-STATEMENT CREATE (t:test {prop: 506484}); +---- ok +-STATEMENT CREATE (t:test {prop: 942966}); +---- ok +-STATEMENT CREATE (t:test {prop: 906852}); +---- ok +-STATEMENT CREATE (t:test {prop: 89113}); +---- ok +-STATEMENT CREATE (t:test {prop: 441968}); +---- ok +-STATEMENT CREATE (t:test {prop: 990212}); +---- ok +-STATEMENT CREATE (t:test {prop: 121537}); +---- ok +-STATEMENT CREATE (t:test {prop: 789672}); +---- ok +-STATEMENT CREATE (t:test {prop: 426739}); +---- ok +-STATEMENT CREATE (t:test {prop: 892226}); +---- ok +-STATEMENT CREATE (t:test {prop: 499916}); +---- ok +-STATEMENT CREATE (t:test {prop: 854813}); +---- ok +-STATEMENT CREATE (t:test {prop: 231465}); +---- ok +-STATEMENT CREATE (t:test {prop: 412931}); +---- ok +-STATEMENT CREATE (t:test {prop: 940152}); +---- ok +-STATEMENT CREATE (t:test {prop: 24317}); +---- ok +-STATEMENT CREATE (t:test {prop: 465410}); +---- ok +-STATEMENT CREATE (t:test {prop: 481058}); +---- ok +-STATEMENT CREATE (t:test {prop: 663649}); +---- ok +-STATEMENT CREATE (t:test {prop: 595741}); +---- ok +-STATEMENT CREATE (t:test {prop: 746247}); +---- ok +-STATEMENT CREATE (t:test {prop: 517056}); +---- ok +-STATEMENT CREATE (t:test {prop: 729430}); +---- ok +-STATEMENT CREATE (t:test {prop: 439993}); +---- ok +-STATEMENT CREATE (t:test {prop: 313262}); +---- ok +-STATEMENT CREATE (t:test {prop: 589192}); +---- ok +-STATEMENT CREATE (t:test {prop: 688814}); +---- ok +-STATEMENT CREATE (t:test {prop: 162743}); +---- ok +-STATEMENT CREATE (t:test {prop: 472656}); +---- ok +-STATEMENT CREATE (t:test {prop: 174674}); +---- ok +-STATEMENT CREATE (t:test {prop: 237800}); +---- ok +-STATEMENT CREATE (t:test {prop: 495282}); +---- ok +-STATEMENT CREATE (t:test {prop: 523802}); +---- ok +-STATEMENT CREATE (t:test {prop: 600271}); +---- ok +-STATEMENT CREATE (t:test {prop: 490474}); +---- ok +-STATEMENT CREATE (t:test {prop: 423142}); +---- ok +-STATEMENT CREATE (t:test {prop: 316598}); +---- ok +-STATEMENT CREATE (t:test {prop: 785843}); +---- ok +-STATEMENT CREATE (t:test {prop: 577936}); +---- ok +-STATEMENT CREATE (t:test {prop: 953045}); +---- ok +-STATEMENT CREATE (t:test {prop: 469937}); +---- ok +-STATEMENT CREATE (t:test {prop: 627102}); +---- ok +-STATEMENT CREATE (t:test {prop: 796615}); +---- ok +-STATEMENT CREATE (t:test {prop: 24322}); +---- ok +-STATEMENT CREATE (t:test {prop: 525113}); +---- ok +-STATEMENT CREATE (t:test {prop: 570891}); +---- ok +-STATEMENT CREATE (t:test {prop: 385441}); +---- ok +-STATEMENT CREATE (t:test {prop: 661507}); +---- ok +-STATEMENT CREATE (t:test {prop: 739132}); +---- ok +-STATEMENT CREATE (t:test {prop: 855106}); +---- ok +-STATEMENT CREATE (t:test {prop: 486514}); +---- ok +-STATEMENT CREATE (t:test {prop: 318169}); +---- ok +-STATEMENT CREATE (t:test {prop: 192661}); +---- ok +-STATEMENT CREATE (t:test {prop: 245786}); +---- ok +-STATEMENT CREATE (t:test {prop: 233885}); +---- ok +-STATEMENT CREATE (t:test {prop: 391901}); +---- ok +-STATEMENT CREATE (t:test {prop: 632507}); +---- ok +-STATEMENT CREATE (t:test {prop: 168414}); +---- ok +-STATEMENT CREATE (t:test {prop: 556848}); +---- ok +-STATEMENT CREATE (t:test {prop: 817207}); +---- ok +-STATEMENT CREATE (t:test {prop: 872894}); +---- ok +-STATEMENT CREATE (t:test {prop: 28423}); +---- ok +-STATEMENT CREATE (t:test {prop: 567898}); +---- ok +-STATEMENT CREATE (t:test {prop: 592225}); +---- ok +-STATEMENT CREATE (t:test {prop: 838461}); +---- ok +-STATEMENT CREATE (t:test {prop: 873691}); +---- ok +-STATEMENT CREATE (t:test {prop: 898890}); +---- ok +-STATEMENT CREATE (t:test {prop: 33972}); +---- ok +-STATEMENT CREATE (t:test {prop: 61222}); +---- ok +-STATEMENT CREATE (t:test {prop: 172456}); +---- ok +-STATEMENT CREATE (t:test {prop: 440455}); +---- ok +-STATEMENT CREATE (t:test {prop: 798597}); +---- ok +-STATEMENT CREATE (t:test {prop: 322490}); +---- ok +-STATEMENT CREATE (t:test {prop: 172670}); +---- ok +-STATEMENT CREATE (t:test {prop: 805181}); +---- ok +-STATEMENT CREATE (t:test {prop: 205226}); +---- ok +-STATEMENT CREATE (t:test {prop: 29794}); +---- ok +-STATEMENT CREATE (t:test {prop: 176213}); +---- ok +-STATEMENT CREATE (t:test {prop: 489643}); +---- ok +-STATEMENT CREATE (t:test {prop: 329441}); +---- ok +-STATEMENT CREATE (t:test {prop: 45007}); +---- ok +-STATEMENT CREATE (t:test {prop: 528616}); +---- ok +-STATEMENT CREATE (t:test {prop: 257382}); +---- ok +-STATEMENT CREATE (t:test {prop: 37337}); +---- ok +-STATEMENT CREATE (t:test {prop: 18123}); +---- ok +-STATEMENT CREATE (t:test {prop: 148526}); +---- ok +-STATEMENT CREATE (t:test {prop: 712370}); +---- ok +-STATEMENT CREATE (t:test {prop: 513098}); +---- ok +-STATEMENT CREATE (t:test {prop: 476130}); +---- ok +-STATEMENT CREATE (t:test {prop: 808721}); +---- ok +-STATEMENT CREATE (t:test {prop: 369101}); +---- ok +-STATEMENT CREATE (t:test {prop: 23227}); +---- ok +-STATEMENT CREATE (t:test {prop: 440897}); +---- ok +-STATEMENT CREATE (t:test {prop: 661888}); +---- ok +-STATEMENT CREATE (t:test {prop: 713262}); +---- ok +-STATEMENT CREATE (t:test {prop: 373719}); +---- ok +-STATEMENT CREATE (t:test {prop: 271454}); +---- ok +-STATEMENT CREATE (t:test {prop: 18049}); +---- ok +-STATEMENT CREATE (t:test {prop: 162104}); +---- ok +-STATEMENT CREATE (t:test {prop: 268247}); +---- ok +-STATEMENT CREATE (t:test {prop: 43908}); +---- ok +-STATEMENT CREATE (t:test {prop: 147717}); +---- ok +-STATEMENT CREATE (t:test {prop: 685574}); +---- ok +-STATEMENT CREATE (t:test {prop: 719119}); +---- ok +-STATEMENT CREATE (t:test {prop: 696770}); +---- ok +-STATEMENT CREATE (t:test {prop: 939381}); +---- ok +-STATEMENT CREATE (t:test {prop: 250861}); +---- ok +-STATEMENT CREATE (t:test {prop: 119890}); +---- ok +-STATEMENT CREATE (t:test {prop: 540268}); +---- ok +-STATEMENT CREATE (t:test {prop: 748278}); +---- ok +-STATEMENT CREATE (t:test {prop: 974849}); +---- ok +-STATEMENT CREATE (t:test {prop: 496371}); +---- ok +-STATEMENT CREATE (t:test {prop: 814871}); +---- ok +-STATEMENT CREATE (t:test {prop: 803344}); +---- ok +-STATEMENT CREATE (t:test {prop: 310849}); +---- ok +-STATEMENT CREATE (t:test {prop: 367552}); +---- ok +-STATEMENT CREATE (t:test {prop: 335789}); +---- ok +-STATEMENT CREATE (t:test {prop: 578891}); +---- ok +-STATEMENT CREATE (t:test {prop: 447141}); +---- ok +-STATEMENT CREATE (t:test {prop: 816570}); +---- ok +-STATEMENT CREATE (t:test {prop: 906717}); +---- ok +-STATEMENT CREATE (t:test {prop: 731829}); +---- ok +-STATEMENT CREATE (t:test {prop: 344893}); +---- ok +-STATEMENT CREATE (t:test {prop: 626386}); +---- ok +-STATEMENT CREATE (t:test {prop: 859885}); +---- ok +-STATEMENT CREATE (t:test {prop: 308980}); +---- ok +-STATEMENT CREATE (t:test {prop: 450365}); +---- ok +-STATEMENT CREATE (t:test {prop: 59196}); +---- ok +-STATEMENT CREATE (t:test {prop: 112599}); +---- ok +-STATEMENT CREATE (t:test {prop: 505660}); +---- ok +-STATEMENT CREATE (t:test {prop: 697935}); +---- ok +-STATEMENT CREATE (t:test {prop: 757851}); +---- ok +-STATEMENT CREATE (t:test {prop: 750574}); +---- ok +-STATEMENT CREATE (t:test {prop: 377179}); +---- ok +-STATEMENT CREATE (t:test {prop: 509552}); +---- ok +-STATEMENT CREATE (t:test {prop: 761816}); +---- ok +-STATEMENT CREATE (t:test {prop: 458480}); +---- ok +-STATEMENT CREATE (t:test {prop: 493846}); +---- ok +-STATEMENT CREATE (t:test {prop: 374408}); +---- ok +-STATEMENT CREATE (t:test {prop: 73250}); +---- ok +-STATEMENT CREATE (t:test {prop: 165376}); +---- ok +-STATEMENT CREATE (t:test {prop: 609148}); +---- ok +-STATEMENT CREATE (t:test {prop: 200273}); +---- ok +-STATEMENT CREATE (t:test {prop: 575845}); +---- ok +-STATEMENT CREATE (t:test {prop: 793945}); +---- ok +-STATEMENT CREATE (t:test {prop: 337358}); +---- ok +-STATEMENT CREATE (t:test {prop: 302563}); +---- ok +-STATEMENT CREATE (t:test {prop: 208774}); +---- ok +-STATEMENT CREATE (t:test {prop: 5251}); +---- ok +-STATEMENT CREATE (t:test {prop: 765072}); +---- ok +-STATEMENT CREATE (t:test {prop: 614082}); +---- ok +-STATEMENT CREATE (t:test {prop: 450514}); +---- ok +-STATEMENT CREATE (t:test {prop: 759631}); +---- ok +-STATEMENT CREATE (t:test {prop: 804186}); +---- ok +-STATEMENT CREATE (t:test {prop: 44245}); +---- ok +-STATEMENT CREATE (t:test {prop: 800035}); +---- ok +-STATEMENT CREATE (t:test {prop: 768920}); +---- ok +-STATEMENT CREATE (t:test {prop: 179691}); +---- ok +-STATEMENT CREATE (t:test {prop: 169343}); +---- ok +-STATEMENT CREATE (t:test {prop: 835376}); +---- ok +-STATEMENT CREATE (t:test {prop: 506576}); +---- ok +-STATEMENT CREATE (t:test {prop: 377866}); +---- ok +-STATEMENT CREATE (t:test {prop: 412839}); +---- ok +-STATEMENT CREATE (t:test {prop: 125909}); +---- ok +-STATEMENT CREATE (t:test {prop: 407806}); +---- ok +-STATEMENT CREATE (t:test {prop: 260138}); +---- ok +-STATEMENT CREATE (t:test {prop: 829124}); +---- ok +-STATEMENT CREATE (t:test {prop: 212467}); +---- ok +-STATEMENT CREATE (t:test {prop: 947497}); +---- ok +-STATEMENT CREATE (t:test {prop: 990955}); +---- ok +-STATEMENT CREATE (t:test {prop: 602396}); +---- ok +-STATEMENT CREATE (t:test {prop: 891238}); +---- ok +-STATEMENT CREATE (t:test {prop: 81230}); +---- ok +-STATEMENT CREATE (t:test {prop: 515283}); +---- ok +-STATEMENT CREATE (t:test {prop: 857623}); +---- ok +-STATEMENT CREATE (t:test {prop: 918807}); +---- ok +-STATEMENT CREATE (t:test {prop: 56183}); +---- ok +-STATEMENT CREATE (t:test {prop: 576451}); +---- ok +-STATEMENT CREATE (t:test {prop: 879190}); +---- ok +-STATEMENT CREATE (t:test {prop: 962940}); +---- ok +-STATEMENT CREATE (t:test {prop: 269131}); +---- ok +-STATEMENT CREATE (t:test {prop: 512233}); +---- ok +-STATEMENT CREATE (t:test {prop: 86982}); +---- ok +-STATEMENT CREATE (t:test {prop: 816552}); +---- ok +-STATEMENT CREATE (t:test {prop: 780125}); +---- ok +-STATEMENT CREATE (t:test {prop: 953684}); +---- ok +-STATEMENT CREATE (t:test {prop: 690217}); +---- ok +-STATEMENT CREATE (t:test {prop: 643030}); +---- ok +-STATEMENT CREATE (t:test {prop: 729281}); +---- ok +-STATEMENT CREATE (t:test {prop: 90538}); +---- ok +-STATEMENT CREATE (t:test {prop: 256844}); +---- ok +-STATEMENT CREATE (t:test {prop: 906885}); +---- ok +-STATEMENT CREATE (t:test {prop: 678745}); +---- ok +-STATEMENT CREATE (t:test {prop: 182954}); +---- ok +-STATEMENT CREATE (t:test {prop: 177962}); +---- ok +-STATEMENT CREATE (t:test {prop: 471097}); +---- ok +-STATEMENT CREATE (t:test {prop: 424408}); +---- ok +-STATEMENT CREATE (t:test {prop: 937311}); +---- ok +-STATEMENT CREATE (t:test {prop: 737504}); +---- ok +-STATEMENT CREATE (t:test {prop: 587186}); +---- ok +-STATEMENT CREATE (t:test {prop: 200034}); +---- ok +-STATEMENT CREATE (t:test {prop: 719362}); +---- ok +-STATEMENT CREATE (t:test {prop: 443813}); +---- ok +-STATEMENT CREATE (t:test {prop: 734200}); +---- ok +-STATEMENT CREATE (t:test {prop: 240511}); +---- ok +-STATEMENT CREATE (t:test {prop: 456026}); +---- ok +-STATEMENT CREATE (t:test {prop: 433912}); +---- ok +-STATEMENT CREATE (t:test {prop: 199265}); +---- ok +-STATEMENT CREATE (t:test {prop: 242502}); +---- ok +-STATEMENT CREATE (t:test {prop: 758724}); +---- ok +-STATEMENT CREATE (t:test {prop: 737162}); +---- ok +-STATEMENT CREATE (t:test {prop: 893516}); +---- ok +-STATEMENT CREATE (t:test {prop: 875182}); +---- ok +-STATEMENT CREATE (t:test {prop: 378012}); +---- ok +-STATEMENT CREATE (t:test {prop: 504607}); +---- ok +-STATEMENT CREATE (t:test {prop: 877707}); +---- ok +-STATEMENT CREATE (t:test {prop: 746898}); +---- ok +-STATEMENT CREATE (t:test {prop: 136814}); +---- ok +-STATEMENT CREATE (t:test {prop: 791500}); +---- ok +-STATEMENT CREATE (t:test {prop: 966864}); +---- ok +-STATEMENT CREATE (t:test {prop: 846947}); +---- ok +-STATEMENT CREATE (t:test {prop: 208011}); +---- ok +-STATEMENT CREATE (t:test {prop: 841106}); +---- ok +-STATEMENT CREATE (t:test {prop: 598501}); +---- ok +-STATEMENT CREATE (t:test {prop: 689255}); +---- ok +-STATEMENT CREATE (t:test {prop: 891843}); +---- ok +-STATEMENT CREATE (t:test {prop: 774583}); +---- ok +-STATEMENT CREATE (t:test {prop: 54979}); +---- ok +-STATEMENT CREATE (t:test {prop: 764807}); +---- ok +-STATEMENT CREATE (t:test {prop: 717770}); +---- ok +-STATEMENT CREATE (t:test {prop: 548337}); +---- ok +-STATEMENT CREATE (t:test {prop: 735659}); +---- ok +-STATEMENT CREATE (t:test {prop: 834709}); +---- ok +-STATEMENT CREATE (t:test {prop: 195404}); +---- ok +-STATEMENT CREATE (t:test {prop: 198403}); +---- ok +-STATEMENT CREATE (t:test {prop: 82365}); +---- ok +-STATEMENT CREATE (t:test {prop: 754863}); +---- ok +-STATEMENT CREATE (t:test {prop: 412661}); +---- ok +-STATEMENT CREATE (t:test {prop: 669359}); +---- ok +-STATEMENT CREATE (t:test {prop: 716738}); +---- ok +-STATEMENT CREATE (t:test {prop: 566984}); +---- ok +-STATEMENT CREATE (t:test {prop: 3159}); +---- ok +-STATEMENT CREATE (t:test {prop: 633700}); +---- ok +-STATEMENT CREATE (t:test {prop: 526869}); +---- ok +-STATEMENT CREATE (t:test {prop: 962906}); +---- ok +-STATEMENT CREATE (t:test {prop: 238587}); +---- ok +-STATEMENT CREATE (t:test {prop: 827851}); +---- ok +-STATEMENT CREATE (t:test {prop: 942191}); +---- ok +-STATEMENT CREATE (t:test {prop: 724196}); +---- ok +-STATEMENT CREATE (t:test {prop: 749076}); +---- ok +-STATEMENT CREATE (t:test {prop: 944523}); +---- ok +-STATEMENT CREATE (t:test {prop: 595882}); +---- ok +-STATEMENT CREATE (t:test {prop: 913657}); +---- ok +-STATEMENT CREATE (t:test {prop: 971024}); +---- ok +-STATEMENT CREATE (t:test {prop: 343530}); +---- ok +-STATEMENT CREATE (t:test {prop: 330499}); +---- ok +-STATEMENT CREATE (t:test {prop: 902559}); +---- ok +-STATEMENT CREATE (t:test {prop: 514358}); +---- ok +-STATEMENT CREATE (t:test {prop: 929154}); +---- ok +-STATEMENT CREATE (t:test {prop: 963898}); +---- ok +-STATEMENT CREATE (t:test {prop: 610634}); +---- ok +-STATEMENT CREATE (t:test {prop: 986195}); +---- ok +-STATEMENT CREATE (t:test {prop: 970329}); +---- ok +-STATEMENT CREATE (t:test {prop: 656638}); +---- ok +-STATEMENT CREATE (t:test {prop: 183984}); +---- ok +-STATEMENT CREATE (t:test {prop: 838915}); +---- ok +-STATEMENT CREATE (t:test {prop: 840981}); +---- ok +-STATEMENT CREATE (t:test {prop: 492248}); +---- ok +-STATEMENT CREATE (t:test {prop: 254422}); +---- ok +-STATEMENT CREATE (t:test {prop: 393712}); +---- ok +-STATEMENT CREATE (t:test {prop: 419093}); +---- ok +-STATEMENT CREATE (t:test {prop: 485761}); +---- ok +-STATEMENT CREATE (t:test {prop: 532664}); +---- ok +-STATEMENT CREATE (t:test {prop: 112050}); +---- ok +-STATEMENT CREATE (t:test {prop: 442240}); +---- ok +-STATEMENT CREATE (t:test {prop: 632629}); +---- ok +-STATEMENT CREATE (t:test {prop: 541928}); +---- ok +-STATEMENT CREATE (t:test {prop: 762594}); +---- ok +-STATEMENT CREATE (t:test {prop: 97183}); +---- ok +-STATEMENT CREATE (t:test {prop: 258608}); +---- ok +-STATEMENT CREATE (t:test {prop: 61863}); +---- ok +-STATEMENT CREATE (t:test {prop: 114307}); +---- ok +-STATEMENT CREATE (t:test {prop: 759500}); +---- ok +-STATEMENT CREATE (t:test {prop: 68410}); +---- ok +-STATEMENT CREATE (t:test {prop: 283496}); +---- ok +-STATEMENT CREATE (t:test {prop: 259868}); +---- ok +-STATEMENT CREATE (t:test {prop: 291027}); +---- ok +-STATEMENT CREATE (t:test {prop: 753829}); +---- ok +-STATEMENT CREATE (t:test {prop: 734278}); +---- ok +-STATEMENT CREATE (t:test {prop: 357226}); +---- ok +-STATEMENT CREATE (t:test {prop: 793395}); +---- ok +-STATEMENT CREATE (t:test {prop: 300263}); +---- ok +-STATEMENT CREATE (t:test {prop: 560961}); +---- ok +-STATEMENT CREATE (t:test {prop: 386070}); +---- ok +-STATEMENT CREATE (t:test {prop: 857460}); +---- ok +-STATEMENT CREATE (t:test {prop: 141932}); +---- ok +-STATEMENT CREATE (t:test {prop: 367685}); +---- ok +-STATEMENT CREATE (t:test {prop: 807939}); +---- ok +-STATEMENT CREATE (t:test {prop: 933276}); +---- ok +-STATEMENT CREATE (t:test {prop: 594320}); +---- ok +-STATEMENT CREATE (t:test {prop: 669236}); +---- ok +-STATEMENT CREATE (t:test {prop: 831018}); +---- ok +-STATEMENT CREATE (t:test {prop: 887856}); +---- ok +-STATEMENT CREATE (t:test {prop: 954170}); +---- ok +-STATEMENT CREATE (t:test {prop: 853441}); +---- ok +-STATEMENT CREATE (t:test {prop: 134332}); +---- ok +-STATEMENT CREATE (t:test {prop: 735001}); +---- ok +-STATEMENT CREATE (t:test {prop: 74993}); +---- ok +-STATEMENT CREATE (t:test {prop: 969047}); +---- ok +-STATEMENT CREATE (t:test {prop: 14667}); +---- ok +-STATEMENT CREATE (t:test {prop: 790861}); +---- ok +-STATEMENT CREATE (t:test {prop: 807082}); +---- ok +-STATEMENT CREATE (t:test {prop: 472079}); +---- ok +-STATEMENT CREATE (t:test {prop: 678089}); +---- ok +-STATEMENT CREATE (t:test {prop: 124157}); +---- ok +-STATEMENT CREATE (t:test {prop: 959510}); +---- ok +-STATEMENT CREATE (t:test {prop: 422938}); +---- ok +-STATEMENT CREATE (t:test {prop: 643570}); +---- ok +-STATEMENT CREATE (t:test {prop: 648921}); +---- ok +-STATEMENT CREATE (t:test {prop: 24074}); +---- ok +-STATEMENT CREATE (t:test {prop: 171424}); +---- ok +-STATEMENT CREATE (t:test {prop: 625475}); +---- ok +-STATEMENT CREATE (t:test {prop: 142662}); +---- ok +-STATEMENT CREATE (t:test {prop: 427763}); +---- ok +-STATEMENT CREATE (t:test {prop: 253923}); +---- ok +-STATEMENT CREATE (t:test {prop: 498703}); +---- ok +-STATEMENT CREATE (t:test {prop: 483844}); +---- ok +-STATEMENT CREATE (t:test {prop: 69449}); +---- ok +-STATEMENT CREATE (t:test {prop: 180087}); +---- ok +-STATEMENT CREATE (t:test {prop: 82036}); +---- ok +-STATEMENT CREATE (t:test {prop: 359251}); +---- ok +-STATEMENT CREATE (t:test {prop: 679946}); +---- ok +-STATEMENT CREATE (t:test {prop: 688489}); +---- ok +-STATEMENT CREATE (t:test {prop: 282340}); +---- ok +-STATEMENT CREATE (t:test {prop: 805043}); +---- ok +-STATEMENT CREATE (t:test {prop: 161836}); +---- ok +-STATEMENT CREATE (t:test {prop: 669691}); +---- ok +-STATEMENT CREATE (t:test {prop: 908842}); +---- ok +-STATEMENT CREATE (t:test {prop: 929090}); +---- ok +-STATEMENT CREATE (t:test {prop: 59920}); +---- ok +-STATEMENT CREATE (t:test {prop: 463206}); +---- ok +-STATEMENT CREATE (t:test {prop: 737251}); +---- ok +-STATEMENT CREATE (t:test {prop: 771956}); +---- ok +-STATEMENT CREATE (t:test {prop: 863030}); +---- ok +-STATEMENT CREATE (t:test {prop: 544806}); +---- ok +-STATEMENT CREATE (t:test {prop: 940087}); +---- ok +-STATEMENT CREATE (t:test {prop: 43465}); +---- ok +-STATEMENT CREATE (t:test {prop: 691284}); +---- ok +-STATEMENT CREATE (t:test {prop: 56239}); +---- ok +-STATEMENT CREATE (t:test {prop: 35047}); +---- ok +-STATEMENT CREATE (t:test {prop: 458843}); +---- ok +-STATEMENT CREATE (t:test {prop: 932653}); +---- ok +-STATEMENT CREATE (t:test {prop: 916992}); +---- ok +-STATEMENT CREATE (t:test {prop: 556202}); +---- ok +-STATEMENT CREATE (t:test {prop: 430470}); +---- ok +-STATEMENT CREATE (t:test {prop: 576497}); +---- ok +-STATEMENT CREATE (t:test {prop: 561359}); +---- ok +-STATEMENT CREATE (t:test {prop: 325613}); +---- ok +-STATEMENT CREATE (t:test {prop: 778882}); +---- ok +-STATEMENT CREATE (t:test {prop: 631065}); +---- ok +-STATEMENT CREATE (t:test {prop: 605068}); +---- ok +-STATEMENT CREATE (t:test {prop: 714495}); +---- ok +-STATEMENT CREATE (t:test {prop: 378097}); +---- ok +-STATEMENT CREATE (t:test {prop: 306303}); +---- ok +-STATEMENT CREATE (t:test {prop: 620966}); +---- ok +-STATEMENT CREATE (t:test {prop: 142023}); +---- ok +-STATEMENT CREATE (t:test {prop: 487032}); +---- ok +-STATEMENT CREATE (t:test {prop: 759303}); +---- ok +-STATEMENT CREATE (t:test {prop: 348888}); +---- ok +-STATEMENT CREATE (t:test {prop: 374142}); +---- ok +-STATEMENT CREATE (t:test {prop: 73199}); +---- ok +-STATEMENT CREATE (t:test {prop: 927939}); +---- ok +-STATEMENT CREATE (t:test {prop: 273055}); +---- ok +-STATEMENT CREATE (t:test {prop: 739517}); +---- ok +-STATEMENT CREATE (t:test {prop: 922787}); +---- ok +-STATEMENT CREATE (t:test {prop: 306948}); +---- ok +-STATEMENT CREATE (t:test {prop: 684268}); +---- ok +-STATEMENT CREATE (t:test {prop: 365298}); +---- ok +-STATEMENT CREATE (t:test {prop: 737098}); +---- ok +-STATEMENT CREATE (t:test {prop: 585889}); +---- ok +-STATEMENT CREATE (t:test {prop: 107757}); +---- ok +-STATEMENT CREATE (t:test {prop: 987884}); +---- ok +-STATEMENT CREATE (t:test {prop: 265059}); +---- ok +-STATEMENT CREATE (t:test {prop: 657189}); +---- ok +-STATEMENT CREATE (t:test {prop: 394923}); +---- ok +-STATEMENT CREATE (t:test {prop: 328530}); +---- ok +-STATEMENT CREATE (t:test {prop: 486632}); +---- ok +-STATEMENT CREATE (t:test {prop: 448689}); +---- ok +-STATEMENT CREATE (t:test {prop: 424619}); +---- ok +-STATEMENT CREATE (t:test {prop: 174746}); +---- ok +-STATEMENT CREATE (t:test {prop: 287855}); +---- ok +-STATEMENT CREATE (t:test {prop: 121664}); +---- ok +-STATEMENT CREATE (t:test {prop: 157694}); +---- ok +-STATEMENT CREATE (t:test {prop: 974247}); +---- ok +-STATEMENT CREATE (t:test {prop: 582396}); +---- ok +-STATEMENT CREATE (t:test {prop: 647476}); +---- ok +-STATEMENT CREATE (t:test {prop: 177188}); +---- ok +-STATEMENT CREATE (t:test {prop: 888170}); +---- ok +-STATEMENT CREATE (t:test {prop: 3826}); +---- ok +-STATEMENT CREATE (t:test {prop: 465646}); +---- ok +-STATEMENT CREATE (t:test {prop: 796016}); +---- ok +-STATEMENT CREATE (t:test {prop: 841847}); +---- ok +-STATEMENT CREATE (t:test {prop: 800729}); +---- ok +-STATEMENT CREATE (t:test {prop: 972393}); +---- ok +-STATEMENT CREATE (t:test {prop: 378717}); +---- ok +-STATEMENT CREATE (t:test {prop: 451024}); +---- ok +-STATEMENT CREATE (t:test {prop: 924741}); +---- ok +-STATEMENT CREATE (t:test {prop: 280214}); +---- ok +-STATEMENT CREATE (t:test {prop: 167026}); +---- ok +-STATEMENT CREATE (t:test {prop: 328724}); +---- ok +-STATEMENT CREATE (t:test {prop: 944739}); +---- ok +-STATEMENT CREATE (t:test {prop: 197863}); +---- ok +-STATEMENT CREATE (t:test {prop: 714510}); +---- ok +-STATEMENT CREATE (t:test {prop: 670314}); +---- ok +-STATEMENT CREATE (t:test {prop: 702795}); +---- ok +-STATEMENT CREATE (t:test {prop: 134963}); +---- ok +-STATEMENT CREATE (t:test {prop: 52462}); +---- ok +-STATEMENT CREATE (t:test {prop: 56199}); +---- ok +-STATEMENT CREATE (t:test {prop: 798755}); +---- ok +-STATEMENT CREATE (t:test {prop: 613005}); +---- ok +-STATEMENT CREATE (t:test {prop: 177278}); +---- ok +-STATEMENT CREATE (t:test {prop: 593336}); +---- ok +-STATEMENT CREATE (t:test {prop: 561704}); +---- ok +-STATEMENT CREATE (t:test {prop: 980217}); +---- ok +-STATEMENT CREATE (t:test {prop: 576955}); +---- ok +-STATEMENT CREATE (t:test {prop: 158607}); +---- ok +-STATEMENT CREATE (t:test {prop: 63419}); +---- ok +-STATEMENT CREATE (t:test {prop: 602785}); +---- ok +-STATEMENT CREATE (t:test {prop: 309619}); +---- ok +-STATEMENT CREATE (t:test {prop: 369726}); +---- ok +-STATEMENT CREATE (t:test {prop: 964140}); +---- ok +-STATEMENT CREATE (t:test {prop: 483461}); +---- ok +-STATEMENT CREATE (t:test {prop: 795749}); +---- ok +-STATEMENT CREATE (t:test {prop: 382698}); +---- ok +-STATEMENT CREATE (t:test {prop: 322813}); +---- ok +-STATEMENT CREATE (t:test {prop: 901387}); +---- ok +-STATEMENT CREATE (t:test {prop: 268303}); +---- ok +-STATEMENT CREATE (t:test {prop: 75554}); +---- ok +-STATEMENT CREATE (t:test {prop: 208875}); +---- ok +-STATEMENT CREATE (t:test {prop: 684275}); +---- ok +-STATEMENT CREATE (t:test {prop: 842630}); +---- ok +-STATEMENT CREATE (t:test {prop: 371899}); +---- ok +-STATEMENT CREATE (t:test {prop: 888797}); +---- ok +-STATEMENT CREATE (t:test {prop: 73436}); +---- ok +-STATEMENT CREATE (t:test {prop: 678260}); +---- ok +-STATEMENT CREATE (t:test {prop: 74527}); +---- ok +-STATEMENT CREATE (t:test {prop: 775325}); +---- ok +-STATEMENT CREATE (t:test {prop: 591719}); +---- ok +-STATEMENT CREATE (t:test {prop: 258276}); +---- ok +-STATEMENT CREATE (t:test {prop: 464237}); +---- ok +-STATEMENT CREATE (t:test {prop: 820595}); +---- ok +-STATEMENT CREATE (t:test {prop: 567641}); +---- ok +-STATEMENT CREATE (t:test {prop: 713684}); +---- ok +-STATEMENT CREATE (t:test {prop: 249246}); +---- ok +-STATEMENT CREATE (t:test {prop: 601876}); +---- ok +-STATEMENT CREATE (t:test {prop: 652603}); +---- ok +-STATEMENT CREATE (t:test {prop: 279854}); +---- ok +-STATEMENT CREATE (t:test {prop: 581651}); +---- ok +-STATEMENT CREATE (t:test {prop: 704745}); +---- ok +-STATEMENT CREATE (t:test {prop: 303395}); +---- ok +-STATEMENT CREATE (t:test {prop: 52049}); +---- ok +-STATEMENT CREATE (t:test {prop: 886719}); +---- ok +-STATEMENT CREATE (t:test {prop: 526623}); +---- ok +-STATEMENT CREATE (t:test {prop: 451165}); +---- ok +-STATEMENT CREATE (t:test {prop: 689371}); +---- ok +-STATEMENT CREATE (t:test {prop: 755733}); +---- ok +-STATEMENT CREATE (t:test {prop: 354948}); +---- ok +-STATEMENT CREATE (t:test {prop: 490103}); +---- ok +-STATEMENT CREATE (t:test {prop: 629057}); +---- ok +-STATEMENT CREATE (t:test {prop: 730480}); +---- ok +-STATEMENT CREATE (t:test {prop: 58621}); +---- ok +-STATEMENT CREATE (t:test {prop: 392049}); +---- ok +-STATEMENT CREATE (t:test {prop: 350767}); +---- ok +-STATEMENT CREATE (t:test {prop: 501537}); +---- ok +-STATEMENT CREATE (t:test {prop: 514759}); +---- ok +-STATEMENT CREATE (t:test {prop: 295825}); +---- ok +-STATEMENT CREATE (t:test {prop: 868546}); +---- ok +-STATEMENT CREATE (t:test {prop: 562708}); +---- ok +-STATEMENT CREATE (t:test {prop: 511246}); +---- ok +-STATEMENT CREATE (t:test {prop: 974997}); +---- ok +-STATEMENT CREATE (t:test {prop: 1208}); +---- ok +-STATEMENT CREATE (t:test {prop: 391366}); +---- ok +-STATEMENT CREATE (t:test {prop: 264041}); +---- ok +-STATEMENT CREATE (t:test {prop: 935519}); +---- ok +-STATEMENT CREATE (t:test {prop: 610606}); +---- ok +-STATEMENT CREATE (t:test {prop: 610154}); +---- ok +-STATEMENT CREATE (t:test {prop: 679034}); +---- ok +-STATEMENT CREATE (t:test {prop: 493135}); +---- ok +-STATEMENT CREATE (t:test {prop: 979548}); +---- ok +-STATEMENT CREATE (t:test {prop: 191414}); +---- ok +-STATEMENT CREATE (t:test {prop: 857348}); +---- ok +-STATEMENT CREATE (t:test {prop: 866543}); +---- ok +-STATEMENT CREATE (t:test {prop: 860421}); +---- ok +-STATEMENT CREATE (t:test {prop: 833871}); +---- ok +-STATEMENT CREATE (t:test {prop: 239920}); +---- ok +-STATEMENT CREATE (t:test {prop: 406295}); +---- ok +-STATEMENT CREATE (t:test {prop: 457520}); +---- ok +-STATEMENT CREATE (t:test {prop: 336870}); +---- ok +-STATEMENT CREATE (t:test {prop: 712988}); +---- ok +-STATEMENT CREATE (t:test {prop: 287190}); +---- ok +-STATEMENT CREATE (t:test {prop: 110728}); +---- ok +-STATEMENT CREATE (t:test {prop: 356681}); +---- ok +-STATEMENT CREATE (t:test {prop: 118725}); +---- ok +-STATEMENT CREATE (t:test {prop: 95408}); +---- ok +-STATEMENT CREATE (t:test {prop: 111981}); +---- ok +-STATEMENT CREATE (t:test {prop: 896094}); +---- ok +-STATEMENT CREATE (t:test {prop: 269708}); +---- ok +-STATEMENT CREATE (t:test {prop: 457435}); +---- ok +-STATEMENT CREATE (t:test {prop: 245975}); +---- ok +-STATEMENT CREATE (t:test {prop: 186217}); +---- ok +-STATEMENT CREATE (t:test {prop: 571931}); +---- ok +-STATEMENT CREATE (t:test {prop: 714711}); +---- ok +-STATEMENT CREATE (t:test {prop: 801344}); +---- ok +-STATEMENT CREATE (t:test {prop: 183923}); +---- ok +-STATEMENT CREATE (t:test {prop: 806457}); +---- ok +-STATEMENT CREATE (t:test {prop: 922414}); +---- ok +-STATEMENT CREATE (t:test {prop: 903593}); +---- ok +-STATEMENT CREATE (t:test {prop: 4595}); +---- ok +-STATEMENT CREATE (t:test {prop: 526698}); +---- ok +-STATEMENT CREATE (t:test {prop: 580097}); +---- ok +-STATEMENT CREATE (t:test {prop: 301282}); +---- ok +-STATEMENT CREATE (t:test {prop: 671638}); +---- ok +-STATEMENT CREATE (t:test {prop: 169856}); +---- ok +-STATEMENT CREATE (t:test {prop: 359254}); +---- ok +-STATEMENT CREATE (t:test {prop: 601669}); +---- ok +-STATEMENT CREATE (t:test {prop: 202511}); +---- ok +-STATEMENT CREATE (t:test {prop: 947928}); +---- ok +-STATEMENT CREATE (t:test {prop: 942993}); +---- ok +-STATEMENT CREATE (t:test {prop: 620675}); +---- ok +-STATEMENT CREATE (t:test {prop: 755532}); +---- ok +-STATEMENT CREATE (t:test {prop: 729044}); +---- ok +-STATEMENT CREATE (t:test {prop: 128142}); +---- ok +-STATEMENT CREATE (t:test {prop: 174130}); +---- ok +-STATEMENT CREATE (t:test {prop: 329757}); +---- ok +-STATEMENT CREATE (t:test {prop: 10041}); +---- ok +-STATEMENT CREATE (t:test {prop: 358060}); +---- ok +-STATEMENT CREATE (t:test {prop: 951113}); +---- ok +-STATEMENT CREATE (t:test {prop: 498012}); +---- ok +-STATEMENT CREATE (t:test {prop: 197215}); +---- ok +-STATEMENT CREATE (t:test {prop: 469450}); +---- ok +-STATEMENT CREATE (t:test {prop: 57571}); +---- ok +-STATEMENT CREATE (t:test {prop: 623644}); +---- ok +-STATEMENT CREATE (t:test {prop: 815084}); +---- ok +-STATEMENT CREATE (t:test {prop: 502325}); +---- ok +-STATEMENT CREATE (t:test {prop: 593999}); +---- ok +-STATEMENT CREATE (t:test {prop: 140831}); +---- ok +-STATEMENT CREATE (t:test {prop: 17981}); +---- ok +-STATEMENT CREATE (t:test {prop: 901509}); +---- ok +-STATEMENT CREATE (t:test {prop: 584630}); +---- ok +-STATEMENT CREATE (t:test {prop: 309050}); +---- ok +-STATEMENT CREATE (t:test {prop: 533544}); +---- ok +-STATEMENT CREATE (t:test {prop: 186738}); +---- ok +-STATEMENT CREATE (t:test {prop: 967919}); +---- ok +-STATEMENT CREATE (t:test {prop: 546764}); +---- ok +-STATEMENT CREATE (t:test {prop: 618870}); +---- ok +-STATEMENT CREATE (t:test {prop: 110240}); +---- ok +-STATEMENT CREATE (t:test {prop: 157929}); +---- ok +-STATEMENT CREATE (t:test {prop: 521872}); +---- ok +-STATEMENT CREATE (t:test {prop: 655517}); +---- ok +-STATEMENT CREATE (t:test {prop: 839333}); +---- ok +-STATEMENT CREATE (t:test {prop: 785719}); +---- ok +-STATEMENT CREATE (t:test {prop: 326341}); +---- ok +-STATEMENT CREATE (t:test {prop: 994645}); +---- ok +-STATEMENT CREATE (t:test {prop: 605208}); +---- ok +-STATEMENT CREATE (t:test {prop: 315123}); +---- ok +-STATEMENT CREATE (t:test {prop: 49999}); +---- ok +-STATEMENT CREATE (t:test {prop: 409511}); +---- ok +-STATEMENT CREATE (t:test {prop: 175135}); +---- ok +-STATEMENT CREATE (t:test {prop: 149797}); +---- ok +-STATEMENT CREATE (t:test {prop: 393853}); +---- ok +-STATEMENT CREATE (t:test {prop: 684556}); +---- ok +-STATEMENT CREATE (t:test {prop: 683243}); +---- ok +-STATEMENT CREATE (t:test {prop: 897534}); +---- ok +-STATEMENT CREATE (t:test {prop: 9765}); +---- ok +-STATEMENT CREATE (t:test {prop: 503001}); +---- ok +-STATEMENT CREATE (t:test {prop: 453996}); +---- ok +-STATEMENT CREATE (t:test {prop: 927156}); +---- ok +-STATEMENT CREATE (t:test {prop: 426944}); +---- ok +-STATEMENT CREATE (t:test {prop: 637367}); +---- ok +-STATEMENT CREATE (t:test {prop: 596229}); +---- ok +-STATEMENT CREATE (t:test {prop: 663234}); +---- ok +-STATEMENT CREATE (t:test {prop: 894208}); +---- ok +-STATEMENT CREATE (t:test {prop: 669904}); +---- ok +-STATEMENT CREATE (t:test {prop: 17091}); +---- ok +-STATEMENT CREATE (t:test {prop: 31952}); +---- ok +-STATEMENT CREATE (t:test {prop: 905112}); +---- ok +-STATEMENT CREATE (t:test {prop: 971447}); +---- ok +-STATEMENT CREATE (t:test {prop: 886938}); +---- ok +-STATEMENT CREATE (t:test {prop: 611491}); +---- ok +-STATEMENT CREATE (t:test {prop: 172707}); +---- ok +-STATEMENT CREATE (t:test {prop: 731524}); +---- ok +-STATEMENT CREATE (t:test {prop: 810152}); +---- ok +-STATEMENT CREATE (t:test {prop: 289276}); +---- ok +-STATEMENT CREATE (t:test {prop: 425387}); +---- ok +-STATEMENT CREATE (t:test {prop: 201222}); +---- ok +-STATEMENT CREATE (t:test {prop: 620372}); +---- ok +-STATEMENT CREATE (t:test {prop: 535703}); +---- ok +-STATEMENT CREATE (t:test {prop: 627301}); +---- ok +-STATEMENT CREATE (t:test {prop: 745871}); +---- ok +-STATEMENT CREATE (t:test {prop: 507585}); +---- ok +-STATEMENT CREATE (t:test {prop: 399113}); +---- ok +-STATEMENT CREATE (t:test {prop: 248901}); +---- ok +-STATEMENT CREATE (t:test {prop: 357781}); +---- ok +-STATEMENT CREATE (t:test {prop: 566339}); +---- ok +-STATEMENT CREATE (t:test {prop: 235124}); +---- ok +-STATEMENT CREATE (t:test {prop: 377113}); +---- ok +-STATEMENT CREATE (t:test {prop: 602334}); +---- ok +-STATEMENT CREATE (t:test {prop: 890956}); +---- ok +-STATEMENT CREATE (t:test {prop: 611503}); +---- ok +-STATEMENT CREATE (t:test {prop: 37942}); +---- ok +-STATEMENT CREATE (t:test {prop: 910010}); +---- ok +-STATEMENT CREATE (t:test {prop: 598404}); +---- ok +-STATEMENT CREATE (t:test {prop: 874913}); +---- ok +-STATEMENT CREATE (t:test {prop: 8490}); +---- ok +-STATEMENT CREATE (t:test {prop: 839358}); +---- ok +-STATEMENT CREATE (t:test {prop: 153826}); +---- ok +-STATEMENT CREATE (t:test {prop: 13718}); +---- ok +-STATEMENT CREATE (t:test {prop: 138180}); +---- ok +-STATEMENT CREATE (t:test {prop: 214420}); +---- ok +-STATEMENT CREATE (t:test {prop: 285185}); +---- ok +-STATEMENT CREATE (t:test {prop: 255883}); +---- ok +-STATEMENT CREATE (t:test {prop: 778294}); +---- ok +-STATEMENT CREATE (t:test {prop: 79073}); +---- ok +-STATEMENT CREATE (t:test {prop: 513049}); +---- ok +-STATEMENT CREATE (t:test {prop: 433049}); +---- ok +-STATEMENT CREATE (t:test {prop: 765764}); +---- ok +-STATEMENT CREATE (t:test {prop: 62691}); +---- ok +-STATEMENT CREATE (t:test {prop: 882136}); +---- ok +-STATEMENT CREATE (t:test {prop: 474931}); +---- ok +-STATEMENT CREATE (t:test {prop: 387638}); +---- ok +-STATEMENT CREATE (t:test {prop: 732565}); +---- ok +-STATEMENT CREATE (t:test {prop: 3616}); +---- ok +-STATEMENT CREATE (t:test {prop: 656768}); +---- ok +-STATEMENT CREATE (t:test {prop: 223559}); +---- ok +-STATEMENT CREATE (t:test {prop: 185574}); +---- ok +-STATEMENT CREATE (t:test {prop: 646922}); +---- ok +-STATEMENT CREATE (t:test {prop: 600815}); +---- ok +-STATEMENT CREATE (t:test {prop: 854409}); +---- ok +-STATEMENT CREATE (t:test {prop: 214025}); +---- ok +-STATEMENT CREATE (t:test {prop: 725080}); +---- ok +-STATEMENT CREATE (t:test {prop: 791015}); +---- ok +-STATEMENT CREATE (t:test {prop: 365263}); +---- ok +-STATEMENT CREATE (t:test {prop: 30373}); +---- ok +-STATEMENT CREATE (t:test {prop: 310155}); +---- ok +-STATEMENT CREATE (t:test {prop: 162278}); +---- ok +-STATEMENT CREATE (t:test {prop: 913412}); +---- ok +-STATEMENT CREATE (t:test {prop: 543589}); +---- ok +-STATEMENT CREATE (t:test {prop: 823788}); +---- ok +-STATEMENT CREATE (t:test {prop: 633926}); +---- ok +-STATEMENT CREATE (t:test {prop: 961874}); +---- ok +-STATEMENT CREATE (t:test {prop: 513017}); +---- ok +-STATEMENT CREATE (t:test {prop: 402675}); +---- ok +-STATEMENT CREATE (t:test {prop: 93589}); +---- ok +-STATEMENT CREATE (t:test {prop: 852241}); +---- ok +-STATEMENT CREATE (t:test {prop: 131680}); +---- ok +-STATEMENT CREATE (t:test {prop: 495222}); +---- ok +-STATEMENT CREATE (t:test {prop: 81250}); +---- ok +-STATEMENT CREATE (t:test {prop: 316777}); +---- ok +-STATEMENT CREATE (t:test {prop: 696670}); +---- ok +-STATEMENT CREATE (t:test {prop: 998946}); +---- ok +-STATEMENT CREATE (t:test {prop: 192247}); +---- ok +-STATEMENT CREATE (t:test {prop: 519821}); +---- ok +-STATEMENT CREATE (t:test {prop: 812512}); +---- ok +-STATEMENT CREATE (t:test {prop: 741699}); +---- ok +-STATEMENT CREATE (t:test {prop: 498348}); +---- ok +-STATEMENT CREATE (t:test {prop: 306571}); +---- ok +-STATEMENT CREATE (t:test {prop: 794850}); +---- ok +-STATEMENT CREATE (t:test {prop: 927615}); +---- ok +-STATEMENT CREATE (t:test {prop: 57438}); +---- ok +-STATEMENT CREATE (t:test {prop: 499785}); +---- ok +-STATEMENT CREATE (t:test {prop: 308421}); +---- ok +-STATEMENT CREATE (t:test {prop: 49125}); +---- ok +-STATEMENT CREATE (t:test {prop: 377373}); +---- ok +-STATEMENT CREATE (t:test {prop: 70566}); +---- ok +-STATEMENT CREATE (t:test {prop: 81980}); +---- ok +-STATEMENT CREATE (t:test {prop: 369854}); +---- ok +-STATEMENT CREATE (t:test {prop: 552688}); +---- ok +-STATEMENT CREATE (t:test {prop: 448395}); +---- ok +-STATEMENT CREATE (t:test {prop: 40413}); +---- ok +-STATEMENT CREATE (t:test {prop: 116647}); +---- ok +-STATEMENT CREATE (t:test {prop: 995933}); +---- ok +-STATEMENT CREATE (t:test {prop: 890156}); +---- ok +-STATEMENT CREATE (t:test {prop: 713089}); +---- ok +-STATEMENT CREATE (t:test {prop: 583783}); +---- ok +-STATEMENT CREATE (t:test {prop: 993943}); +---- ok +-STATEMENT CREATE (t:test {prop: 961562}); +---- ok +-STATEMENT CREATE (t:test {prop: 682542}); +---- ok +-STATEMENT CREATE (t:test {prop: 985910}); +---- ok +-STATEMENT CREATE (t:test {prop: 837787}); +---- ok +-STATEMENT CREATE (t:test {prop: 923797}); +---- ok +-STATEMENT CREATE (t:test {prop: 178722}); +---- ok +-STATEMENT CREATE (t:test {prop: 134641}); +---- ok +-STATEMENT CREATE (t:test {prop: 46194}); +---- ok +-STATEMENT CREATE (t:test {prop: 833065}); +---- ok +-STATEMENT CREATE (t:test {prop: 239234}); +---- ok +-STATEMENT CREATE (t:test {prop: 704070}); +---- ok +-STATEMENT CREATE (t:test {prop: 439550}); +---- ok +-STATEMENT CREATE (t:test {prop: 929421}); +---- ok +-STATEMENT CREATE (t:test {prop: 52519}); +---- ok +-STATEMENT CREATE (t:test {prop: 80130}); +---- ok +-STATEMENT CREATE (t:test {prop: 972472}); +---- ok +-STATEMENT CREATE (t:test {prop: 997341}); +---- ok +-STATEMENT CREATE (t:test {prop: 313394}); +---- ok +-STATEMENT CREATE (t:test {prop: 913185}); +---- ok +-STATEMENT CREATE (t:test {prop: 830972}); +---- ok +-STATEMENT CREATE (t:test {prop: 982418}); +---- ok +-STATEMENT CREATE (t:test {prop: 48095}); +---- ok +-STATEMENT CREATE (t:test {prop: 434124}); +---- ok +-STATEMENT CREATE (t:test {prop: 891085}); +---- ok +-STATEMENT CREATE (t:test {prop: 386904}); +---- ok +-STATEMENT CREATE (t:test {prop: 349450}); +---- ok +-STATEMENT CREATE (t:test {prop: 972043}); +---- ok +-STATEMENT CREATE (t:test {prop: 539754}); +---- ok +-STATEMENT CREATE (t:test {prop: 638256}); +---- ok +-STATEMENT CREATE (t:test {prop: 639078}); +---- ok +-STATEMENT CREATE (t:test {prop: 939949}); +---- ok +-STATEMENT CREATE (t:test {prop: 640459}); +---- ok +-STATEMENT CREATE (t:test {prop: 310512}); +---- ok +-STATEMENT CREATE (t:test {prop: 405253}); +---- ok +-STATEMENT CREATE (t:test {prop: 266332}); +---- ok +-STATEMENT CREATE (t:test {prop: 964225}); +---- ok +-STATEMENT CREATE (t:test {prop: 406979}); +---- ok +-STATEMENT CREATE (t:test {prop: 16342}); +---- ok +-STATEMENT CREATE (t:test {prop: 583170}); +---- ok +-STATEMENT CREATE (t:test {prop: 568091}); +---- ok +-STATEMENT CREATE (t:test {prop: 584}); +---- ok +-STATEMENT CREATE (t:test {prop: 488385}); +---- ok +-STATEMENT CREATE (t:test {prop: 238173}); +---- ok +-STATEMENT CREATE (t:test {prop: 583220}); +---- ok +-STATEMENT CREATE (t:test {prop: 73388}); +---- ok +-STATEMENT CREATE (t:test {prop: 394683}); +---- ok +-STATEMENT CREATE (t:test {prop: 873495}); +---- ok +-STATEMENT CREATE (t:test {prop: 566971}); +---- ok +-STATEMENT CREATE (t:test {prop: 734545}); +---- ok +-STATEMENT CREATE (t:test {prop: 372533}); +---- ok +-STATEMENT CREATE (t:test {prop: 871725}); +---- ok +-STATEMENT CREATE (t:test {prop: 281166}); +---- ok +-STATEMENT CREATE (t:test {prop: 702089}); +---- ok +-STATEMENT CREATE (t:test {prop: 572581}); +---- ok +-STATEMENT CREATE (t:test {prop: 36926}); +---- ok +-STATEMENT CREATE (t:test {prop: 51701}); +---- ok +-STATEMENT CREATE (t:test {prop: 343199}); +---- ok +-STATEMENT CREATE (t:test {prop: 611646}); +---- ok +-STATEMENT CREATE (t:test {prop: 924791}); +---- ok +-STATEMENT CREATE (t:test {prop: 694839}); +---- ok +-STATEMENT CREATE (t:test {prop: 489226}); +---- ok +-STATEMENT CREATE (t:test {prop: 325635}); +---- ok +-STATEMENT CREATE (t:test {prop: 337556}); +---- ok +-STATEMENT CREATE (t:test {prop: 178427}); +---- ok +-STATEMENT CREATE (t:test {prop: 165736}); +---- ok +-STATEMENT CREATE (t:test {prop: 361392}); +---- ok +-STATEMENT CREATE (t:test {prop: 957223}); +---- ok +-STATEMENT CREATE (t:test {prop: 518924}); +---- ok +-STATEMENT CREATE (t:test {prop: 98441}); +---- ok +-STATEMENT CREATE (t:test {prop: 778340}); +---- ok +-STATEMENT CREATE (t:test {prop: 378403}); +---- ok +-STATEMENT CREATE (t:test {prop: 232298}); +---- ok +-STATEMENT CREATE (t:test {prop: 331424}); +---- ok +-STATEMENT CREATE (t:test {prop: 54986}); +---- ok +-STATEMENT CREATE (t:test {prop: 668227}); +---- ok +-STATEMENT CREATE (t:test {prop: 320266}); +---- ok +-STATEMENT CREATE (t:test {prop: 955726}); +---- ok +-STATEMENT CREATE (t:test {prop: 946388}); +---- ok +-STATEMENT CREATE (t:test {prop: 775833}); +---- ok +-STATEMENT CREATE (t:test {prop: 7613}); +---- ok +-STATEMENT CREATE (t:test {prop: 539942}); +---- ok +-STATEMENT CREATE (t:test {prop: 298718}); +---- ok +-STATEMENT CREATE (t:test {prop: 118761}); +---- ok +-STATEMENT CREATE (t:test {prop: 782211}); +---- ok +-STATEMENT CREATE (t:test {prop: 786234}); +---- ok +-STATEMENT CREATE (t:test {prop: 747496}); +---- ok +-STATEMENT CREATE (t:test {prop: 380186}); +---- ok +-STATEMENT CREATE (t:test {prop: 55746}); +---- ok +-STATEMENT CREATE (t:test {prop: 138962}); +---- ok +-STATEMENT CREATE (t:test {prop: 601743}); +---- ok +-STATEMENT CREATE (t:test {prop: 919965}); +---- ok +-STATEMENT CREATE (t:test {prop: 905344}); +---- ok +-STATEMENT CREATE (t:test {prop: 31758}); +---- ok +-STATEMENT CREATE (t:test {prop: 286142}); +---- ok +-STATEMENT CREATE (t:test {prop: 238405}); +---- ok +-STATEMENT CREATE (t:test {prop: 370953}); +---- ok +-STATEMENT CREATE (t:test {prop: 561649}); +---- ok +-STATEMENT CREATE (t:test {prop: 19175}); +---- ok +-STATEMENT CREATE (t:test {prop: 637555}); +---- ok +-STATEMENT CREATE (t:test {prop: 313446}); +---- ok +-STATEMENT CREATE (t:test {prop: 570975}); +---- ok +-STATEMENT CREATE (t:test {prop: 973593}); +---- ok +-STATEMENT CREATE (t:test {prop: 926038}); +---- ok +-STATEMENT CREATE (t:test {prop: 714412}); +---- ok +-STATEMENT CREATE (t:test {prop: 397669}); +---- ok +-STATEMENT CREATE (t:test {prop: 973443}); +---- ok +-STATEMENT CREATE (t:test {prop: 690423}); +---- ok +-STATEMENT CREATE (t:test {prop: 749326}); +---- ok +-STATEMENT CREATE (t:test {prop: 571212}); +---- ok +-STATEMENT CREATE (t:test {prop: 666623}); +---- ok +-STATEMENT CREATE (t:test {prop: 861278}); +---- ok +-STATEMENT CREATE (t:test {prop: 912378}); +---- ok +-STATEMENT CREATE (t:test {prop: 409874}); +---- ok +-STATEMENT CREATE (t:test {prop: 655110}); +---- ok +-STATEMENT CREATE (t:test {prop: 963570}); +---- ok +-STATEMENT CREATE (t:test {prop: 469716}); +---- ok +-STATEMENT CREATE (t:test {prop: 888590}); +---- ok +-STATEMENT CREATE (t:test {prop: 333049}); +---- ok +-STATEMENT CREATE (t:test {prop: 758231}); +---- ok +-STATEMENT CREATE (t:test {prop: 8164}); +---- ok +-STATEMENT CREATE (t:test {prop: 960330}); +---- ok +-STATEMENT CREATE (t:test {prop: 899151}); +---- ok +-STATEMENT CREATE (t:test {prop: 695132}); +---- ok +-STATEMENT CREATE (t:test {prop: 134528}); +---- ok +-STATEMENT CREATE (t:test {prop: 308070}); +---- ok +-STATEMENT CREATE (t:test {prop: 199910}); +---- ok +-STATEMENT CREATE (t:test {prop: 368935}); +---- ok +-STATEMENT CREATE (t:test {prop: 363607}); +---- ok +-STATEMENT CREATE (t:test {prop: 657531}); +---- ok +-STATEMENT CREATE (t:test {prop: 854267}); +---- ok +-STATEMENT CREATE (t:test {prop: 524681}); +---- ok +-STATEMENT CREATE (t:test {prop: 935009}); +---- ok +-STATEMENT CREATE (t:test {prop: 297792}); +---- ok +-STATEMENT CREATE (t:test {prop: 434499}); +---- ok +-STATEMENT CREATE (t:test {prop: 729475}); +---- ok +-STATEMENT CREATE (t:test {prop: 978190}); +---- ok +-STATEMENT CREATE (t:test {prop: 100767}); +---- ok +-STATEMENT CREATE (t:test {prop: 472558}); +---- ok +-STATEMENT CREATE (t:test {prop: 149768}); +---- ok +-STATEMENT CREATE (t:test {prop: 236322}); +---- ok +-STATEMENT CREATE (t:test {prop: 401270}); +---- ok +-STATEMENT CREATE (t:test {prop: 561641}); +---- ok +-STATEMENT CREATE (t:test {prop: 346049}); +---- ok +-STATEMENT CREATE (t:test {prop: 706119}); +---- ok +-STATEMENT CREATE (t:test {prop: 709963}); +---- ok +-STATEMENT CREATE (t:test {prop: 314976}); +---- ok +-STATEMENT CREATE (t:test {prop: 259960}); +---- ok +-STATEMENT CREATE (t:test {prop: 615457}); +---- ok +-STATEMENT CREATE (t:test {prop: 718048}); +---- ok +-STATEMENT CREATE (t:test {prop: 458248}); +---- ok +-STATEMENT CREATE (t:test {prop: 22396}); +---- ok +-STATEMENT CREATE (t:test {prop: 851869}); +---- ok +-STATEMENT CREATE (t:test {prop: 68049}); +---- ok +-STATEMENT CREATE (t:test {prop: 241545}); +---- ok +-STATEMENT CREATE (t:test {prop: 398312}); +---- ok +-STATEMENT CREATE (t:test {prop: 806512}); +---- ok +-STATEMENT CREATE (t:test {prop: 734707}); +---- ok +-STATEMENT CREATE (t:test {prop: 220421}); +---- ok +-STATEMENT CREATE (t:test {prop: 165995}); +---- ok +-STATEMENT CREATE (t:test {prop: 52046}); +---- ok +-STATEMENT CREATE (t:test {prop: 88450}); +---- ok +-STATEMENT CREATE (t:test {prop: 380633}); +---- ok +-STATEMENT CREATE (t:test {prop: 390544}); +---- ok +-STATEMENT CREATE (t:test {prop: 113036}); +---- ok +-STATEMENT CREATE (t:test {prop: 704711}); +---- ok +-STATEMENT CREATE (t:test {prop: 195759}); +---- ok +-STATEMENT CREATE (t:test {prop: 774361}); +---- ok +-STATEMENT CREATE (t:test {prop: 965267}); +---- ok +-STATEMENT CREATE (t:test {prop: 692022}); +---- ok +-STATEMENT CREATE (t:test {prop: 886214}); +---- ok +-STATEMENT CREATE (t:test {prop: 628584}); +---- ok +-STATEMENT CREATE (t:test {prop: 694247}); +---- ok +-STATEMENT CREATE (t:test {prop: 971643}); +---- ok +-STATEMENT CREATE (t:test {prop: 61460}); +---- ok +-STATEMENT CREATE (t:test {prop: 673316}); +---- ok +-STATEMENT CREATE (t:test {prop: 81123}); +---- ok +-STATEMENT CREATE (t:test {prop: 24109}); +---- ok +-STATEMENT CREATE (t:test {prop: 432856}); +---- ok +-STATEMENT CREATE (t:test {prop: 246243}); +---- ok +-STATEMENT CREATE (t:test {prop: 737118}); +---- ok +-STATEMENT CREATE (t:test {prop: 70810}); +---- ok +-STATEMENT CREATE (t:test {prop: 585675}); +---- ok +-STATEMENT CREATE (t:test {prop: 703403}); +---- ok +-STATEMENT CREATE (t:test {prop: 455192}); +---- ok +-STATEMENT CREATE (t:test {prop: 858990}); +---- ok +-STATEMENT CREATE (t:test {prop: 520592}); +---- ok +-STATEMENT CREATE (t:test {prop: 274024}); +---- ok +-STATEMENT CREATE (t:test {prop: 117671}); +---- ok +-STATEMENT CREATE (t:test {prop: 17869}); +---- ok +-STATEMENT CREATE (t:test {prop: 568682}); +---- ok +-STATEMENT CREATE (t:test {prop: 106989}); +---- ok +-STATEMENT CREATE (t:test {prop: 890788}); +---- ok +-STATEMENT CREATE (t:test {prop: 842671}); +---- ok +-STATEMENT CREATE (t:test {prop: 206257}); +---- ok +-STATEMENT CREATE (t:test {prop: 597391}); +---- ok +-STATEMENT CREATE (t:test {prop: 834976}); +---- ok +-STATEMENT CREATE (t:test {prop: 653786}); +---- ok +-STATEMENT CREATE (t:test {prop: 661416}); +---- ok +-STATEMENT CREATE (t:test {prop: 894227}); +---- ok +-STATEMENT CREATE (t:test {prop: 81849}); +---- ok +-STATEMENT CREATE (t:test {prop: 875575}); +---- ok +-STATEMENT CREATE (t:test {prop: 801179}); +---- ok +-STATEMENT CREATE (t:test {prop: 959309}); +---- ok +-STATEMENT CREATE (t:test {prop: 801259}); +---- ok +-STATEMENT CREATE (t:test {prop: 396329}); +---- ok +-STATEMENT CREATE (t:test {prop: 677529}); +---- ok +-STATEMENT CREATE (t:test {prop: 278510}); +---- ok +-STATEMENT CREATE (t:test {prop: 78592}); +---- ok +-STATEMENT CREATE (t:test {prop: 341944}); +---- ok +-STATEMENT CREATE (t:test {prop: 632007}); +---- ok +-STATEMENT CREATE (t:test {prop: 118874}); +---- ok +-STATEMENT CREATE (t:test {prop: 313602}); +---- ok +-STATEMENT CREATE (t:test {prop: 748787}); +---- ok +-STATEMENT CREATE (t:test {prop: 245000}); +---- ok +-STATEMENT CREATE (t:test {prop: 252371}); +---- ok +-STATEMENT CREATE (t:test {prop: 470680}); +---- ok +-STATEMENT CREATE (t:test {prop: 878392}); +---- ok +-STATEMENT CREATE (t:test {prop: 134742}); +---- ok +-STATEMENT CREATE (t:test {prop: 505880}); +---- ok +-STATEMENT CREATE (t:test {prop: 691742}); +---- ok +-STATEMENT CREATE (t:test {prop: 820164}); +---- ok +-STATEMENT CREATE (t:test {prop: 339822}); +---- ok +-STATEMENT CREATE (t:test {prop: 792990}); +---- ok +-STATEMENT CREATE (t:test {prop: 308114}); +---- ok +-STATEMENT CREATE (t:test {prop: 211005}); +---- ok +-STATEMENT CREATE (t:test {prop: 453665}); +---- ok +-STATEMENT CREATE (t:test {prop: 56651}); +---- ok +-STATEMENT CREATE (t:test {prop: 455436}); +---- ok +-STATEMENT CREATE (t:test {prop: 132777}); +---- ok +-STATEMENT CREATE (t:test {prop: 456126}); +---- ok +-STATEMENT CREATE (t:test {prop: 266249}); +---- ok +-STATEMENT CREATE (t:test {prop: 149209}); +---- ok +-STATEMENT CREATE (t:test {prop: 789666}); +---- ok +-STATEMENT CREATE (t:test {prop: 382291}); +---- ok +-STATEMENT CREATE (t:test {prop: 939213}); +---- ok +-STATEMENT CREATE (t:test {prop: 147666}); +---- ok +-STATEMENT CREATE (t:test {prop: 592853}); +---- ok +-STATEMENT CREATE (t:test {prop: 756654}); +---- ok +-STATEMENT CREATE (t:test {prop: 817509}); +---- ok +-STATEMENT CREATE (t:test {prop: 849709}); +---- ok +-STATEMENT CREATE (t:test {prop: 846569}); +---- ok +-STATEMENT CREATE (t:test {prop: 299750}); +---- ok +-STATEMENT CREATE (t:test {prop: 696668}); +---- ok +-STATEMENT CREATE (t:test {prop: 911464}); +---- ok +-STATEMENT CREATE (t:test {prop: 597045}); +---- ok +-STATEMENT CREATE (t:test {prop: 668200}); +---- ok +-STATEMENT CREATE (t:test {prop: 666250}); +---- ok +-STATEMENT CREATE (t:test {prop: 535323}); +---- ok +-STATEMENT CREATE (t:test {prop: 579957}); +---- ok +-STATEMENT CREATE (t:test {prop: 424432}); +---- ok +-STATEMENT CREATE (t:test {prop: 927505}); +---- ok +-STATEMENT CREATE (t:test {prop: 214294}); +---- ok +-STATEMENT CREATE (t:test {prop: 515859}); +---- ok +-STATEMENT CREATE (t:test {prop: 423337}); +---- ok +-STATEMENT CREATE (t:test {prop: 744195}); +---- ok +-STATEMENT CREATE (t:test {prop: 101350}); +---- ok +-STATEMENT CREATE (t:test {prop: 271903}); +---- ok +-STATEMENT CREATE (t:test {prop: 52208}); +---- ok +-STATEMENT CREATE (t:test {prop: 167651}); +---- ok +-STATEMENT CREATE (t:test {prop: 412582}); +---- ok +-STATEMENT CREATE (t:test {prop: 565406}); +---- ok +-STATEMENT CREATE (t:test {prop: 713311}); +---- ok +-STATEMENT CREATE (t:test {prop: 864868}); +---- ok +-STATEMENT CREATE (t:test {prop: 104222}); +---- ok +-STATEMENT CREATE (t:test {prop: 151373}); +---- ok +-STATEMENT CREATE (t:test {prop: 542842}); +---- ok +-STATEMENT CREATE (t:test {prop: 760485}); +---- ok +-STATEMENT CREATE (t:test {prop: 234804}); +---- ok +-STATEMENT CREATE (t:test {prop: 287215}); +---- ok +-STATEMENT CREATE (t:test {prop: 232822}); +---- ok +-STATEMENT CREATE (t:test {prop: 116867}); +---- ok +-STATEMENT CREATE (t:test {prop: 63511}); +---- ok +-STATEMENT CREATE (t:test {prop: 849138}); +---- ok +-STATEMENT CREATE (t:test {prop: 830108}); +---- ok +-STATEMENT CREATE (t:test {prop: 60836}); +---- ok +-STATEMENT CREATE (t:test {prop: 728996}); +---- ok +-STATEMENT CREATE (t:test {prop: 440050}); +---- ok +-STATEMENT CREATE (t:test {prop: 418068}); +---- ok +-STATEMENT CREATE (t:test {prop: 687577}); +---- ok +-STATEMENT CREATE (t:test {prop: 524487}); +---- ok +-STATEMENT CREATE (t:test {prop: 736585}); +---- ok +-STATEMENT CREATE (t:test {prop: 33284}); +---- ok +-STATEMENT CREATE (t:test {prop: 803154}); +---- ok +-STATEMENT CREATE (t:test {prop: 758851}); +---- ok +-STATEMENT CREATE (t:test {prop: 104293}); +---- ok +-STATEMENT CREATE (t:test {prop: 958246}); +---- ok +-STATEMENT CREATE (t:test {prop: 137366}); +---- ok +-STATEMENT CREATE (t:test {prop: 444713}); +---- ok +-STATEMENT CREATE (t:test {prop: 321056}); +---- ok +-STATEMENT CREATE (t:test {prop: 51353}); +---- ok +-STATEMENT CREATE (t:test {prop: 883796}); +---- ok +-STATEMENT CREATE (t:test {prop: 232872}); +---- ok +-STATEMENT CREATE (t:test {prop: 938950}); +---- ok +-STATEMENT CREATE (t:test {prop: 442698}); +---- ok +-STATEMENT CREATE (t:test {prop: 328959}); +---- ok +-STATEMENT CREATE (t:test {prop: 295499}); +---- ok +-STATEMENT CREATE (t:test {prop: 459185}); +---- ok +-STATEMENT CREATE (t:test {prop: 644506}); +---- ok +-STATEMENT CREATE (t:test {prop: 565884}); +---- ok +-STATEMENT CREATE (t:test {prop: 450620}); +---- ok +-STATEMENT CREATE (t:test {prop: 861936}); +---- ok +-STATEMENT CREATE (t:test {prop: 20784}); +---- ok +-STATEMENT CREATE (t:test {prop: 999927}); +---- ok +-STATEMENT CREATE (t:test {prop: 637632}); +---- ok +-STATEMENT CREATE (t:test {prop: 227816}); +---- ok +-STATEMENT CREATE (t:test {prop: 973480}); +---- ok +-STATEMENT CREATE (t:test {prop: 170377}); +---- ok +-STATEMENT CREATE (t:test {prop: 698400}); +---- ok +-STATEMENT CREATE (t:test {prop: 879865}); +---- ok +-STATEMENT CREATE (t:test {prop: 759826}); +---- ok +-STATEMENT CREATE (t:test {prop: 217173}); +---- ok +-STATEMENT CREATE (t:test {prop: 74706}); +---- ok +-STATEMENT CREATE (t:test {prop: 34273}); +---- ok +-STATEMENT CREATE (t:test {prop: 643114}); +---- ok +-STATEMENT CREATE (t:test {prop: 151389}); +---- ok +-STATEMENT CREATE (t:test {prop: 986537}); +---- ok +-STATEMENT CREATE (t:test {prop: 638023}); +---- ok +-STATEMENT CREATE (t:test {prop: 284989}); +---- ok +-STATEMENT CREATE (t:test {prop: 789415}); +---- ok +-STATEMENT CREATE (t:test {prop: 336181}); +---- ok +-STATEMENT CREATE (t:test {prop: 983796}); +---- ok +-STATEMENT CREATE (t:test {prop: 262336}); +---- ok +-STATEMENT CREATE (t:test {prop: 548881}); +---- ok +-STATEMENT CREATE (t:test {prop: 627065}); +---- ok +-STATEMENT CREATE (t:test {prop: 979349}); +---- ok +-STATEMENT CREATE (t:test {prop: 361346}); +---- ok +-STATEMENT CREATE (t:test {prop: 687908}); +---- ok +-STATEMENT CREATE (t:test {prop: 890030}); +---- ok +-STATEMENT CREATE (t:test {prop: 52075}); +---- ok +-STATEMENT CREATE (t:test {prop: 709159}); +---- ok +-STATEMENT CREATE (t:test {prop: 797789}); +---- ok +-STATEMENT CREATE (t:test {prop: 571475}); +---- ok +-STATEMENT CREATE (t:test {prop: 146078}); +---- ok +-STATEMENT CREATE (t:test {prop: 798333}); +---- ok +-STATEMENT CREATE (t:test {prop: 604517}); +---- ok +-STATEMENT CREATE (t:test {prop: 218009}); +---- ok +-STATEMENT CREATE (t:test {prop: 413747}); +---- ok +-STATEMENT CREATE (t:test {prop: 262903}); +---- ok +-STATEMENT CREATE (t:test {prop: 509650}); +---- ok +-STATEMENT CREATE (t:test {prop: 444159}); +---- ok +-STATEMENT CREATE (t:test {prop: 598903}); +---- ok +-STATEMENT CREATE (t:test {prop: 413005}); +---- ok +-STATEMENT CREATE (t:test {prop: 707931}); +---- ok +-STATEMENT CREATE (t:test {prop: 461035}); +---- ok +-STATEMENT CREATE (t:test {prop: 374916}); +---- ok +-STATEMENT CREATE (t:test {prop: 434901}); +---- ok +-STATEMENT CREATE (t:test {prop: 339716}); +---- ok +-STATEMENT CREATE (t:test {prop: 889771}); +---- ok +-STATEMENT CREATE (t:test {prop: 588581}); +---- ok +-STATEMENT CREATE (t:test {prop: 874177}); +---- ok +-STATEMENT CREATE (t:test {prop: 237661}); +---- ok +-STATEMENT CREATE (t:test {prop: 332360}); +---- ok +-STATEMENT CREATE (t:test {prop: 563557}); +---- ok +-STATEMENT CREATE (t:test {prop: 412080}); +---- ok +-STATEMENT CREATE (t:test {prop: 43157}); +---- ok +-STATEMENT CREATE (t:test {prop: 23728}); +---- ok +-STATEMENT CREATE (t:test {prop: 792415}); +---- ok +-STATEMENT CREATE (t:test {prop: 728802}); +---- ok +-STATEMENT CREATE (t:test {prop: 508293}); +---- ok +-STATEMENT CREATE (t:test {prop: 487228}); +---- ok +-STATEMENT CREATE (t:test {prop: 177703}); +---- ok +-STATEMENT CREATE (t:test {prop: 943468}); +---- ok +-STATEMENT CREATE (t:test {prop: 946570}); +---- ok +-STATEMENT CREATE (t:test {prop: 38995}); +---- ok +-STATEMENT CREATE (t:test {prop: 470447}); +---- ok +-STATEMENT CREATE (t:test {prop: 791063}); +---- ok +-STATEMENT CREATE (t:test {prop: 253561}); +---- ok +-STATEMENT CREATE (t:test {prop: 35550}); +---- ok +-STATEMENT CREATE (t:test {prop: 498688}); +---- ok +-STATEMENT CREATE (t:test {prop: 621163}); +---- ok +-STATEMENT CREATE (t:test {prop: 178719}); +---- ok +-STATEMENT CREATE (t:test {prop: 80042}); +---- ok +-STATEMENT CREATE (t:test {prop: 252395}); +---- ok +-STATEMENT CREATE (t:test {prop: 735569}); +---- ok +-STATEMENT CREATE (t:test {prop: 676962}); +---- ok +-STATEMENT CREATE (t:test {prop: 742850}); +---- ok +-STATEMENT CREATE (t:test {prop: 688027}); +---- ok +-STATEMENT CREATE (t:test {prop: 995311}); +---- ok +-STATEMENT CREATE (t:test {prop: 110358}); +---- ok +-STATEMENT CREATE (t:test {prop: 568433}); +---- ok +-STATEMENT CREATE (t:test {prop: 771833}); +---- ok +-STATEMENT CREATE (t:test {prop: 677897}); +---- ok +-STATEMENT CREATE (t:test {prop: 809336}); +---- ok +-STATEMENT CREATE (t:test {prop: 166834}); +---- ok +-STATEMENT CREATE (t:test {prop: 563619}); +---- ok +-STATEMENT CREATE (t:test {prop: 223780}); +---- ok +-STATEMENT CREATE (t:test {prop: 638420}); +---- ok +-STATEMENT CREATE (t:test {prop: 389455}); +---- ok +-STATEMENT CREATE (t:test {prop: 640148}); +---- ok +-STATEMENT CREATE (t:test {prop: 861486}); +---- ok +-STATEMENT CREATE (t:test {prop: 813492}); +---- ok +-STATEMENT CREATE (t:test {prop: 168490}); +---- ok +-STATEMENT CREATE (t:test {prop: 747361}); +---- ok +-STATEMENT CREATE (t:test {prop: 823524}); +---- ok +-STATEMENT CREATE (t:test {prop: 50567}); +---- ok +-STATEMENT CREATE (t:test {prop: 541647}); +---- ok +-STATEMENT CREATE (t:test {prop: 491210}); +---- ok +-STATEMENT CREATE (t:test {prop: 253699}); +---- ok +-STATEMENT CREATE (t:test {prop: 148027}); +---- ok +-STATEMENT CREATE (t:test {prop: 742373}); +---- ok +-STATEMENT CREATE (t:test {prop: 704165}); +---- ok +-STATEMENT CREATE (t:test {prop: 488027}); +---- ok +-STATEMENT CREATE (t:test {prop: 673078}); +---- ok +-STATEMENT CREATE (t:test {prop: 75356}); +---- ok +-STATEMENT CREATE (t:test {prop: 808417}); +---- ok +-STATEMENT CREATE (t:test {prop: 818529}); +---- ok +-STATEMENT CREATE (t:test {prop: 678561}); +---- ok +-STATEMENT CREATE (t:test {prop: 255962}); +---- ok +-STATEMENT CREATE (t:test {prop: 519500}); +---- ok +-STATEMENT CREATE (t:test {prop: 105335}); +---- ok +-STATEMENT CREATE (t:test {prop: 60612}); +---- ok +-STATEMENT CREATE (t:test {prop: 181263}); +---- ok +-STATEMENT CREATE (t:test {prop: 681038}); +---- ok +-STATEMENT CREATE (t:test {prop: 813345}); +---- ok +-STATEMENT CREATE (t:test {prop: 708088}); +---- ok +-STATEMENT CREATE (t:test {prop: 179574}); +---- ok +-STATEMENT CREATE (t:test {prop: 140854}); +---- ok +-STATEMENT CREATE (t:test {prop: 640131}); +---- ok +-STATEMENT CREATE (t:test {prop: 246988}); +---- ok +-STATEMENT CREATE (t:test {prop: 81210}); +---- ok +-STATEMENT CREATE (t:test {prop: 486133}); +---- ok +-STATEMENT CREATE (t:test {prop: 41869}); +---- ok +-STATEMENT CREATE (t:test {prop: 122824}); +---- ok +-STATEMENT CREATE (t:test {prop: 842887}); +---- ok +-STATEMENT CREATE (t:test {prop: 98641}); +---- ok +-STATEMENT CREATE (t:test {prop: 77179}); +---- ok +-STATEMENT CREATE (t:test {prop: 856352}); +---- ok +-STATEMENT CREATE (t:test {prop: 733838}); +---- ok +-STATEMENT CREATE (t:test {prop: 803702}); +---- ok +-STATEMENT CREATE (t:test {prop: 914815}); +---- ok +-STATEMENT CREATE (t:test {prop: 888609}); +---- ok +-STATEMENT CREATE (t:test {prop: 63652}); +---- ok +-STATEMENT CREATE (t:test {prop: 105813}); +---- ok +-STATEMENT CREATE (t:test {prop: 502368}); +---- ok +-STATEMENT CREATE (t:test {prop: 875104}); +---- ok +-STATEMENT CREATE (t:test {prop: 462660}); +---- ok +-STATEMENT CREATE (t:test {prop: 81161}); +---- ok +-STATEMENT CREATE (t:test {prop: 623632}); +---- ok +-STATEMENT CREATE (t:test {prop: 628099}); +---- ok +-STATEMENT CREATE (t:test {prop: 611954}); +---- ok +-STATEMENT CREATE (t:test {prop: 220302}); +---- ok +-STATEMENT CREATE (t:test {prop: 786300}); +---- ok +-STATEMENT CREATE (t:test {prop: 801369}); +---- ok +-STATEMENT CREATE (t:test {prop: 909226}); +---- ok +-STATEMENT CREATE (t:test {prop: 810201}); +---- ok +-STATEMENT CREATE (t:test {prop: 112168}); +---- ok +-STATEMENT CREATE (t:test {prop: 210305}); +---- ok +-STATEMENT CREATE (t:test {prop: 116450}); +---- ok +-STATEMENT CREATE (t:test {prop: 997776}); +---- ok +-STATEMENT CREATE (t:test {prop: 671498}); +---- ok +-STATEMENT CREATE (t:test {prop: 604226}); +---- ok +-STATEMENT CREATE (t:test {prop: 951160}); +---- ok +-STATEMENT CREATE (t:test {prop: 914579}); +---- ok +-STATEMENT CREATE (t:test {prop: 744505}); +---- ok +-STATEMENT CREATE (t:test {prop: 688748}); +---- ok +-STATEMENT CREATE (t:test {prop: 957260}); +---- ok +-STATEMENT CREATE (t:test {prop: 391158}); +---- ok +-STATEMENT CREATE (t:test {prop: 172797}); +---- ok +-STATEMENT CREATE (t:test {prop: 556018}); +---- ok +-STATEMENT CREATE (t:test {prop: 288255}); +---- ok +-STATEMENT CREATE (t:test {prop: 332013}); +---- ok +-STATEMENT CREATE (t:test {prop: 198211}); +---- ok +-STATEMENT CREATE (t:test {prop: 525379}); +---- ok +-STATEMENT CREATE (t:test {prop: 566022}); +---- ok +-STATEMENT CREATE (t:test {prop: 218953}); +---- ok +-STATEMENT CREATE (t:test {prop: 456860}); +---- ok +-STATEMENT CREATE (t:test {prop: 209940}); +---- ok +-STATEMENT CREATE (t:test {prop: 559400}); +---- ok +-STATEMENT CREATE (t:test {prop: 467681}); +---- ok +-STATEMENT CREATE (t:test {prop: 860218}); +---- ok +-STATEMENT CREATE (t:test {prop: 489957}); +---- ok +-STATEMENT CREATE (t:test {prop: 610986}); +---- ok +-STATEMENT CREATE (t:test {prop: 572954}); +---- ok +-STATEMENT CREATE (t:test {prop: 777401}); +---- ok +-STATEMENT CREATE (t:test {prop: 314209}); +---- ok +-STATEMENT CREATE (t:test {prop: 689429}); +---- ok +-STATEMENT CREATE (t:test {prop: 468112}); +---- ok +-STATEMENT CREATE (t:test {prop: 804039}); +---- ok +-STATEMENT CREATE (t:test {prop: 576}); +---- ok +-STATEMENT CREATE (t:test {prop: 361150}); +---- ok +-STATEMENT CREATE (t:test {prop: 3055}); +---- ok +-STATEMENT CREATE (t:test {prop: 274247}); +---- ok +-STATEMENT CREATE (t:test {prop: 551742}); +---- ok +-STATEMENT CREATE (t:test {prop: 267645}); +---- ok +-STATEMENT CREATE (t:test {prop: 109923}); +---- ok +-STATEMENT CREATE (t:test {prop: 639536}); +---- ok +-STATEMENT CREATE (t:test {prop: 427435}); +---- ok +-STATEMENT CREATE (t:test {prop: 430762}); +---- ok +-STATEMENT CREATE (t:test {prop: 315618}); +---- ok +-STATEMENT CREATE (t:test {prop: 452226}); +---- ok +-STATEMENT CREATE (t:test {prop: 81036}); +---- ok +-STATEMENT CREATE (t:test {prop: 311908}); +---- ok +-STATEMENT CREATE (t:test {prop: 169304}); +---- ok +-STATEMENT CREATE (t:test {prop: 904664}); +---- ok +-STATEMENT CREATE (t:test {prop: 809126}); +---- ok +-STATEMENT CREATE (t:test {prop: 360720}); +---- ok +-STATEMENT CREATE (t:test {prop: 147728}); +---- ok +-STATEMENT CREATE (t:test {prop: 906807}); +---- ok +-STATEMENT CREATE (t:test {prop: 118314}); +---- ok +-STATEMENT CREATE (t:test {prop: 69278}); +---- ok +-STATEMENT CREATE (t:test {prop: 394136}); +---- ok +-STATEMENT CREATE (t:test {prop: 663583}); +---- ok +-STATEMENT CREATE (t:test {prop: 281513}); +---- ok +-STATEMENT CREATE (t:test {prop: 193953}); +---- ok +-STATEMENT CREATE (t:test {prop: 252296}); +---- ok +-STATEMENT CREATE (t:test {prop: 969859}); +---- ok +-STATEMENT CREATE (t:test {prop: 922114}); +---- ok +-STATEMENT CREATE (t:test {prop: 46277}); +---- ok +-STATEMENT CREATE (t:test {prop: 359309}); +---- ok +-STATEMENT CREATE (t:test {prop: 872894}); +---- ok +-STATEMENT CREATE (t:test {prop: 266580}); +---- ok +-STATEMENT CREATE (t:test {prop: 804102}); +---- ok +-STATEMENT CREATE (t:test {prop: 453552}); +---- ok +-STATEMENT CREATE (t:test {prop: 417696}); +---- ok +-STATEMENT CREATE (t:test {prop: 544228}); +---- ok +-STATEMENT CREATE (t:test {prop: 67303}); +---- ok +-STATEMENT CREATE (t:test {prop: 762478}); +---- ok +-STATEMENT CREATE (t:test {prop: 741572}); +---- ok +-STATEMENT CREATE (t:test {prop: 275526}); +---- ok +-STATEMENT CREATE (t:test {prop: 760260}); +---- ok +-STATEMENT CREATE (t:test {prop: 999018}); +---- ok +-STATEMENT CREATE (t:test {prop: 829806}); +---- ok +-STATEMENT CREATE (t:test {prop: 766225}); +---- ok +-STATEMENT CREATE (t:test {prop: 711835}); +---- ok +-STATEMENT CREATE (t:test {prop: 358812}); +---- ok +-STATEMENT CREATE (t:test {prop: 861176}); +---- ok +-STATEMENT CREATE (t:test {prop: 745119}); +---- ok +-STATEMENT CREATE (t:test {prop: 416937}); +---- ok +-STATEMENT CREATE (t:test {prop: 261038}); +---- ok +-STATEMENT CREATE (t:test {prop: 679551}); +---- ok +-STATEMENT CREATE (t:test {prop: 9560}); +---- ok +-STATEMENT CREATE (t:test {prop: 947188}); +---- ok +-STATEMENT CREATE (t:test {prop: 783986}); +---- ok +-STATEMENT CREATE (t:test {prop: 306102}); +---- ok +-STATEMENT CREATE (t:test {prop: 905527}); +---- ok +-STATEMENT CREATE (t:test {prop: 237892}); +---- ok +-STATEMENT CREATE (t:test {prop: 889283}); +---- ok +-STATEMENT CREATE (t:test {prop: 318032}); +---- ok +-STATEMENT CREATE (t:test {prop: 253860}); +---- ok +-STATEMENT CREATE (t:test {prop: 18731}); +---- ok +-STATEMENT CREATE (t:test {prop: 215719}); +---- ok +-STATEMENT CREATE (t:test {prop: 882370}); +---- ok +-STATEMENT CREATE (t:test {prop: 970763}); +---- ok +-STATEMENT CREATE (t:test {prop: 183240}); +---- ok +-STATEMENT CREATE (t:test {prop: 199165}); +---- ok +-STATEMENT CREATE (t:test {prop: 8961}); +---- ok +-STATEMENT CREATE (t:test {prop: 126732}); +---- ok +-STATEMENT CREATE (t:test {prop: 274896}); +---- ok +-STATEMENT CREATE (t:test {prop: 278213}); +---- ok +-STATEMENT CREATE (t:test {prop: 492815}); +---- ok +-STATEMENT CREATE (t:test {prop: 117341}); +---- ok +-STATEMENT CREATE (t:test {prop: 946336}); +---- ok +-STATEMENT CREATE (t:test {prop: 368033}); +---- ok +-STATEMENT CREATE (t:test {prop: 986819}); +---- ok +-STATEMENT CREATE (t:test {prop: 907046}); +---- ok +-STATEMENT CREATE (t:test {prop: 851634}); +---- ok +-STATEMENT CREATE (t:test {prop: 975716}); +---- ok +-STATEMENT CREATE (t:test {prop: 86562}); +---- ok +-STATEMENT CREATE (t:test {prop: 614205}); +---- ok +-STATEMENT CREATE (t:test {prop: 688686}); +---- ok +-STATEMENT CREATE (t:test {prop: 579176}); +---- ok +-STATEMENT CREATE (t:test {prop: 739879}); +---- ok +-STATEMENT CREATE (t:test {prop: 826872}); +---- ok +-STATEMENT CREATE (t:test {prop: 422706}); +---- ok +-STATEMENT CREATE (t:test {prop: 720887}); +---- ok +-STATEMENT CREATE (t:test {prop: 339537}); +---- ok +-STATEMENT CREATE (t:test {prop: 108667}); +---- ok +-STATEMENT CREATE (t:test {prop: 416107}); +---- ok +-STATEMENT CREATE (t:test {prop: 430049}); +---- ok +-STATEMENT CREATE (t:test {prop: 445140}); +---- ok +-STATEMENT CREATE (t:test {prop: 894928}); +---- ok +-STATEMENT CREATE (t:test {prop: 800719}); +---- ok +-STATEMENT CREATE (t:test {prop: 441722}); +---- ok +-STATEMENT CREATE (t:test {prop: 619954}); +---- ok +-STATEMENT CREATE (t:test {prop: 826869}); +---- ok +-STATEMENT CREATE (t:test {prop: 742006}); +---- ok +-STATEMENT CREATE (t:test {prop: 885618}); +---- ok +-STATEMENT CREATE (t:test {prop: 809972}); +---- ok +-STATEMENT CREATE (t:test {prop: 49872}); +---- ok +-STATEMENT CREATE (t:test {prop: 762579}); +---- ok +-STATEMENT CREATE (t:test {prop: 374462}); +---- ok +-STATEMENT CREATE (t:test {prop: 349234}); +---- ok +-STATEMENT CREATE (t:test {prop: 2573}); +---- ok +-STATEMENT CREATE (t:test {prop: 526728}); +---- ok +-STATEMENT CREATE (t:test {prop: 630138}); +---- ok +-STATEMENT CREATE (t:test {prop: 877571}); +---- ok +-STATEMENT CREATE (t:test {prop: 109623}); +---- ok +-STATEMENT CREATE (t:test {prop: 456312}); +---- ok +-STATEMENT CREATE (t:test {prop: 568018}); +---- ok +-STATEMENT CREATE (t:test {prop: 602414}); +---- ok +-STATEMENT CREATE (t:test {prop: 536683}); +---- ok +-STATEMENT CREATE (t:test {prop: 52108}); +---- ok +-STATEMENT CREATE (t:test {prop: 632742}); +---- ok +-STATEMENT CREATE (t:test {prop: 458706}); +---- ok +-STATEMENT CREATE (t:test {prop: 125495}); +---- ok +-STATEMENT CREATE (t:test {prop: 524235}); +---- ok +-STATEMENT CREATE (t:test {prop: 599289}); +---- ok +-STATEMENT CREATE (t:test {prop: 165658}); +---- ok +-STATEMENT CREATE (t:test {prop: 940550}); +---- ok +-STATEMENT CREATE (t:test {prop: 405735}); +---- ok +-STATEMENT CREATE (t:test {prop: 839037}); +---- ok +-STATEMENT CREATE (t:test {prop: 80327}); +---- ok +-STATEMENT CREATE (t:test {prop: 276156}); +---- ok +-STATEMENT CREATE (t:test {prop: 119924}); +---- ok +-STATEMENT CREATE (t:test {prop: 146834}); +---- ok +-STATEMENT CREATE (t:test {prop: 733591}); +---- ok +-STATEMENT CREATE (t:test {prop: 753143}); +---- ok +-STATEMENT CREATE (t:test {prop: 699771}); +---- ok +-STATEMENT CREATE (t:test {prop: 280017}); +---- ok +-STATEMENT CREATE (t:test {prop: 367697}); +---- ok +-STATEMENT CREATE (t:test {prop: 319028}); +---- ok +-STATEMENT CREATE (t:test {prop: 902759}); +---- ok +-STATEMENT CREATE (t:test {prop: 634879}); +---- ok +-STATEMENT CREATE (t:test {prop: 557946}); +---- ok +-STATEMENT CREATE (t:test {prop: 834902}); +---- ok +-STATEMENT CREATE (t:test {prop: 254912}); +---- ok +-STATEMENT CREATE (t:test {prop: 700812}); +---- ok +-STATEMENT CREATE (t:test {prop: 99741}); +---- ok +-STATEMENT CREATE (t:test {prop: 452859}); +---- ok +-STATEMENT CREATE (t:test {prop: 447251}); +---- ok +-STATEMENT CREATE (t:test {prop: 928654}); +---- ok +-STATEMENT CREATE (t:test {prop: 351392}); +---- ok +-STATEMENT CREATE (t:test {prop: 791089}); +---- ok +-STATEMENT CREATE (t:test {prop: 223996}); +---- ok +-STATEMENT CREATE (t:test {prop: 399158}); +---- ok +-STATEMENT CREATE (t:test {prop: 970532}); +---- ok +-STATEMENT CREATE (t:test {prop: 70218}); +---- ok +-STATEMENT CREATE (t:test {prop: 646189}); +---- ok +-STATEMENT CREATE (t:test {prop: 454239}); +---- ok +-STATEMENT CREATE (t:test {prop: 123079}); +---- ok +-STATEMENT CREATE (t:test {prop: 126212}); +---- ok +-STATEMENT CREATE (t:test {prop: 487039}); +---- ok +-STATEMENT CREATE (t:test {prop: 511552}); +---- ok +-STATEMENT CREATE (t:test {prop: 342683}); +---- ok +-STATEMENT CREATE (t:test {prop: 352164}); +---- ok +-STATEMENT CREATE (t:test {prop: 830848}); +---- ok +-STATEMENT CREATE (t:test {prop: 149822}); +---- ok +-STATEMENT CREATE (t:test {prop: 601602}); +---- ok +-STATEMENT CREATE (t:test {prop: 42656}); +---- ok +-STATEMENT CREATE (t:test {prop: 17984}); +---- ok +-STATEMENT CREATE (t:test {prop: 557003}); +---- ok +-STATEMENT CREATE (t:test {prop: 724104}); +---- ok +-STATEMENT CREATE (t:test {prop: 503673}); +---- ok +-STATEMENT CREATE (t:test {prop: 671586}); +---- ok +-STATEMENT CREATE (t:test {prop: 273549}); +---- ok +-STATEMENT CREATE (t:test {prop: 955159}); +---- ok +-STATEMENT CREATE (t:test {prop: 457626}); +---- ok +-STATEMENT CREATE (t:test {prop: 770672}); +---- ok +-STATEMENT CREATE (t:test {prop: 273326}); +---- ok +-STATEMENT CREATE (t:test {prop: 155984}); +---- ok +-STATEMENT CREATE (t:test {prop: 138963}); +---- ok +-STATEMENT CREATE (t:test {prop: 411126}); +---- ok +-STATEMENT CREATE (t:test {prop: 311366}); +---- ok +-STATEMENT CREATE (t:test {prop: 825109}); +---- ok +-STATEMENT CREATE (t:test {prop: 63712}); +---- ok +-STATEMENT CREATE (t:test {prop: 887124}); +---- ok +-STATEMENT CREATE (t:test {prop: 599357}); +---- ok +-STATEMENT CREATE (t:test {prop: 384167}); +---- ok +-STATEMENT CREATE (t:test {prop: 858983}); +---- ok +-STATEMENT CREATE (t:test {prop: 870520}); +---- ok +-STATEMENT CREATE (t:test {prop: 906759}); +---- ok +-STATEMENT CREATE (t:test {prop: 600129}); +---- ok +-STATEMENT CREATE (t:test {prop: 483236}); +---- ok +-STATEMENT CREATE (t:test {prop: 570112}); +---- ok +-STATEMENT CREATE (t:test {prop: 746386}); +---- ok +-STATEMENT CREATE (t:test {prop: 391341}); +---- ok +-STATEMENT CREATE (t:test {prop: 497791}); +---- ok +-STATEMENT CREATE (t:test {prop: 16037}); +---- ok +-STATEMENT CREATE (t:test {prop: 595222}); +---- ok +-STATEMENT CREATE (t:test {prop: 310729}); +---- ok +-STATEMENT CREATE (t:test {prop: 160125}); +---- ok +-STATEMENT CREATE (t:test {prop: 532287}); +---- ok +-STATEMENT CREATE (t:test {prop: 860592}); +---- ok +-STATEMENT CREATE (t:test {prop: 889190}); +---- ok +-STATEMENT CREATE (t:test {prop: 841564}); +---- ok +-STATEMENT CREATE (t:test {prop: 697447}); +---- ok +-STATEMENT CREATE (t:test {prop: 280367}); +---- ok +-STATEMENT CREATE (t:test {prop: 184130}); +---- ok +-STATEMENT CREATE (t:test {prop: 637787}); +---- ok +-STATEMENT CREATE (t:test {prop: 213388}); +---- ok +-STATEMENT CREATE (t:test {prop: 530809}); +---- ok +-STATEMENT CREATE (t:test {prop: 828690}); +---- ok +-STATEMENT CREATE (t:test {prop: 649445}); +---- ok +-STATEMENT CREATE (t:test {prop: 138541}); +---- ok +-STATEMENT CREATE (t:test {prop: 77163}); +---- ok +-STATEMENT CREATE (t:test {prop: 206546}); +---- ok +-STATEMENT CREATE (t:test {prop: 97055}); +---- ok +-STATEMENT CREATE (t:test {prop: 491728}); +---- ok +-STATEMENT CREATE (t:test {prop: 344820}); +---- ok +-STATEMENT CREATE (t:test {prop: 337517}); +---- ok +-STATEMENT CREATE (t:test {prop: 793640}); +---- ok +-STATEMENT CREATE (t:test {prop: 460301}); +---- ok +-STATEMENT CREATE (t:test {prop: 359867}); +---- ok +-STATEMENT CREATE (t:test {prop: 128152}); +---- ok +-STATEMENT CREATE (t:test {prop: 383891}); +---- ok +-STATEMENT CREATE (t:test {prop: 738972}); +---- ok +-STATEMENT CREATE (t:test {prop: 907509}); +---- ok +-STATEMENT CREATE (t:test {prop: 168392}); +---- ok +-STATEMENT CREATE (t:test {prop: 752632}); +---- ok +-STATEMENT CREATE (t:test {prop: 100141}); +---- ok +-STATEMENT CREATE (t:test {prop: 717546}); +---- ok +-STATEMENT CREATE (t:test {prop: 565097}); +---- ok +-STATEMENT CREATE (t:test {prop: 34918}); +---- ok +-STATEMENT CREATE (t:test {prop: 866946}); +---- ok +-STATEMENT CREATE (t:test {prop: 548493}); +---- ok +-STATEMENT CREATE (t:test {prop: 692979}); +---- ok +-STATEMENT CREATE (t:test {prop: 890294}); +---- ok +-STATEMENT CREATE (t:test {prop: 764747}); +---- ok +-STATEMENT CREATE (t:test {prop: 590548}); +---- ok +-STATEMENT CREATE (t:test {prop: 272916}); +---- ok +-STATEMENT CREATE (t:test {prop: 92556}); +---- ok +-STATEMENT CREATE (t:test {prop: 381415}); +---- ok +-STATEMENT CREATE (t:test {prop: 632171}); +---- ok +-STATEMENT CREATE (t:test {prop: 629057}); +---- ok +-STATEMENT CREATE (t:test {prop: 758828}); +---- ok +-STATEMENT CREATE (t:test {prop: 321394}); +---- ok +-STATEMENT CREATE (t:test {prop: 597532}); +---- ok +-STATEMENT CREATE (t:test {prop: 384757}); +---- ok +-STATEMENT CREATE (t:test {prop: 142510}); +---- ok +-STATEMENT CREATE (t:test {prop: 809711}); +---- ok +-STATEMENT CREATE (t:test {prop: 480958}); +---- ok +-STATEMENT CREATE (t:test {prop: 88657}); +---- ok +-STATEMENT CREATE (t:test {prop: 929134}); +---- ok +-STATEMENT CREATE (t:test {prop: 677686}); +---- ok +-STATEMENT CREATE (t:test {prop: 828457}); +---- ok +-STATEMENT CREATE (t:test {prop: 309630}); +---- ok +-STATEMENT CREATE (t:test {prop: 760632}); +---- ok +-STATEMENT CREATE (t:test {prop: 277050}); +---- ok +-STATEMENT CREATE (t:test {prop: 483089}); +---- ok +-STATEMENT CREATE (t:test {prop: 850050}); +---- ok +-STATEMENT CREATE (t:test {prop: 452650}); +---- ok +-STATEMENT CREATE (t:test {prop: 862350}); +---- ok +-STATEMENT CREATE (t:test {prop: 826078}); +---- ok +-STATEMENT CREATE (t:test {prop: 69032}); +---- ok +-STATEMENT CREATE (t:test {prop: 96011}); +---- ok +-STATEMENT CREATE (t:test {prop: 539264}); +---- ok +-STATEMENT CREATE (t:test {prop: 376787}); +---- ok +-STATEMENT CREATE (t:test {prop: 513819}); +---- ok +-STATEMENT CREATE (t:test {prop: 462976}); +---- ok +-STATEMENT CREATE (t:test {prop: 371291}); +---- ok +-STATEMENT CREATE (t:test {prop: 425723}); +---- ok +-STATEMENT CREATE (t:test {prop: 902362}); +---- ok +-STATEMENT CREATE (t:test {prop: 676103}); +---- ok +-STATEMENT CREATE (t:test {prop: 164173}); +---- ok +-STATEMENT CREATE (t:test {prop: 390781}); +---- ok +-STATEMENT CREATE (t:test {prop: 654010}); +---- ok +-STATEMENT CREATE (t:test {prop: 241532}); +---- ok +-STATEMENT CREATE (t:test {prop: 852084}); +---- ok +-STATEMENT CREATE (t:test {prop: 732161}); +---- ok +-STATEMENT CREATE (t:test {prop: 46822}); +---- ok +-STATEMENT CREATE (t:test {prop: 854297}); +---- ok +-STATEMENT CREATE (t:test {prop: 852683}); +---- ok +-STATEMENT CREATE (t:test {prop: 885758}); +---- ok +-STATEMENT CREATE (t:test {prop: 229138}); +---- ok +-STATEMENT CREATE (t:test {prop: 399142}); +---- ok +-STATEMENT CREATE (t:test {prop: 823844}); +---- ok +-STATEMENT CREATE (t:test {prop: 37558}); +---- ok +-STATEMENT CREATE (t:test {prop: 591383}); +---- ok +-STATEMENT CREATE (t:test {prop: 102061}); +---- ok +-STATEMENT CREATE (t:test {prop: 52322}); +---- ok +-STATEMENT CREATE (t:test {prop: 744293}); +---- ok +-STATEMENT CREATE (t:test {prop: 216048}); +---- ok +-STATEMENT CREATE (t:test {prop: 962347}); +---- ok +-STATEMENT CREATE (t:test {prop: 621082}); +---- ok +-STATEMENT CREATE (t:test {prop: 355034}); +---- ok +-STATEMENT CREATE (t:test {prop: 516019}); +---- ok +-STATEMENT CREATE (t:test {prop: 430076}); +---- ok +-STATEMENT CREATE (t:test {prop: 887600}); +---- ok +-STATEMENT CREATE (t:test {prop: 753191}); +---- ok +-STATEMENT CREATE (t:test {prop: 13481}); +---- ok +-STATEMENT CREATE (t:test {prop: 483093}); +---- ok +-STATEMENT CREATE (t:test {prop: 441736}); +---- ok +-STATEMENT CREATE (t:test {prop: 10633}); +---- ok +-STATEMENT CREATE (t:test {prop: 81306}); +---- ok +-STATEMENT CREATE (t:test {prop: 787435}); +---- ok +-STATEMENT CREATE (t:test {prop: 294678}); +---- ok +-STATEMENT CREATE (t:test {prop: 972453}); +---- ok +-STATEMENT CREATE (t:test {prop: 394999}); +---- ok +-STATEMENT CREATE (t:test {prop: 29107}); +---- ok +-STATEMENT CREATE (t:test {prop: 770324}); +---- ok +-STATEMENT CREATE (t:test {prop: 791924}); +---- ok +-STATEMENT CREATE (t:test {prop: 238016}); +---- ok +-STATEMENT CREATE (t:test {prop: 730496}); +---- ok +-STATEMENT CREATE (t:test {prop: 449506}); +---- ok +-STATEMENT CREATE (t:test {prop: 457177}); +---- ok +-STATEMENT CREATE (t:test {prop: 196553}); +---- ok +-STATEMENT CREATE (t:test {prop: 547235}); +---- ok +-STATEMENT CREATE (t:test {prop: 616984}); +---- ok +-STATEMENT CREATE (t:test {prop: 782666}); +---- ok +-STATEMENT CREATE (t:test {prop: 33889}); +---- ok +-STATEMENT CREATE (t:test {prop: 729353}); +---- ok +-STATEMENT CREATE (t:test {prop: 537856}); +---- ok +-STATEMENT CREATE (t:test {prop: 198456}); +---- ok +-STATEMENT CREATE (t:test {prop: 821183}); +---- ok +-STATEMENT CREATE (t:test {prop: 903864}); +---- ok +-STATEMENT CREATE (t:test {prop: 359029}); +---- ok +-STATEMENT CREATE (t:test {prop: 853193}); +---- ok +-STATEMENT CREATE (t:test {prop: 432223}); +---- ok +-STATEMENT CREATE (t:test {prop: 760087}); +---- ok +-STATEMENT CREATE (t:test {prop: 418846}); +---- ok +-STATEMENT CREATE (t:test {prop: 679396}); +---- ok +-STATEMENT CREATE (t:test {prop: 569088}); +---- ok +-STATEMENT CREATE (t:test {prop: 495524}); +---- ok +-STATEMENT CREATE (t:test {prop: 191207}); +---- ok +-STATEMENT CREATE (t:test {prop: 543515}); +---- ok +-STATEMENT CREATE (t:test {prop: 79872}); +---- ok +-STATEMENT CREATE (t:test {prop: 966792}); +---- ok +-STATEMENT CREATE (t:test {prop: 92364}); +---- ok +-STATEMENT CREATE (t:test {prop: 111173}); +---- ok +-STATEMENT CREATE (t:test {prop: 42380}); +---- ok +-STATEMENT CREATE (t:test {prop: 235160}); +---- ok +-STATEMENT CREATE (t:test {prop: 881445}); +---- ok +-STATEMENT CREATE (t:test {prop: 757985}); +---- ok +-STATEMENT CREATE (t:test {prop: 606808}); +---- ok +-STATEMENT CREATE (t:test {prop: 881218}); +---- ok +-STATEMENT CREATE (t:test {prop: 817}); +---- ok +-STATEMENT CREATE (t:test {prop: 891334}); +---- ok +-STATEMENT CREATE (t:test {prop: 878568}); +---- ok +-STATEMENT CREATE (t:test {prop: 786437}); +---- ok +-STATEMENT CREATE (t:test {prop: 57815}); +---- ok +-STATEMENT CREATE (t:test {prop: 795792}); +---- ok +-STATEMENT CREATE (t:test {prop: 431996}); +---- ok +-STATEMENT CREATE (t:test {prop: 332111}); +---- ok +-STATEMENT CREATE (t:test {prop: 598332}); +---- ok +-STATEMENT CREATE (t:test {prop: 766364}); +---- ok +-STATEMENT CREATE (t:test {prop: 287287}); +---- ok +-STATEMENT CREATE (t:test {prop: 715217}); +---- ok +-STATEMENT CREATE (t:test {prop: 906323}); +---- ok +-STATEMENT CREATE (t:test {prop: 735754}); +---- ok +-STATEMENT CREATE (t:test {prop: 481135}); +---- ok +-STATEMENT CREATE (t:test {prop: 964017}); +---- ok +-STATEMENT CREATE (t:test {prop: 643952}); +---- ok +-STATEMENT CREATE (t:test {prop: 698933}); +---- ok +-STATEMENT CREATE (t:test {prop: 937750}); +---- ok +-STATEMENT CREATE (t:test {prop: 538236}); +---- ok +-STATEMENT CREATE (t:test {prop: 349411}); +---- ok +-STATEMENT CREATE (t:test {prop: 602008}); +---- ok +-STATEMENT CREATE (t:test {prop: 814543}); +---- ok +-STATEMENT CREATE (t:test {prop: 65926}); +---- ok +-STATEMENT CREATE (t:test {prop: 790798}); +---- ok +-STATEMENT CREATE (t:test {prop: 897072}); +---- ok +-STATEMENT CREATE (t:test {prop: 560223}); +---- ok +-STATEMENT CREATE (t:test {prop: 178405}); +---- ok +-STATEMENT CREATE (t:test {prop: 332619}); +---- ok +-STATEMENT CREATE (t:test {prop: 507469}); +---- ok +-STATEMENT CREATE (t:test {prop: 678343}); +---- ok +-STATEMENT CREATE (t:test {prop: 472290}); +---- ok +-STATEMENT CREATE (t:test {prop: 473845}); +---- ok +-STATEMENT CREATE (t:test {prop: 446289}); +---- ok +-STATEMENT CREATE (t:test {prop: 406215}); +---- ok +-STATEMENT CREATE (t:test {prop: 646263}); +---- ok +-STATEMENT CREATE (t:test {prop: 464225}); +---- ok +-STATEMENT CREATE (t:test {prop: 246282}); +---- ok +-STATEMENT CREATE (t:test {prop: 847805}); +---- ok +-STATEMENT CREATE (t:test {prop: 483935}); +---- ok +-STATEMENT CREATE (t:test {prop: 714874}); +---- ok +-STATEMENT CREATE (t:test {prop: 291891}); +---- ok +-STATEMENT CREATE (t:test {prop: 923377}); +---- ok +-STATEMENT CREATE (t:test {prop: 581566}); +---- ok +-STATEMENT CREATE (t:test {prop: 159832}); +---- ok +-STATEMENT CREATE (t:test {prop: 147260}); +---- ok +-STATEMENT CREATE (t:test {prop: 139681}); +---- ok +-STATEMENT CREATE (t:test {prop: 32479}); +---- ok +-STATEMENT CREATE (t:test {prop: 762540}); +---- ok +-STATEMENT CREATE (t:test {prop: 730008}); +---- ok +-STATEMENT CREATE (t:test {prop: 370183}); +---- ok +-STATEMENT CREATE (t:test {prop: 255829}); +---- ok +-STATEMENT CREATE (t:test {prop: 42955}); +---- ok +-STATEMENT CREATE (t:test {prop: 13836}); +---- ok +-STATEMENT CREATE (t:test {prop: 159529}); +---- ok +-STATEMENT CREATE (t:test {prop: 821772}); +---- ok +-STATEMENT CREATE (t:test {prop: 833324}); +---- ok +-STATEMENT CREATE (t:test {prop: 651314}); +---- ok +-STATEMENT CREATE (t:test {prop: 971154}); +---- ok +-STATEMENT CREATE (t:test {prop: 95133}); +---- ok +-STATEMENT CREATE (t:test {prop: 669667}); +---- ok +-STATEMENT CREATE (t:test {prop: 419684}); +---- ok +-STATEMENT CREATE (t:test {prop: 112972}); +---- ok +-STATEMENT CREATE (t:test {prop: 474592}); +---- ok +-STATEMENT CREATE (t:test {prop: 180468}); +---- ok +-STATEMENT CREATE (t:test {prop: 626763}); +---- ok +-STATEMENT CREATE (t:test {prop: 42588}); +---- ok +-STATEMENT CREATE (t:test {prop: 974522}); +---- ok +-STATEMENT CREATE (t:test {prop: 634717}); +---- ok +-STATEMENT CREATE (t:test {prop: 780415}); +---- ok +-STATEMENT CREATE (t:test {prop: 512205}); +---- ok +-STATEMENT CREATE (t:test {prop: 871753}); +---- ok +-STATEMENT CREATE (t:test {prop: 36029}); +---- ok +-STATEMENT CREATE (t:test {prop: 99121}); +---- ok +-STATEMENT CREATE (t:test {prop: 60565}); +---- ok +-STATEMENT CREATE (t:test {prop: 571774}); +---- ok +-STATEMENT CREATE (t:test {prop: 821518}); +---- ok +-STATEMENT CREATE (t:test {prop: 702143}); +---- ok +-STATEMENT CREATE (t:test {prop: 175830}); +---- ok +-STATEMENT CREATE (t:test {prop: 257660}); +---- ok +-STATEMENT CREATE (t:test {prop: 705453}); +---- ok +-STATEMENT CREATE (t:test {prop: 402504}); +---- ok +-STATEMENT CREATE (t:test {prop: 351283}); +---- ok +-STATEMENT CREATE (t:test {prop: 79487}); +---- ok +-STATEMENT CREATE (t:test {prop: 770245}); +---- ok +-STATEMENT CREATE (t:test {prop: 795505}); +---- ok +-STATEMENT CREATE (t:test {prop: 573366}); +---- ok +-STATEMENT CREATE (t:test {prop: 441087}); +---- ok +-STATEMENT CREATE (t:test {prop: 125568}); +---- ok +-STATEMENT CREATE (t:test {prop: 214051}); +---- ok +-STATEMENT CREATE (t:test {prop: 792571}); +---- ok +-STATEMENT CREATE (t:test {prop: 897698}); +---- ok +-STATEMENT CREATE (t:test {prop: 994561}); +---- ok +-STATEMENT CREATE (t:test {prop: 723506}); +---- ok +-STATEMENT CREATE (t:test {prop: 500584}); +---- ok +-STATEMENT CREATE (t:test {prop: 393323}); +---- ok +-STATEMENT CREATE (t:test {prop: 946544}); +---- ok +-STATEMENT CREATE (t:test {prop: 629355}); +---- ok +-STATEMENT CREATE (t:test {prop: 631617}); +---- ok +-STATEMENT CREATE (t:test {prop: 524523}); +---- ok +-STATEMENT CREATE (t:test {prop: 373053}); +---- ok +-STATEMENT CREATE (t:test {prop: 487276}); +---- ok +-STATEMENT CREATE (t:test {prop: 904163}); +---- ok +-STATEMENT CREATE (t:test {prop: 539500}); +---- ok +-STATEMENT CREATE (t:test {prop: 913568}); +---- ok +-STATEMENT CREATE (t:test {prop: 896366}); +---- ok +-STATEMENT CREATE (t:test {prop: 454107}); +---- ok +-STATEMENT CREATE (t:test {prop: 619752}); +---- ok +-STATEMENT CREATE (t:test {prop: 618984}); +---- ok +-STATEMENT CREATE (t:test {prop: 826635}); +---- ok +-STATEMENT CREATE (t:test {prop: 350716}); +---- ok +-STATEMENT CREATE (t:test {prop: 519316}); +---- ok +-STATEMENT CREATE (t:test {prop: 889162}); +---- ok +-STATEMENT CREATE (t:test {prop: 654345}); +---- ok +-STATEMENT CREATE (t:test {prop: 868633}); +---- ok +-STATEMENT CREATE (t:test {prop: 349047}); +---- ok +-STATEMENT CREATE (t:test {prop: 354980}); +---- ok +-STATEMENT CREATE (t:test {prop: 575728}); +---- ok +-STATEMENT CREATE (t:test {prop: 367901}); +---- ok +-STATEMENT CREATE (t:test {prop: 977440}); +---- ok +-STATEMENT CREATE (t:test {prop: 994619}); +---- ok +-STATEMENT CREATE (t:test {prop: 571392}); +---- ok +-STATEMENT CREATE (t:test {prop: 663413}); +---- ok +-STATEMENT CREATE (t:test {prop: 68800}); +---- ok +-STATEMENT CREATE (t:test {prop: 228502}); +---- ok +-STATEMENT CREATE (t:test {prop: 145954}); +---- ok +-STATEMENT CREATE (t:test {prop: 860541}); +---- ok +-STATEMENT CREATE (t:test {prop: 904276}); +---- ok +-STATEMENT CREATE (t:test {prop: 311063}); +---- ok +-STATEMENT CREATE (t:test {prop: 974232}); +---- ok +-STATEMENT CREATE (t:test {prop: 876266}); +---- ok +-STATEMENT CREATE (t:test {prop: 139242}); +---- ok +-STATEMENT CREATE (t:test {prop: 954080}); +---- ok +-STATEMENT CREATE (t:test {prop: 882346}); +---- ok +-STATEMENT CREATE (t:test {prop: 946798}); +---- ok +-STATEMENT CREATE (t:test {prop: 81391}); +---- ok +-STATEMENT CREATE (t:test {prop: 326165}); +---- ok +-STATEMENT CREATE (t:test {prop: 343192}); +---- ok +-STATEMENT CREATE (t:test {prop: 76821}); +---- ok +-STATEMENT CREATE (t:test {prop: 458160}); +---- ok +-STATEMENT CREATE (t:test {prop: 143448}); +---- ok +-STATEMENT CREATE (t:test {prop: 933561}); +---- ok +-STATEMENT CREATE (t:test {prop: 816353}); +---- ok +-STATEMENT CREATE (t:test {prop: 475777}); +---- ok +-STATEMENT CREATE (t:test {prop: 984194}); +---- ok +-STATEMENT CREATE (t:test {prop: 398375}); +---- ok +-STATEMENT CREATE (t:test {prop: 532291}); +---- ok +-STATEMENT CREATE (t:test {prop: 543254}); +---- ok +-STATEMENT CREATE (t:test {prop: 585798}); +---- ok +-STATEMENT CREATE (t:test {prop: 65854}); +---- ok +-STATEMENT CREATE (t:test {prop: 436160}); +---- ok +-STATEMENT CREATE (t:test {prop: 512677}); +---- ok +-STATEMENT CREATE (t:test {prop: 976921}); +---- ok +-STATEMENT CREATE (t:test {prop: 247337}); +---- ok +-STATEMENT CREATE (t:test {prop: 789763}); +---- ok +-STATEMENT CREATE (t:test {prop: 164296}); +---- ok +-STATEMENT CREATE (t:test {prop: 570799}); +---- ok +-STATEMENT CREATE (t:test {prop: 60444}); +---- ok +-STATEMENT CREATE (t:test {prop: 668145}); +---- ok +-STATEMENT CREATE (t:test {prop: 936658}); +---- ok +-STATEMENT CREATE (t:test {prop: 166167}); +---- ok +-STATEMENT CREATE (t:test {prop: 246647}); +---- ok +-STATEMENT CREATE (t:test {prop: 440923}); +---- ok +-STATEMENT CREATE (t:test {prop: 707747}); +---- ok +-STATEMENT CREATE (t:test {prop: 736234}); +---- ok +-STATEMENT CREATE (t:test {prop: 419394}); +---- ok +-STATEMENT CREATE (t:test {prop: 774241}); +---- ok +-STATEMENT CREATE (t:test {prop: 415502}); +---- ok +-STATEMENT CREATE (t:test {prop: 912756}); +---- ok +-STATEMENT CREATE (t:test {prop: 866752}); +---- ok +-STATEMENT CREATE (t:test {prop: 851733}); +---- ok +-STATEMENT CREATE (t:test {prop: 264658}); +---- ok +-STATEMENT CREATE (t:test {prop: 162339}); +---- ok +-STATEMENT CREATE (t:test {prop: 473957}); +---- ok +-STATEMENT CREATE (t:test {prop: 322014}); +---- ok +-STATEMENT CREATE (t:test {prop: 468092}); +---- ok +-STATEMENT CREATE (t:test {prop: 426217}); +---- ok +-STATEMENT CREATE (t:test {prop: 805721}); +---- ok +-STATEMENT CREATE (t:test {prop: 620400}); +---- ok +-STATEMENT CREATE (t:test {prop: 961360}); +---- ok +-STATEMENT CREATE (t:test {prop: 50852}); +---- ok +-STATEMENT CREATE (t:test {prop: 409607}); +---- ok +-STATEMENT CREATE (t:test {prop: 702290}); +---- ok +-STATEMENT CREATE (t:test {prop: 47283}); +---- ok +-STATEMENT CREATE (t:test {prop: 397128}); +---- ok +-STATEMENT CREATE (t:test {prop: 73391}); +---- ok +-STATEMENT CREATE (t:test {prop: 839245}); +---- ok +-STATEMENT CREATE (t:test {prop: 688791}); +---- ok +-STATEMENT CREATE (t:test {prop: 746362}); +---- ok +-STATEMENT CREATE (t:test {prop: 91131}); +---- ok +-STATEMENT CREATE (t:test {prop: 25914}); +---- ok +-STATEMENT CREATE (t:test {prop: 423080}); +---- ok +-STATEMENT CREATE (t:test {prop: 452983}); +---- ok +-STATEMENT CREATE (t:test {prop: 573891}); +---- ok +-STATEMENT CREATE (t:test {prop: 87031}); +---- ok +-STATEMENT CREATE (t:test {prop: 194141}); +---- ok +-STATEMENT CREATE (t:test {prop: 410480}); +---- ok +-STATEMENT CREATE (t:test {prop: 21215}); +---- ok +-STATEMENT CREATE (t:test {prop: 706498}); +---- ok +-STATEMENT CREATE (t:test {prop: 401463}); +---- ok +-STATEMENT CREATE (t:test {prop: 538903}); +---- ok +-STATEMENT CREATE (t:test {prop: 175017}); +---- ok +-STATEMENT CREATE (t:test {prop: 823412}); +---- ok +-STATEMENT CREATE (t:test {prop: 960392}); +---- ok +-STATEMENT CREATE (t:test {prop: 461902}); +---- ok +-STATEMENT CREATE (t:test {prop: 152232}); +---- ok +-STATEMENT CREATE (t:test {prop: 933141}); +---- ok +-STATEMENT CREATE (t:test {prop: 726747}); +---- ok +-STATEMENT CREATE (t:test {prop: 334210}); +---- ok +-STATEMENT CREATE (t:test {prop: 462302}); +---- ok +-STATEMENT CREATE (t:test {prop: 627435}); +---- ok +-STATEMENT CREATE (t:test {prop: 970800}); +---- ok +-STATEMENT CREATE (t:test {prop: 116005}); +---- ok +-STATEMENT CREATE (t:test {prop: 506337}); +---- ok +-STATEMENT CREATE (t:test {prop: 26350}); +---- ok +-STATEMENT CREATE (t:test {prop: 679923}); +---- ok +-STATEMENT CREATE (t:test {prop: 716902}); +---- ok +-STATEMENT CREATE (t:test {prop: 418299}); +---- ok +-STATEMENT CREATE (t:test {prop: 385708}); +---- ok +-STATEMENT CREATE (t:test {prop: 496654}); +---- ok +-STATEMENT CREATE (t:test {prop: 552958}); +---- ok +-STATEMENT CREATE (t:test {prop: 927838}); +---- ok +-STATEMENT CREATE (t:test {prop: 480255}); +---- ok +-STATEMENT CREATE (t:test {prop: 477534}); +---- ok +-STATEMENT CREATE (t:test {prop: 774172}); +---- ok +-STATEMENT CREATE (t:test {prop: 41201}); +---- ok +-STATEMENT CREATE (t:test {prop: 258885}); +---- ok +-STATEMENT CREATE (t:test {prop: 555996}); +---- ok +-STATEMENT CREATE (t:test {prop: 96059}); +---- ok +-STATEMENT CREATE (t:test {prop: 465889}); +---- ok +-STATEMENT CREATE (t:test {prop: 809313}); +---- ok +-STATEMENT CREATE (t:test {prop: 146110}); +---- ok +-STATEMENT CREATE (t:test {prop: 639291}); +---- ok +-STATEMENT CREATE (t:test {prop: 207979}); +---- ok +-STATEMENT CREATE (t:test {prop: 492230}); +---- ok +-STATEMENT CREATE (t:test {prop: 919068}); +---- ok +-STATEMENT CREATE (t:test {prop: 467336}); +---- ok +-STATEMENT CREATE (t:test {prop: 187212}); +---- ok +-STATEMENT CREATE (t:test {prop: 901474}); +---- ok +-STATEMENT CREATE (t:test {prop: 312342}); +---- ok +-STATEMENT CREATE (t:test {prop: 323075}); +---- ok +-STATEMENT CREATE (t:test {prop: 513924}); +---- ok +-STATEMENT CREATE (t:test {prop: 284763}); +---- ok +-STATEMENT CREATE (t:test {prop: 655793}); +---- ok +-STATEMENT CREATE (t:test {prop: 884655}); +---- ok +-STATEMENT CREATE (t:test {prop: 522427}); +---- ok +-STATEMENT CREATE (t:test {prop: 324224}); +---- ok +-STATEMENT CREATE (t:test {prop: 172093}); +---- ok +-STATEMENT CREATE (t:test {prop: 867685}); +---- ok +-STATEMENT CREATE (t:test {prop: 283154}); +---- ok +-STATEMENT CREATE (t:test {prop: 58102}); +---- ok +-STATEMENT CREATE (t:test {prop: 439047}); +---- ok +-STATEMENT CREATE (t:test {prop: 337401}); +---- ok +-STATEMENT CREATE (t:test {prop: 77337}); +---- ok +-STATEMENT CREATE (t:test {prop: 323450}); +---- ok +-STATEMENT CREATE (t:test {prop: 434185}); +---- ok +-STATEMENT CREATE (t:test {prop: 884948}); +---- ok +-STATEMENT CREATE (t:test {prop: 116021}); +---- ok +-STATEMENT CREATE (t:test {prop: 464596}); +---- ok +-STATEMENT CREATE (t:test {prop: 115735}); +---- ok +-STATEMENT CREATE (t:test {prop: 842982}); +---- ok +-STATEMENT CREATE (t:test {prop: 800802}); +---- ok +-STATEMENT CREATE (t:test {prop: 868138}); +---- ok +-STATEMENT CREATE (t:test {prop: 727713}); +---- ok +-STATEMENT CREATE (t:test {prop: 252362}); +---- ok +-STATEMENT CREATE (t:test {prop: 362015}); +---- ok +-STATEMENT CREATE (t:test {prop: 232021}); +---- ok +-STATEMENT CREATE (t:test {prop: 564579}); +---- ok +-STATEMENT CREATE (t:test {prop: 70254}); +---- ok +-STATEMENT CREATE (t:test {prop: 588455}); +---- ok +-STATEMENT CREATE (t:test {prop: 576462}); +---- ok +-STATEMENT CREATE (t:test {prop: 477212}); +---- ok +-STATEMENT CREATE (t:test {prop: 114597}); +---- ok +-STATEMENT CREATE (t:test {prop: 713110}); +---- ok +-STATEMENT CREATE (t:test {prop: 334661}); +---- ok +-STATEMENT CREATE (t:test {prop: 206557}); +---- ok +-STATEMENT CREATE (t:test {prop: 532503}); +---- ok +-STATEMENT CREATE (t:test {prop: 676365}); +---- ok +-STATEMENT CREATE (t:test {prop: 305205}); +---- ok +-STATEMENT CREATE (t:test {prop: 132263}); +---- ok +-STATEMENT CREATE (t:test {prop: 589105}); +---- ok +-STATEMENT CREATE (t:test {prop: 845937}); +---- ok +-STATEMENT CREATE (t:test {prop: 293574}); +---- ok +-STATEMENT CREATE (t:test {prop: 792747}); +---- ok +-STATEMENT CREATE (t:test {prop: 870357}); +---- ok +-STATEMENT CREATE (t:test {prop: 68757}); +---- ok +-STATEMENT CREATE (t:test {prop: 201972}); +---- ok +-STATEMENT CREATE (t:test {prop: 956888}); +---- ok +-STATEMENT CREATE (t:test {prop: 741753}); +---- ok +-STATEMENT CREATE (t:test {prop: 931681}); +---- ok +-STATEMENT CREATE (t:test {prop: 782555}); +---- ok +-STATEMENT CREATE (t:test {prop: 373705}); +---- ok +-STATEMENT CREATE (t:test {prop: 965362}); +---- ok +-STATEMENT CREATE (t:test {prop: 824856}); +---- ok +-STATEMENT CREATE (t:test {prop: 314089}); +---- ok +-STATEMENT CREATE (t:test {prop: 544792}); +---- ok +-STATEMENT CREATE (t:test {prop: 436759}); +---- ok +-STATEMENT CREATE (t:test {prop: 215637}); +---- ok +-STATEMENT CREATE (t:test {prop: 311947}); +---- ok +-STATEMENT CREATE (t:test {prop: 48160}); +---- ok +-STATEMENT CREATE (t:test {prop: 445202}); +---- ok +-STATEMENT CREATE (t:test {prop: 598375}); +---- ok +-STATEMENT CREATE (t:test {prop: 825658}); +---- ok +-STATEMENT CREATE (t:test {prop: 879361}); +---- ok +-STATEMENT CREATE (t:test {prop: 543097}); +---- ok +-STATEMENT CREATE (t:test {prop: 673889}); +---- ok +-STATEMENT CREATE (t:test {prop: 851133}); +---- ok +-STATEMENT CREATE (t:test {prop: 604566}); +---- ok +-STATEMENT CREATE (t:test {prop: 214266}); +---- ok +-STATEMENT CREATE (t:test {prop: 959289}); +---- ok +-STATEMENT CREATE (t:test {prop: 409690}); +---- ok +-STATEMENT CREATE (t:test {prop: 758470}); +---- ok +-STATEMENT CREATE (t:test {prop: 687793}); +---- ok +-STATEMENT CREATE (t:test {prop: 904689}); +---- ok +-STATEMENT CREATE (t:test {prop: 922894}); +---- ok +-STATEMENT CREATE (t:test {prop: 18519}); +---- ok +-STATEMENT CREATE (t:test {prop: 646024}); +---- ok +-STATEMENT CREATE (t:test {prop: 987166}); +---- ok +-STATEMENT CREATE (t:test {prop: 981786}); +---- ok +-STATEMENT CREATE (t:test {prop: 837675}); +---- ok +-STATEMENT CREATE (t:test {prop: 10566}); +---- ok +-STATEMENT CREATE (t:test {prop: 194596}); +---- ok +-STATEMENT CREATE (t:test {prop: 795067}); +---- ok +-STATEMENT CREATE (t:test {prop: 345714}); +---- ok +-STATEMENT CREATE (t:test {prop: 282336}); +---- ok +-STATEMENT CREATE (t:test {prop: 994366}); +---- ok +-STATEMENT CREATE (t:test {prop: 530807}); +---- ok +-STATEMENT CREATE (t:test {prop: 934961}); +---- ok +-STATEMENT CREATE (t:test {prop: 691533}); +---- ok +-STATEMENT CREATE (t:test {prop: 854029}); +---- ok +-STATEMENT CREATE (t:test {prop: 966584}); +---- ok +-STATEMENT CREATE (t:test {prop: 871832}); +---- ok +-STATEMENT CREATE (t:test {prop: 38452}); +---- ok +-STATEMENT CREATE (t:test {prop: 97421}); +---- ok +-STATEMENT CREATE (t:test {prop: 534728}); +---- ok +-STATEMENT CREATE (t:test {prop: 4740}); +---- ok +-STATEMENT CREATE (t:test {prop: 428743}); +---- ok +-STATEMENT CREATE (t:test {prop: 415600}); +---- ok +-STATEMENT CREATE (t:test {prop: 850986}); +---- ok +-STATEMENT CREATE (t:test {prop: 25578}); +---- ok +-STATEMENT CREATE (t:test {prop: 39848}); +---- ok +-STATEMENT CREATE (t:test {prop: 64219}); +---- ok +-STATEMENT CREATE (t:test {prop: 87973}); +---- ok +-STATEMENT CREATE (t:test {prop: 104624}); +---- ok +-STATEMENT CREATE (t:test {prop: 348205}); +---- ok +-STATEMENT CREATE (t:test {prop: 568123}); +---- ok +-STATEMENT CREATE (t:test {prop: 289482}); +---- ok +-STATEMENT CREATE (t:test {prop: 491693}); +---- ok +-STATEMENT CREATE (t:test {prop: 561056}); +---- ok +-STATEMENT CREATE (t:test {prop: 597014}); +---- ok +-STATEMENT CREATE (t:test {prop: 856678}); +---- ok +-STATEMENT CREATE (t:test {prop: 563188}); +---- ok +-STATEMENT CREATE (t:test {prop: 70866}); +---- ok +-STATEMENT CREATE (t:test {prop: 280809}); +---- ok +-STATEMENT CREATE (t:test {prop: 437524}); +---- ok +-STATEMENT CREATE (t:test {prop: 416144}); +---- ok +-STATEMENT CREATE (t:test {prop: 129404}); +---- ok +-STATEMENT CREATE (t:test {prop: 826959}); +---- ok +-STATEMENT CREATE (t:test {prop: 634236}); +---- ok +-STATEMENT CREATE (t:test {prop: 558360}); +---- ok +-STATEMENT CREATE (t:test {prop: 562343}); +---- ok +-STATEMENT CREATE (t:test {prop: 182199}); +---- ok +-STATEMENT CREATE (t:test {prop: 137958}); +---- ok +-STATEMENT CREATE (t:test {prop: 835589}); +---- ok +-STATEMENT CREATE (t:test {prop: 727412}); +---- ok +-STATEMENT CREATE (t:test {prop: 622046}); +---- ok +-STATEMENT CREATE (t:test {prop: 178736}); +---- ok +-STATEMENT CREATE (t:test {prop: 665135}); +---- ok +-STATEMENT CREATE (t:test {prop: 165349}); +---- ok +-STATEMENT CREATE (t:test {prop: 594759}); +---- ok +-STATEMENT CREATE (t:test {prop: 814149}); +---- ok +-STATEMENT CREATE (t:test {prop: 944853}); +---- ok +-STATEMENT CREATE (t:test {prop: 137653}); +---- ok +-STATEMENT CREATE (t:test {prop: 638096}); +---- ok +-STATEMENT CREATE (t:test {prop: 409076}); +---- ok +-STATEMENT CREATE (t:test {prop: 758846}); +---- ok +-STATEMENT CREATE (t:test {prop: 874578}); +---- ok +-STATEMENT CREATE (t:test {prop: 112897}); +---- ok +-STATEMENT CREATE (t:test {prop: 517085}); +---- ok +-STATEMENT CREATE (t:test {prop: 907319}); +---- ok +-STATEMENT CREATE (t:test {prop: 338580}); +---- ok +-STATEMENT CREATE (t:test {prop: 323239}); +---- ok +-STATEMENT CREATE (t:test {prop: 97181}); +---- ok +-STATEMENT CREATE (t:test {prop: 604317}); +---- ok +-STATEMENT CREATE (t:test {prop: 633819}); +---- ok +-STATEMENT CREATE (t:test {prop: 399069}); +---- ok +-STATEMENT CREATE (t:test {prop: 656691}); +---- ok +-STATEMENT CREATE (t:test {prop: 242619}); +---- ok +-STATEMENT CREATE (t:test {prop: 939636}); +---- ok +-STATEMENT CREATE (t:test {prop: 383065}); +---- ok +-STATEMENT CREATE (t:test {prop: 979897}); +---- ok +-STATEMENT CREATE (t:test {prop: 337800}); +---- ok +-STATEMENT CREATE (t:test {prop: 777964}); +---- ok +-STATEMENT CREATE (t:test {prop: 957376}); +---- ok +-STATEMENT CREATE (t:test {prop: 903091}); +---- ok +-STATEMENT CREATE (t:test {prop: 921178}); +---- ok +-STATEMENT CREATE (t:test {prop: 597182}); +---- ok +-STATEMENT CREATE (t:test {prop: 861012}); +---- ok +-STATEMENT CREATE (t:test {prop: 824959}); +---- ok +-STATEMENT CREATE (t:test {prop: 957959}); +---- ok +-STATEMENT CREATE (t:test {prop: 642601}); +---- ok +-STATEMENT CREATE (t:test {prop: 66140}); +---- ok +-STATEMENT CREATE (t:test {prop: 254501}); +---- ok +-STATEMENT CREATE (t:test {prop: 123832}); +---- ok +-STATEMENT CREATE (t:test {prop: 987284}); +---- ok +-STATEMENT CREATE (t:test {prop: 599230}); +---- ok +-STATEMENT CREATE (t:test {prop: 628761}); +---- ok +-STATEMENT CREATE (t:test {prop: 545260}); +---- ok +-STATEMENT CREATE (t:test {prop: 540521}); +---- ok +-STATEMENT CREATE (t:test {prop: 376946}); +---- ok +-STATEMENT CREATE (t:test {prop: 842985}); +---- ok +-STATEMENT CREATE (t:test {prop: 529260}); +---- ok +-STATEMENT CREATE (t:test {prop: 725641}); +---- ok +-STATEMENT CREATE (t:test {prop: 514508}); +---- ok +-STATEMENT CREATE (t:test {prop: 12820}); +---- ok +-STATEMENT CREATE (t:test {prop: 684006}); +---- ok +-STATEMENT CREATE (t:test {prop: 950759}); +---- ok +-STATEMENT CREATE (t:test {prop: 773474}); +---- ok +-STATEMENT CREATE (t:test {prop: 523005}); +---- ok +-STATEMENT CREATE (t:test {prop: 734552}); +---- ok +-STATEMENT CREATE (t:test {prop: 251969}); +---- ok +-STATEMENT CREATE (t:test {prop: 702376}); +---- ok +-STATEMENT CREATE (t:test {prop: 635497}); +---- ok +-STATEMENT CREATE (t:test {prop: 253524}); +---- ok +-STATEMENT CREATE (t:test {prop: 448988}); +---- ok +-STATEMENT CREATE (t:test {prop: 626045}); +---- ok +-STATEMENT CREATE (t:test {prop: 365346}); +---- ok +-STATEMENT CREATE (t:test {prop: 237126}); +---- ok +-STATEMENT CREATE (t:test {prop: 401934}); +---- ok +-STATEMENT CREATE (t:test {prop: 638803}); +---- ok +-STATEMENT CREATE (t:test {prop: 999970}); +---- ok +-STATEMENT CREATE (t:test {prop: 536958}); +---- ok +-STATEMENT CREATE (t:test {prop: 203597}); +---- ok +-STATEMENT CREATE (t:test {prop: 740245}); +---- ok +-STATEMENT CREATE (t:test {prop: 548677}); +---- ok +-STATEMENT CREATE (t:test {prop: 403516}); +---- ok +-STATEMENT CREATE (t:test {prop: 479687}); +---- ok +-STATEMENT CREATE (t:test {prop: 947202}); +---- ok +-STATEMENT CREATE (t:test {prop: 61539}); +---- ok +-STATEMENT CREATE (t:test {prop: 677888}); +---- ok +-STATEMENT CREATE (t:test {prop: 568675}); +---- ok +-STATEMENT CREATE (t:test {prop: 498645}); +---- ok +-STATEMENT CREATE (t:test {prop: 590727}); +---- ok +-STATEMENT CREATE (t:test {prop: 644529}); +---- ok +-STATEMENT CREATE (t:test {prop: 723264}); +---- ok +-STATEMENT CREATE (t:test {prop: 487142}); +---- ok +-STATEMENT CREATE (t:test {prop: 611960}); +---- ok +-STATEMENT CREATE (t:test {prop: 690811}); +---- ok +-STATEMENT CREATE (t:test {prop: 262536}); +---- ok +-STATEMENT CREATE (t:test {prop: 280876}); +---- ok +-STATEMENT CREATE (t:test {prop: 109733}); +---- ok +-STATEMENT CREATE (t:test {prop: 902749}); +---- ok +-STATEMENT CREATE (t:test {prop: 829355}); +---- ok +-STATEMENT CREATE (t:test {prop: 544856}); +---- ok +-STATEMENT CREATE (t:test {prop: 894212}); +---- ok +-STATEMENT CREATE (t:test {prop: 886836}); +---- ok +-STATEMENT CREATE (t:test {prop: 305723}); +---- ok +-STATEMENT CREATE (t:test {prop: 782978}); +---- ok +-STATEMENT CREATE (t:test {prop: 398908}); +---- ok +-STATEMENT CREATE (t:test {prop: 449654}); +---- ok +-STATEMENT CREATE (t:test {prop: 815077}); +---- ok +-STATEMENT CREATE (t:test {prop: 504336}); +---- ok +-STATEMENT CREATE (t:test {prop: 504817}); +---- ok +-STATEMENT CREATE (t:test {prop: 475080}); +---- ok +-STATEMENT CREATE (t:test {prop: 801503}); +---- ok +-STATEMENT CREATE (t:test {prop: 736708}); +---- ok +-STATEMENT CREATE (t:test {prop: 950818}); +---- ok +-STATEMENT CREATE (t:test {prop: 887947}); +---- ok +-STATEMENT CREATE (t:test {prop: 447909}); +---- ok +-STATEMENT CREATE (t:test {prop: 25105}); +---- ok +-STATEMENT CREATE (t:test {prop: 259140}); +---- ok +-STATEMENT CREATE (t:test {prop: 285432}); +---- ok +-STATEMENT CREATE (t:test {prop: 812605}); +---- ok +-STATEMENT CREATE (t:test {prop: 181612}); +---- ok +-STATEMENT CREATE (t:test {prop: 711455}); +---- ok +-STATEMENT CREATE (t:test {prop: 254020}); +---- ok +-STATEMENT CREATE (t:test {prop: 443808}); +---- ok +-STATEMENT CREATE (t:test {prop: 128276}); +---- ok +-STATEMENT CREATE (t:test {prop: 426253}); +---- ok +-STATEMENT CREATE (t:test {prop: 626150}); +---- ok +-STATEMENT CREATE (t:test {prop: 542562}); +---- ok +-STATEMENT CREATE (t:test {prop: 835372}); +---- ok +-STATEMENT CREATE (t:test {prop: 659388}); +---- ok +-STATEMENT CREATE (t:test {prop: 730847}); +---- ok +-STATEMENT CREATE (t:test {prop: 465907}); +---- ok +-STATEMENT CREATE (t:test {prop: 359958}); +---- ok +-STATEMENT CREATE (t:test {prop: 863686}); +---- ok +-STATEMENT CREATE (t:test {prop: 887075}); +---- ok +-STATEMENT CREATE (t:test {prop: 712289}); +---- ok +-STATEMENT CREATE (t:test {prop: 373749}); +---- ok +-STATEMENT CREATE (t:test {prop: 463961}); +---- ok +-STATEMENT CREATE (t:test {prop: 56664}); +---- ok +-STATEMENT CREATE (t:test {prop: 323964}); +---- ok +-STATEMENT CREATE (t:test {prop: 117209}); +---- ok +-STATEMENT CREATE (t:test {prop: 421426}); +---- ok +-STATEMENT CREATE (t:test {prop: 923749}); +---- ok +-STATEMENT CREATE (t:test {prop: 854313}); +---- ok +-STATEMENT CREATE (t:test {prop: 83036}); +---- ok +-STATEMENT CREATE (t:test {prop: 306496}); +---- ok +-STATEMENT CREATE (t:test {prop: 649255}); +---- ok +-STATEMENT CREATE (t:test {prop: 244072}); +---- ok +-STATEMENT CREATE (t:test {prop: 507398}); +---- ok +-STATEMENT CREATE (t:test {prop: 212679}); +---- ok +-STATEMENT CREATE (t:test {prop: 368425}); +---- ok +-STATEMENT CREATE (t:test {prop: 176111}); +---- ok +-STATEMENT CREATE (t:test {prop: 169668}); +---- ok +-STATEMENT CREATE (t:test {prop: 14520}); +---- ok +-STATEMENT CREATE (t:test {prop: 279263}); +---- ok +-STATEMENT CREATE (t:test {prop: 637710}); +---- ok +-STATEMENT CREATE (t:test {prop: 16096}); +---- ok +-STATEMENT CREATE (t:test {prop: 198729}); +---- ok +-STATEMENT CREATE (t:test {prop: 829091}); +---- ok +-STATEMENT CREATE (t:test {prop: 477129}); +---- ok +-STATEMENT CREATE (t:test {prop: 335041}); +---- ok +-STATEMENT CREATE (t:test {prop: 939841}); +---- ok +-STATEMENT CREATE (t:test {prop: 346892}); +---- ok +-STATEMENT CREATE (t:test {prop: 674817}); +---- ok +-STATEMENT CREATE (t:test {prop: 289696}); +---- ok +-STATEMENT CREATE (t:test {prop: 397687}); +---- ok +-STATEMENT CREATE (t:test {prop: 107396}); +---- ok +-STATEMENT CREATE (t:test {prop: 10428}); +---- ok +-STATEMENT CREATE (t:test {prop: 337515}); +---- ok +-STATEMENT CREATE (t:test {prop: 286226}); +---- ok +-STATEMENT CREATE (t:test {prop: 487644}); +---- ok +-STATEMENT CREATE (t:test {prop: 728582}); +---- ok +-STATEMENT CREATE (t:test {prop: 306058}); +---- ok +-STATEMENT CREATE (t:test {prop: 339249}); +---- ok +-STATEMENT CREATE (t:test {prop: 280639}); +---- ok +-STATEMENT CREATE (t:test {prop: 434812}); +---- ok +-STATEMENT CREATE (t:test {prop: 34961}); +---- ok +-STATEMENT CREATE (t:test {prop: 418393}); +---- ok +-STATEMENT CREATE (t:test {prop: 375972}); +---- ok +-STATEMENT CREATE (t:test {prop: 487410}); +---- ok +-STATEMENT CREATE (t:test {prop: 62163}); +---- ok +-STATEMENT CREATE (t:test {prop: 646610}); +---- ok +-STATEMENT CREATE (t:test {prop: 648950}); +---- ok +-STATEMENT CREATE (t:test {prop: 699131}); +---- ok +-STATEMENT CREATE (t:test {prop: 169509}); +---- ok +-STATEMENT CREATE (t:test {prop: 324898}); +---- ok +-STATEMENT CREATE (t:test {prop: 269107}); +---- ok +-STATEMENT CREATE (t:test {prop: 414462}); +---- ok +-STATEMENT CREATE (t:test {prop: 932661}); +---- ok +-STATEMENT CREATE (t:test {prop: 685216}); +---- ok +-STATEMENT CREATE (t:test {prop: 14073}); +---- ok +-STATEMENT CREATE (t:test {prop: 801065}); +---- ok +-STATEMENT CREATE (t:test {prop: 883336}); +---- ok +-STATEMENT CREATE (t:test {prop: 303301}); +---- ok +-STATEMENT CREATE (t:test {prop: 320469}); +---- ok +-STATEMENT CREATE (t:test {prop: 27624}); +---- ok +-STATEMENT CREATE (t:test {prop: 727923}); +---- ok +-STATEMENT CREATE (t:test {prop: 583474}); +---- ok +-STATEMENT CREATE (t:test {prop: 623520}); +---- ok +-STATEMENT CREATE (t:test {prop: 467990}); +---- ok +-STATEMENT CREATE (t:test {prop: 546692}); +---- ok +-STATEMENT CREATE (t:test {prop: 92126}); +---- ok +-STATEMENT CREATE (t:test {prop: 393468}); +---- ok +-STATEMENT CREATE (t:test {prop: 360357}); +---- ok +-STATEMENT CREATE (t:test {prop: 793288}); +---- ok +-STATEMENT CREATE (t:test {prop: 623946}); +---- ok +-STATEMENT CREATE (t:test {prop: 402111}); +---- ok +-STATEMENT CREATE (t:test {prop: 859398}); +---- ok +-STATEMENT CREATE (t:test {prop: 288968}); +---- ok +-STATEMENT CREATE (t:test {prop: 378695}); +---- ok +-STATEMENT CREATE (t:test {prop: 737853}); +---- ok +-STATEMENT CREATE (t:test {prop: 987206}); +---- ok +-STATEMENT CREATE (t:test {prop: 119035}); +---- ok +-STATEMENT CREATE (t:test {prop: 36662}); +---- ok +-STATEMENT CREATE (t:test {prop: 913847}); +---- ok +-STATEMENT CREATE (t:test {prop: 401365}); +---- ok +-STATEMENT CREATE (t:test {prop: 728145}); +---- ok +-STATEMENT CREATE (t:test {prop: 473138}); +---- ok +-STATEMENT CREATE (t:test {prop: 563741}); +---- ok +-STATEMENT CREATE (t:test {prop: 524006}); +---- ok +-STATEMENT CREATE (t:test {prop: 199594}); +---- ok +-STATEMENT CREATE (t:test {prop: 168380}); +---- ok +-STATEMENT CREATE (t:test {prop: 169586}); +---- ok +-STATEMENT CREATE (t:test {prop: 756167}); +---- ok +-STATEMENT CREATE (t:test {prop: 784157}); +---- ok +-STATEMENT CREATE (t:test {prop: 158250}); +---- ok +-STATEMENT CREATE (t:test {prop: 494790}); +---- ok +-STATEMENT CREATE (t:test {prop: 149213}); +---- ok +-STATEMENT CREATE (t:test {prop: 622319}); +---- ok +-STATEMENT CREATE (t:test {prop: 944810}); +---- ok +-STATEMENT CREATE (t:test {prop: 342944}); +---- ok +-STATEMENT CREATE (t:test {prop: 459362}); +---- ok +-STATEMENT CREATE (t:test {prop: 229484}); +---- ok +-STATEMENT CREATE (t:test {prop: 917750}); +---- ok +-STATEMENT CREATE (t:test {prop: 829341}); +---- ok +-STATEMENT CREATE (t:test {prop: 373863}); +---- ok +-STATEMENT CREATE (t:test {prop: 996571}); +---- ok +-STATEMENT CREATE (t:test {prop: 936865}); +---- ok +-STATEMENT CREATE (t:test {prop: 117341}); +---- ok +-STATEMENT CREATE (t:test {prop: 89840}); +---- ok +-STATEMENT CREATE (t:test {prop: 584878}); +---- ok +-STATEMENT CREATE (t:test {prop: 963264}); +---- ok +-STATEMENT CREATE (t:test {prop: 35876}); +---- ok +-STATEMENT CREATE (t:test {prop: 790269}); +---- ok +-STATEMENT CREATE (t:test {prop: 689318}); +---- ok +-STATEMENT CREATE (t:test {prop: 466514}); +---- ok +-STATEMENT CREATE (t:test {prop: 207648}); +---- ok +-STATEMENT CREATE (t:test {prop: 878515}); +---- ok +-STATEMENT CREATE (t:test {prop: 873148}); +---- ok +-STATEMENT CREATE (t:test {prop: 282336}); +---- ok +-STATEMENT CREATE (t:test {prop: 661977}); +---- ok +-STATEMENT CREATE (t:test {prop: 601447}); +---- ok +-STATEMENT CREATE (t:test {prop: 423923}); +---- ok +-STATEMENT CREATE (t:test {prop: 493758}); +---- ok +-STATEMENT CREATE (t:test {prop: 97248}); +---- ok +-STATEMENT CREATE (t:test {prop: 188544}); +---- ok +-STATEMENT CREATE (t:test {prop: 661029}); +---- ok +-STATEMENT CREATE (t:test {prop: 177454}); +---- ok +-STATEMENT CREATE (t:test {prop: 846594}); +---- ok +-STATEMENT CREATE (t:test {prop: 917765}); +---- ok +-STATEMENT CREATE (t:test {prop: 430198}); +---- ok +-STATEMENT CREATE (t:test {prop: 472782}); +---- ok +-STATEMENT CREATE (t:test {prop: 277496}); +---- ok +-STATEMENT CREATE (t:test {prop: 892947}); +---- ok +-STATEMENT CREATE (t:test {prop: 350680}); +---- ok +-STATEMENT CREATE (t:test {prop: 192537}); +---- ok +-STATEMENT CREATE (t:test {prop: 604275}); +---- ok +-STATEMENT CREATE (t:test {prop: 385010}); +---- ok +-STATEMENT CREATE (t:test {prop: 800777}); +---- ok +-STATEMENT CREATE (t:test {prop: 789539}); +---- ok +-STATEMENT CREATE (t:test {prop: 316219}); +---- ok +-STATEMENT CREATE (t:test {prop: 914284}); +---- ok +-STATEMENT CREATE (t:test {prop: 109671}); +---- ok +-STATEMENT CREATE (t:test {prop: 603698}); +---- ok +-STATEMENT CREATE (t:test {prop: 151788}); +---- ok +-STATEMENT CREATE (t:test {prop: 580370}); +---- ok +-STATEMENT CREATE (t:test {prop: 966356}); +---- ok +-STATEMENT CREATE (t:test {prop: 447462}); +---- ok +-STATEMENT CREATE (t:test {prop: 945952}); +---- ok +-STATEMENT CREATE (t:test {prop: 308910}); +---- ok +-STATEMENT CREATE (t:test {prop: 323157}); +---- ok +-STATEMENT CREATE (t:test {prop: 782356}); +---- ok +-STATEMENT CREATE (t:test {prop: 619997}); +---- ok +-STATEMENT CREATE (t:test {prop: 83642}); +---- ok +-STATEMENT CREATE (t:test {prop: 374130}); +---- ok +-STATEMENT CREATE (t:test {prop: 678027}); +---- ok +-STATEMENT CREATE (t:test {prop: 208642}); +---- ok +-STATEMENT CREATE (t:test {prop: 180867}); +---- ok +-STATEMENT CREATE (t:test {prop: 503995}); +---- ok +-STATEMENT CREATE (t:test {prop: 52282}); +---- ok +-STATEMENT CREATE (t:test {prop: 463868}); +---- ok +-STATEMENT CREATE (t:test {prop: 533871}); +---- ok +-STATEMENT CREATE (t:test {prop: 609757}); +---- ok +-STATEMENT CREATE (t:test {prop: 766928}); +---- ok +-STATEMENT CREATE (t:test {prop: 42696}); +---- ok +-STATEMENT CREATE (t:test {prop: 534012}); +---- ok +-STATEMENT CREATE (t:test {prop: 556457}); +---- ok +-STATEMENT CREATE (t:test {prop: 947047}); +---- ok +-STATEMENT CREATE (t:test {prop: 163399}); +---- ok +-STATEMENT CREATE (t:test {prop: 866119}); +---- ok +-STATEMENT CREATE (t:test {prop: 857906}); +---- ok +-STATEMENT CREATE (t:test {prop: 750833}); +---- ok +-STATEMENT CREATE (t:test {prop: 693179}); +---- ok +-STATEMENT CREATE (t:test {prop: 752093}); +---- ok +-STATEMENT CREATE (t:test {prop: 973377}); +---- ok +-STATEMENT CREATE (t:test {prop: 867522}); +---- ok +-STATEMENT CREATE (t:test {prop: 946239}); +---- ok +-STATEMENT CREATE (t:test {prop: 375702}); +---- ok +-STATEMENT CREATE (t:test {prop: 307686}); +---- ok +-STATEMENT CREATE (t:test {prop: 824166}); +---- ok +-STATEMENT CREATE (t:test {prop: 918538}); +---- ok +-STATEMENT CREATE (t:test {prop: 28183}); +---- ok +-STATEMENT CREATE (t:test {prop: 411943}); +---- ok +-STATEMENT CREATE (t:test {prop: 496057}); +---- ok +-STATEMENT CREATE (t:test {prop: 182602}); +---- ok +-STATEMENT CREATE (t:test {prop: 666875}); +---- ok +-STATEMENT CREATE (t:test {prop: 425493}); +---- ok +-STATEMENT CREATE (t:test {prop: 290955}); +---- ok +-STATEMENT CREATE (t:test {prop: 381654}); +---- ok +-STATEMENT CREATE (t:test {prop: 132418}); +---- ok +-STATEMENT CREATE (t:test {prop: 308473}); +---- ok +-STATEMENT CREATE (t:test {prop: 63984}); +---- ok +-STATEMENT CREATE (t:test {prop: 95413}); +---- ok +-STATEMENT CREATE (t:test {prop: 794602}); +---- ok +-STATEMENT CREATE (t:test {prop: 984722}); +---- ok +-STATEMENT CREATE (t:test {prop: 848659}); +---- ok +-STATEMENT CREATE (t:test {prop: 984993}); +---- ok +-STATEMENT CREATE (t:test {prop: 41855}); +---- ok +-STATEMENT CREATE (t:test {prop: 972406}); +---- ok +-STATEMENT CREATE (t:test {prop: 669539}); +---- ok +-STATEMENT CREATE (t:test {prop: 640841}); +---- ok +-STATEMENT CREATE (t:test {prop: 357560}); +---- ok +-STATEMENT CREATE (t:test {prop: 176977}); +---- ok +-STATEMENT CREATE (t:test {prop: 759494}); +---- ok +-STATEMENT CREATE (t:test {prop: 664436}); +---- ok +-STATEMENT CREATE (t:test {prop: 279433}); +---- ok +-STATEMENT CREATE (t:test {prop: 946403}); +---- ok +-STATEMENT CREATE (t:test {prop: 818540}); +---- ok +-STATEMENT CREATE (t:test {prop: 348110}); +---- ok +-STATEMENT CREATE (t:test {prop: 46897}); +---- ok +-STATEMENT CREATE (t:test {prop: 86680}); +---- ok +-STATEMENT CREATE (t:test {prop: 440232}); +---- ok +-STATEMENT CREATE (t:test {prop: 725682}); +---- ok +-STATEMENT CREATE (t:test {prop: 379292}); +---- ok +-STATEMENT CREATE (t:test {prop: 822133}); +---- ok +-STATEMENT CREATE (t:test {prop: 601921}); +---- ok +-STATEMENT CREATE (t:test {prop: 442136}); +---- ok +-STATEMENT CREATE (t:test {prop: 803719}); +---- ok +-STATEMENT CREATE (t:test {prop: 596952}); +---- ok +-STATEMENT CREATE (t:test {prop: 575255}); +---- ok +-STATEMENT CREATE (t:test {prop: 725852}); +---- ok +-STATEMENT CREATE (t:test {prop: 740932}); +---- ok +-STATEMENT CREATE (t:test {prop: 548571}); +---- ok +-STATEMENT CREATE (t:test {prop: 926797}); +---- ok +-STATEMENT CREATE (t:test {prop: 718754}); +---- ok +-STATEMENT CREATE (t:test {prop: 273863}); +---- ok +-STATEMENT CREATE (t:test {prop: 195058}); +---- ok +-STATEMENT CREATE (t:test {prop: 924317}); +---- ok +-STATEMENT CREATE (t:test {prop: 762445}); +---- ok +-STATEMENT CREATE (t:test {prop: 971701}); +---- ok +-STATEMENT CREATE (t:test {prop: 937133}); +---- ok +-STATEMENT CREATE (t:test {prop: 560674}); +---- ok +-STATEMENT CREATE (t:test {prop: 989858}); +---- ok +-STATEMENT CREATE (t:test {prop: 145564}); +---- ok +-STATEMENT CREATE (t:test {prop: 771183}); +---- ok +-STATEMENT CREATE (t:test {prop: 390292}); +---- ok +-STATEMENT CREATE (t:test {prop: 343498}); +---- ok +-STATEMENT CREATE (t:test {prop: 241564}); +---- ok +-STATEMENT CREATE (t:test {prop: 630199}); +---- ok +-STATEMENT CREATE (t:test {prop: 574455}); +---- ok +-STATEMENT CREATE (t:test {prop: 887844}); +---- ok +-STATEMENT CREATE (t:test {prop: 290871}); +---- ok +-STATEMENT CREATE (t:test {prop: 784755}); +---- ok +-STATEMENT CREATE (t:test {prop: 731621}); +---- ok +-STATEMENT CREATE (t:test {prop: 882779}); +---- ok +-STATEMENT CREATE (t:test {prop: 499928}); +---- ok +-STATEMENT CREATE (t:test {prop: 100140}); +---- ok +-STATEMENT CREATE (t:test {prop: 793657}); +---- ok +-STATEMENT CREATE (t:test {prop: 800341}); +---- ok +-STATEMENT CREATE (t:test {prop: 666248}); +---- ok +-STATEMENT CREATE (t:test {prop: 642830}); +---- ok +-STATEMENT CREATE (t:test {prop: 975858}); +---- ok +-STATEMENT CREATE (t:test {prop: 181480}); +---- ok +-STATEMENT CREATE (t:test {prop: 360578}); +---- ok +-STATEMENT CREATE (t:test {prop: 623774}); +---- ok +-STATEMENT CREATE (t:test {prop: 754089}); +---- ok +-STATEMENT CREATE (t:test {prop: 730315}); +---- ok +-STATEMENT CREATE (t:test {prop: 598866}); +---- ok +-STATEMENT CREATE (t:test {prop: 297486}); +---- ok +-STATEMENT CREATE (t:test {prop: 515364}); +---- ok +-STATEMENT CREATE (t:test {prop: 457203}); +---- ok +-STATEMENT CREATE (t:test {prop: 288145}); +---- ok +-STATEMENT CREATE (t:test {prop: 18269}); +---- ok +-STATEMENT CREATE (t:test {prop: 403221}); +---- ok +-STATEMENT CREATE (t:test {prop: 296323}); +---- ok +-STATEMENT CREATE (t:test {prop: 847442}); +---- ok +-STATEMENT CREATE (t:test {prop: 884672}); +---- ok +-STATEMENT CREATE (t:test {prop: 707993}); +---- ok +-STATEMENT CREATE (t:test {prop: 891295}); +---- ok +-STATEMENT CREATE (t:test {prop: 699504}); +---- ok +-STATEMENT CREATE (t:test {prop: 865419}); +---- ok +-STATEMENT CREATE (t:test {prop: 688655}); +---- ok +-STATEMENT CREATE (t:test {prop: 957855}); +---- ok +-STATEMENT CREATE (t:test {prop: 421045}); +---- ok +-STATEMENT CREATE (t:test {prop: 824495}); +---- ok +-STATEMENT CREATE (t:test {prop: 604712}); +---- ok +-STATEMENT CREATE (t:test {prop: 772213}); +---- ok +-STATEMENT CREATE (t:test {prop: 960662}); +---- ok +-STATEMENT CREATE (t:test {prop: 913260}); +---- ok +-STATEMENT CREATE (t:test {prop: 353435}); +---- ok +-STATEMENT CREATE (t:test {prop: 821275}); +---- ok +-STATEMENT CREATE (t:test {prop: 882853}); +---- ok +-STATEMENT CREATE (t:test {prop: 612757}); +---- ok +-STATEMENT CREATE (t:test {prop: 689300}); +---- ok +-STATEMENT CREATE (t:test {prop: 782492}); +---- ok +-STATEMENT CREATE (t:test {prop: 79561}); +---- ok +-STATEMENT CREATE (t:test {prop: 611900}); +---- ok +-STATEMENT CREATE (t:test {prop: 996048}); +---- ok +-STATEMENT CREATE (t:test {prop: 402195}); +---- ok +-STATEMENT CREATE (t:test {prop: 354230}); +---- ok +-STATEMENT CREATE (t:test {prop: 177052}); +---- ok +-STATEMENT CREATE (t:test {prop: 746612}); +---- ok +-STATEMENT CREATE (t:test {prop: 53486}); +---- ok +-STATEMENT CREATE (t:test {prop: 201797}); +---- ok +-STATEMENT CREATE (t:test {prop: 706436}); +---- ok +-STATEMENT CREATE (t:test {prop: 650660}); +---- ok +-STATEMENT CREATE (t:test {prop: 213356}); +---- ok +-STATEMENT CREATE (t:test {prop: 341669}); +---- ok +-STATEMENT CREATE (t:test {prop: 775240}); +---- ok +-STATEMENT CREATE (t:test {prop: 591689}); +---- ok +-STATEMENT CREATE (t:test {prop: 343934}); +---- ok +-STATEMENT CREATE (t:test {prop: 917287}); +---- ok +-STATEMENT CREATE (t:test {prop: 417094}); +---- ok +-STATEMENT CREATE (t:test {prop: 926024}); +---- ok +-STATEMENT CREATE (t:test {prop: 379557}); +---- ok +-STATEMENT CREATE (t:test {prop: 460171}); +---- ok +-STATEMENT CREATE (t:test {prop: 805947}); +---- ok +-STATEMENT CREATE (t:test {prop: 625604}); +---- ok +-STATEMENT CREATE (t:test {prop: 959950}); +---- ok +-STATEMENT CREATE (t:test {prop: 117427}); +---- ok +-STATEMENT CREATE (t:test {prop: 77988}); +---- ok +-STATEMENT CREATE (t:test {prop: 830563}); +---- ok +-STATEMENT CREATE (t:test {prop: 124519}); +---- ok +-STATEMENT CREATE (t:test {prop: 794866}); +---- ok +-STATEMENT CREATE (t:test {prop: 609511}); +---- ok +-STATEMENT CREATE (t:test {prop: 379464}); +---- ok +-STATEMENT CREATE (t:test {prop: 867661}); +---- ok +-STATEMENT CREATE (t:test {prop: 678052}); +---- ok +-STATEMENT CREATE (t:test {prop: 862403}); +---- ok +-STATEMENT CREATE (t:test {prop: 202885}); +---- ok +-STATEMENT CREATE (t:test {prop: 686155}); +---- ok +-STATEMENT CREATE (t:test {prop: 576610}); +---- ok +-STATEMENT CREATE (t:test {prop: 893882}); +---- ok +-STATEMENT CREATE (t:test {prop: 811107}); +---- ok +-STATEMENT CREATE (t:test {prop: 623078}); +---- ok +-STATEMENT CREATE (t:test {prop: 528309}); +---- ok +-STATEMENT CREATE (t:test {prop: 532005}); +---- ok +-STATEMENT CREATE (t:test {prop: 562504}); +---- ok +-STATEMENT CREATE (t:test {prop: 20749}); +---- ok +-STATEMENT CREATE (t:test {prop: 182506}); +---- ok +-STATEMENT CREATE (t:test {prop: 865830}); +---- ok +-STATEMENT CREATE (t:test {prop: 887855}); +---- ok +-STATEMENT CREATE (t:test {prop: 194476}); +---- ok +-STATEMENT CREATE (t:test {prop: 543811}); +---- ok +-STATEMENT CREATE (t:test {prop: 351140}); +---- ok +-STATEMENT CREATE (t:test {prop: 444750}); +---- ok +-STATEMENT CREATE (t:test {prop: 608035}); +---- ok +-STATEMENT CREATE (t:test {prop: 767205}); +---- ok +-STATEMENT CREATE (t:test {prop: 306011}); +---- ok +-STATEMENT CREATE (t:test {prop: 434416}); +---- ok +-STATEMENT CREATE (t:test {prop: 997025}); +---- ok +-STATEMENT CREATE (t:test {prop: 997653}); +---- ok +-STATEMENT CREATE (t:test {prop: 267845}); +---- ok +-STATEMENT CREATE (t:test {prop: 110506}); +---- ok +-STATEMENT CREATE (t:test {prop: 482470}); +---- ok +-STATEMENT CREATE (t:test {prop: 862405}); +---- ok +-STATEMENT CREATE (t:test {prop: 172728}); +---- ok +-STATEMENT CREATE (t:test {prop: 379501}); +---- ok +-STATEMENT CREATE (t:test {prop: 103252}); +---- ok +-STATEMENT CREATE (t:test {prop: 375060}); +---- ok +-STATEMENT CREATE (t:test {prop: 736589}); +---- ok +-STATEMENT CREATE (t:test {prop: 382796}); +---- ok +-STATEMENT CREATE (t:test {prop: 416407}); +---- ok +-STATEMENT CREATE (t:test {prop: 925164}); +---- ok +-STATEMENT CREATE (t:test {prop: 898972}); +---- ok +-STATEMENT CREATE (t:test {prop: 274836}); +---- ok +-STATEMENT CREATE (t:test {prop: 333660}); +---- ok +-STATEMENT CREATE (t:test {prop: 944898}); +---- ok +-STATEMENT CREATE (t:test {prop: 807119}); +---- ok +-STATEMENT CREATE (t:test {prop: 746836}); +---- ok +-STATEMENT CREATE (t:test {prop: 566272}); +---- ok +-STATEMENT CREATE (t:test {prop: 226547}); +---- ok +-STATEMENT CREATE (t:test {prop: 958053}); +---- ok +-STATEMENT CREATE (t:test {prop: 14994}); +---- ok +-STATEMENT CREATE (t:test {prop: 454955}); +---- ok +-STATEMENT CREATE (t:test {prop: 678624}); +---- ok +-STATEMENT CREATE (t:test {prop: 731055}); +---- ok +-STATEMENT CREATE (t:test {prop: 618740}); +---- ok +-STATEMENT CREATE (t:test {prop: 734344}); +---- ok +-STATEMENT CREATE (t:test {prop: 181260}); +---- ok +-STATEMENT CREATE (t:test {prop: 260403}); +---- ok +-STATEMENT CREATE (t:test {prop: 109624}); +---- ok +-STATEMENT CREATE (t:test {prop: 339293}); +---- ok +-STATEMENT CREATE (t:test {prop: 614183}); +---- ok +-STATEMENT CREATE (t:test {prop: 469785}); +---- ok +-STATEMENT CREATE (t:test {prop: 806549}); +---- ok +-STATEMENT CREATE (t:test {prop: 444817}); +---- ok +-STATEMENT CREATE (t:test {prop: 20529}); +---- ok +-STATEMENT CREATE (t:test {prop: 519104}); +---- ok +-STATEMENT CREATE (t:test {prop: 282361}); +---- ok +-STATEMENT CREATE (t:test {prop: 731859}); +---- ok +-STATEMENT CREATE (t:test {prop: 452853}); +---- ok +-STATEMENT CREATE (t:test {prop: 560166}); +---- ok +-STATEMENT CREATE (t:test {prop: 376460}); +---- ok +-STATEMENT CREATE (t:test {prop: 555476}); +---- ok +-STATEMENT CREATE (t:test {prop: 645006}); +---- ok +-STATEMENT CREATE (t:test {prop: 713476}); +---- ok +-STATEMENT CREATE (t:test {prop: 986185}); +---- ok +-STATEMENT CREATE (t:test {prop: 584258}); +---- ok +-STATEMENT CREATE (t:test {prop: 541659}); +---- ok +-STATEMENT CREATE (t:test {prop: 357140}); +---- ok +-STATEMENT CREATE (t:test {prop: 968366}); +---- ok +-STATEMENT CREATE (t:test {prop: 907531}); +---- ok +-STATEMENT CREATE (t:test {prop: 575118}); +---- ok +-STATEMENT CREATE (t:test {prop: 729321}); +---- ok +-STATEMENT CREATE (t:test {prop: 822549}); +---- ok +-STATEMENT CREATE (t:test {prop: 263313}); +---- ok +-STATEMENT CREATE (t:test {prop: 222920}); +---- ok +-STATEMENT CREATE (t:test {prop: 436232}); +---- ok +-STATEMENT CREATE (t:test {prop: 815223}); +---- ok +-STATEMENT CREATE (t:test {prop: 581658}); +---- ok +-STATEMENT CREATE (t:test {prop: 56211}); +---- ok +-STATEMENT CREATE (t:test {prop: 77114}); +---- ok +-STATEMENT CREATE (t:test {prop: 704511}); +---- ok +-STATEMENT CREATE (t:test {prop: 826050}); +---- ok +-STATEMENT CREATE (t:test {prop: 966950}); +---- ok +-STATEMENT CREATE (t:test {prop: 215319}); +---- ok +-STATEMENT CREATE (t:test {prop: 38596}); +---- ok +-STATEMENT CREATE (t:test {prop: 136442}); +---- ok +-STATEMENT CREATE (t:test {prop: 159543}); +---- ok +-STATEMENT CREATE (t:test {prop: 485110}); +---- ok +-STATEMENT CREATE (t:test {prop: 587401}); +---- ok +-STATEMENT CREATE (t:test {prop: 129681}); +---- ok +-STATEMENT CREATE (t:test {prop: 985842}); +---- ok +-STATEMENT CREATE (t:test {prop: 97361}); +---- ok +-STATEMENT CREATE (t:test {prop: 609526}); +---- ok +-STATEMENT CREATE (t:test {prop: 299476}); +---- ok +-STATEMENT CREATE (t:test {prop: 488350}); +---- ok +-STATEMENT CREATE (t:test {prop: 784094}); +---- ok +-STATEMENT CREATE (t:test {prop: 852058}); +---- ok +-STATEMENT CREATE (t:test {prop: 818485}); +---- ok +-STATEMENT CREATE (t:test {prop: 490751}); +---- ok +-STATEMENT CREATE (t:test {prop: 180984}); +---- ok +-STATEMENT CREATE (t:test {prop: 576227}); +---- ok +-STATEMENT CREATE (t:test {prop: 35566}); +---- ok +-STATEMENT CREATE (t:test {prop: 857580}); +---- ok +-STATEMENT CREATE (t:test {prop: 981080}); +---- ok +-STATEMENT CREATE (t:test {prop: 146960}); +---- ok +-STATEMENT CREATE (t:test {prop: 7607}); +---- ok +-STATEMENT CREATE (t:test {prop: 233270}); +---- ok +-STATEMENT CREATE (t:test {prop: 247475}); +---- ok +-STATEMENT CREATE (t:test {prop: 19993}); +---- ok +-STATEMENT CREATE (t:test {prop: 611932}); +---- ok +-STATEMENT CREATE (t:test {prop: 666809}); +---- ok +-STATEMENT CREATE (t:test {prop: 729417}); +---- ok +-STATEMENT CREATE (t:test {prop: 867707}); +---- ok +-STATEMENT CREATE (t:test {prop: 925482}); +---- ok +-STATEMENT CREATE (t:test {prop: 642584}); +---- ok +-STATEMENT CREATE (t:test {prop: 424468}); +---- ok +-STATEMENT CREATE (t:test {prop: 547207}); +---- ok +-STATEMENT CREATE (t:test {prop: 378535}); +---- ok +-STATEMENT CREATE (t:test {prop: 752099}); +---- ok +-STATEMENT CREATE (t:test {prop: 524482}); +---- ok +-STATEMENT CREATE (t:test {prop: 596}); +---- ok +-STATEMENT CREATE (t:test {prop: 732524}); +---- ok +-STATEMENT CREATE (t:test {prop: 73309}); +---- ok +-STATEMENT CREATE (t:test {prop: 828540}); +---- ok +-STATEMENT CREATE (t:test {prop: 267834}); +---- ok +-STATEMENT CREATE (t:test {prop: 633266}); +---- ok +-STATEMENT CREATE (t:test {prop: 255758}); +---- ok +-STATEMENT CREATE (t:test {prop: 873120}); +---- ok +-STATEMENT CREATE (t:test {prop: 122487}); +---- ok +-STATEMENT CREATE (t:test {prop: 378551}); +---- ok +-STATEMENT CREATE (t:test {prop: 165429}); +---- ok +-STATEMENT CREATE (t:test {prop: 696183}); +---- ok +-STATEMENT CREATE (t:test {prop: 247425}); +---- ok +-STATEMENT CREATE (t:test {prop: 742913}); +---- ok +-STATEMENT CREATE (t:test {prop: 480347}); +---- ok +-STATEMENT CREATE (t:test {prop: 806724}); +---- ok +-STATEMENT CREATE (t:test {prop: 429312}); +---- ok +-STATEMENT CREATE (t:test {prop: 19824}); +---- ok +-STATEMENT CREATE (t:test {prop: 663043}); +---- ok +-STATEMENT CREATE (t:test {prop: 113948}); +---- ok +-STATEMENT CREATE (t:test {prop: 893308}); +---- ok +-STATEMENT CREATE (t:test {prop: 50865}); +---- ok +-STATEMENT CREATE (t:test {prop: 890825}); +---- ok +-STATEMENT CREATE (t:test {prop: 978787}); +---- ok +-STATEMENT CREATE (t:test {prop: 675807}); +---- ok +-STATEMENT CREATE (t:test {prop: 881666}); +---- ok +-STATEMENT CREATE (t:test {prop: 326618}); +---- ok +-STATEMENT CREATE (t:test {prop: 798750}); +---- ok +-STATEMENT CREATE (t:test {prop: 330325}); +---- ok +-STATEMENT CREATE (t:test {prop: 548923}); +---- ok +-STATEMENT CREATE (t:test {prop: 962895}); +---- ok +-STATEMENT CREATE (t:test {prop: 721988}); +---- ok +-STATEMENT CREATE (t:test {prop: 714420}); +---- ok +-STATEMENT CREATE (t:test {prop: 568691}); +---- ok +-STATEMENT CREATE (t:test {prop: 53991}); +---- ok +-STATEMENT CREATE (t:test {prop: 75556}); +---- ok +-STATEMENT CREATE (t:test {prop: 528767}); +---- ok +-STATEMENT CREATE (t:test {prop: 353057}); +---- ok +-STATEMENT CREATE (t:test {prop: 410349}); +---- ok +-STATEMENT CREATE (t:test {prop: 486792}); +---- ok +-STATEMENT CREATE (t:test {prop: 232518}); +---- ok +-STATEMENT CREATE (t:test {prop: 297816}); +---- ok +-STATEMENT CREATE (t:test {prop: 936748}); +---- ok +-STATEMENT CREATE (t:test {prop: 484031}); +---- ok +-STATEMENT CREATE (t:test {prop: 546119}); +---- ok +-STATEMENT CREATE (t:test {prop: 807327}); +---- ok +-STATEMENT CREATE (t:test {prop: 481030}); +---- ok +-STATEMENT CREATE (t:test {prop: 96215}); +---- ok +-STATEMENT CREATE (t:test {prop: 145337}); +---- ok +-STATEMENT CREATE (t:test {prop: 272910}); +---- ok +-STATEMENT CREATE (t:test {prop: 47213}); +---- ok +-STATEMENT CREATE (t:test {prop: 38601}); +---- ok +-STATEMENT CREATE (t:test {prop: 24096}); +---- ok +-STATEMENT CREATE (t:test {prop: 736463}); +---- ok +-STATEMENT CREATE (t:test {prop: 53392}); +---- ok +-STATEMENT CREATE (t:test {prop: 820960}); +---- ok +-STATEMENT CREATE (t:test {prop: 694077}); +---- ok +-STATEMENT CREATE (t:test {prop: 383392}); +---- ok +-STATEMENT CREATE (t:test {prop: 462991}); +---- ok +-STATEMENT CREATE (t:test {prop: 932052}); +---- ok +-STATEMENT CREATE (t:test {prop: 578970}); +---- ok +-STATEMENT CREATE (t:test {prop: 510414}); +---- ok +-STATEMENT CREATE (t:test {prop: 934489}); +---- ok +-STATEMENT CREATE (t:test {prop: 641137}); +---- ok +-STATEMENT CREATE (t:test {prop: 204438}); +---- ok +-STATEMENT CREATE (t:test {prop: 590163}); +---- ok +-STATEMENT CREATE (t:test {prop: 81716}); +---- ok +-STATEMENT CREATE (t:test {prop: 875479}); +---- ok +-STATEMENT CREATE (t:test {prop: 919029}); +---- ok +-STATEMENT CREATE (t:test {prop: 424524}); +---- ok +-STATEMENT CREATE (t:test {prop: 990364}); +---- ok +-STATEMENT CREATE (t:test {prop: 907586}); +---- ok +-STATEMENT CREATE (t:test {prop: 153718}); +---- ok +-STATEMENT CREATE (t:test {prop: 765407}); +---- ok +-STATEMENT CREATE (t:test {prop: 161374}); +---- ok +-STATEMENT CREATE (t:test {prop: 320223}); +---- ok +-STATEMENT CREATE (t:test {prop: 427885}); +---- ok +-STATEMENT CREATE (t:test {prop: 620520}); +---- ok +-STATEMENT CREATE (t:test {prop: 796580}); +---- ok +-STATEMENT CREATE (t:test {prop: 72936}); +---- ok +-STATEMENT CREATE (t:test {prop: 515941}); +---- ok +-STATEMENT CREATE (t:test {prop: 114339}); +---- ok +-STATEMENT CREATE (t:test {prop: 992434}); +---- ok +-STATEMENT CREATE (t:test {prop: 985071}); +---- ok +-STATEMENT CREATE (t:test {prop: 685110}); +---- ok +-STATEMENT CREATE (t:test {prop: 735334}); +---- ok +-STATEMENT CREATE (t:test {prop: 488791}); +---- ok +-STATEMENT CREATE (t:test {prop: 417088}); +---- ok +-STATEMENT CREATE (t:test {prop: 26326}); +---- ok +-STATEMENT CREATE (t:test {prop: 174873}); +---- ok +-STATEMENT CREATE (t:test {prop: 792943}); +---- ok +-STATEMENT CREATE (t:test {prop: 524819}); +---- ok +-STATEMENT CREATE (t:test {prop: 561432}); +---- ok +-STATEMENT CREATE (t:test {prop: 449142}); +---- ok +-STATEMENT CREATE (t:test {prop: 971528}); +---- ok +-STATEMENT CREATE (t:test {prop: 767111}); +---- ok +-STATEMENT CREATE (t:test {prop: 192551}); +---- ok +-STATEMENT CREATE (t:test {prop: 524116}); +---- ok +-STATEMENT CREATE (t:test {prop: 238644}); +---- ok +-STATEMENT CREATE (t:test {prop: 694519}); +---- ok +-STATEMENT CREATE (t:test {prop: 635424}); +---- ok +-STATEMENT CREATE (t:test {prop: 265033}); +---- ok +-STATEMENT CREATE (t:test {prop: 486429}); +---- ok +-STATEMENT CREATE (t:test {prop: 799654}); +---- ok +-STATEMENT CREATE (t:test {prop: 288817}); +---- ok +-STATEMENT CREATE (t:test {prop: 207301}); +---- ok +-STATEMENT CREATE (t:test {prop: 271112}); +---- ok +-STATEMENT CREATE (t:test {prop: 378227}); +---- ok +-STATEMENT CREATE (t:test {prop: 572316}); +---- ok +-STATEMENT CREATE (t:test {prop: 763946}); +---- ok +-STATEMENT CREATE (t:test {prop: 237573}); +---- ok +-STATEMENT CREATE (t:test {prop: 904129}); +---- ok +-STATEMENT CREATE (t:test {prop: 385138}); +---- ok +-STATEMENT CREATE (t:test {prop: 560352}); +---- ok +-STATEMENT CREATE (t:test {prop: 87403}); +---- ok +-STATEMENT CREATE (t:test {prop: 722024}); +---- ok +-STATEMENT CREATE (t:test {prop: 794545}); +---- ok +-STATEMENT CREATE (t:test {prop: 136330}); +---- ok +-STATEMENT CREATE (t:test {prop: 234799}); +---- ok +-STATEMENT CREATE (t:test {prop: 518494}); +---- ok +-STATEMENT CREATE (t:test {prop: 652197}); +---- ok +-STATEMENT CREATE (t:test {prop: 26521}); +---- ok +-STATEMENT CREATE (t:test {prop: 434374}); +---- ok +-STATEMENT CREATE (t:test {prop: 226134}); +---- ok +-STATEMENT CREATE (t:test {prop: 886636}); +---- ok +-STATEMENT CREATE (t:test {prop: 847680}); +---- ok +-STATEMENT CREATE (t:test {prop: 603636}); +---- ok +-STATEMENT CREATE (t:test {prop: 438088}); +---- ok +-STATEMENT CREATE (t:test {prop: 680585}); +---- ok +-STATEMENT CREATE (t:test {prop: 176380}); +---- ok +-STATEMENT CREATE (t:test {prop: 98224}); +---- ok +-STATEMENT CREATE (t:test {prop: 441352}); +---- ok +-STATEMENT CREATE (t:test {prop: 237456}); +---- ok +-STATEMENT CREATE (t:test {prop: 421210}); +---- ok +-STATEMENT CREATE (t:test {prop: 83294}); +---- ok +-STATEMENT CREATE (t:test {prop: 868465}); +---- ok +-STATEMENT CREATE (t:test {prop: 261118}); +---- ok +-STATEMENT CREATE (t:test {prop: 207167}); +---- ok +-STATEMENT CREATE (t:test {prop: 401708}); +---- ok +-STATEMENT CREATE (t:test {prop: 490041}); +---- ok +-STATEMENT CREATE (t:test {prop: 241747}); +---- ok +-STATEMENT CREATE (t:test {prop: 960319}); +---- ok +-STATEMENT CREATE (t:test {prop: 54905}); +---- ok +-STATEMENT CREATE (t:test {prop: 526338}); +---- ok +-STATEMENT CREATE (t:test {prop: 856715}); +---- ok +-STATEMENT CREATE (t:test {prop: 533682}); +---- ok +-STATEMENT CREATE (t:test {prop: 849122}); +---- ok +-STATEMENT CREATE (t:test {prop: 482955}); +---- ok +-STATEMENT CREATE (t:test {prop: 921477}); +---- ok +-STATEMENT CREATE (t:test {prop: 182922}); +---- ok +-STATEMENT CREATE (t:test {prop: 182473}); +---- ok +-STATEMENT CREATE (t:test {prop: 107878}); +---- ok +-STATEMENT CREATE (t:test {prop: 967871}); +---- ok +-STATEMENT CREATE (t:test {prop: 760205}); +---- ok +-STATEMENT CREATE (t:test {prop: 520378}); +---- ok +-STATEMENT CREATE (t:test {prop: 211575}); +---- ok +-STATEMENT CREATE (t:test {prop: 840357}); +---- ok +-STATEMENT CREATE (t:test {prop: 977452}); +---- ok +-STATEMENT CREATE (t:test {prop: 180476}); +---- ok +-STATEMENT CREATE (t:test {prop: 954486}); +---- ok +-STATEMENT CREATE (t:test {prop: 932618}); +---- ok +-STATEMENT CREATE (t:test {prop: 562875}); +---- ok +-STATEMENT CREATE (t:test {prop: 845045}); +---- ok +-STATEMENT CREATE (t:test {prop: 281335}); +---- ok +-STATEMENT CREATE (t:test {prop: 765181}); +---- ok +-STATEMENT CREATE (t:test {prop: 846359}); +---- ok +-STATEMENT CREATE (t:test {prop: 117705}); +---- ok +-STATEMENT CREATE (t:test {prop: 986151}); +---- ok +-STATEMENT CREATE (t:test {prop: 999689}); +---- ok +-STATEMENT CREATE (t:test {prop: 970892}); +---- ok +-STATEMENT CREATE (t:test {prop: 191845}); +---- ok +-STATEMENT CREATE (t:test {prop: 549040}); +---- ok +-STATEMENT CREATE (t:test {prop: 312422}); +---- ok +-STATEMENT CREATE (t:test {prop: 646534}); +---- ok +-STATEMENT CREATE (t:test {prop: 607389}); +---- ok +-STATEMENT CREATE (t:test {prop: 369768}); +---- ok +-STATEMENT CREATE (t:test {prop: 527236}); +---- ok +-STATEMENT CREATE (t:test {prop: 118689}); +---- ok +-STATEMENT CREATE (t:test {prop: 815152}); +---- ok +-STATEMENT CREATE (t:test {prop: 166266}); +---- ok +-STATEMENT CREATE (t:test {prop: 758295}); +---- ok +-STATEMENT CREATE (t:test {prop: 53444}); +---- ok +-STATEMENT CREATE (t:test {prop: 941465}); +---- ok +-STATEMENT CREATE (t:test {prop: 632354}); +---- ok +-STATEMENT CREATE (t:test {prop: 226626}); +---- ok +-STATEMENT CREATE (t:test {prop: 145877}); +---- ok +-STATEMENT CREATE (t:test {prop: 768625}); +---- ok +-STATEMENT CREATE (t:test {prop: 875349}); +---- ok +-STATEMENT CREATE (t:test {prop: 145139}); +---- ok +-STATEMENT CREATE (t:test {prop: 533693}); +---- ok +-STATEMENT CREATE (t:test {prop: 278336}); +---- ok +-STATEMENT CREATE (t:test {prop: 236563}); +---- ok +-STATEMENT CREATE (t:test {prop: 411496}); +---- ok +-STATEMENT CREATE (t:test {prop: 908647}); +---- ok +-STATEMENT CREATE (t:test {prop: 436369}); +---- ok +-STATEMENT CREATE (t:test {prop: 494040}); +---- ok +-STATEMENT CREATE (t:test {prop: 643418}); +---- ok +-STATEMENT CREATE (t:test {prop: 681386}); +---- ok +-STATEMENT CREATE (t:test {prop: 727120}); +---- ok +-STATEMENT CREATE (t:test {prop: 339417}); +---- ok +-STATEMENT CREATE (t:test {prop: 145833}); +---- ok +-STATEMENT CREATE (t:test {prop: 879067}); +---- ok +-STATEMENT CREATE (t:test {prop: 516244}); +---- ok +-STATEMENT CREATE (t:test {prop: 376840}); +---- ok +-STATEMENT CREATE (t:test {prop: 708507}); +---- ok +-STATEMENT CREATE (t:test {prop: 387973}); +---- ok +-STATEMENT CREATE (t:test {prop: 961936}); +---- ok +-STATEMENT CREATE (t:test {prop: 852695}); +---- ok +-STATEMENT CREATE (t:test {prop: 49636}); +---- ok +-STATEMENT CREATE (t:test {prop: 3658}); +---- ok +-STATEMENT CREATE (t:test {prop: 794484}); +---- ok +-STATEMENT CREATE (t:test {prop: 633562}); +---- ok +-STATEMENT CREATE (t:test {prop: 236301}); +---- ok +-STATEMENT CREATE (t:test {prop: 125616}); +---- ok +-STATEMENT CREATE (t:test {prop: 42370}); +---- ok +-STATEMENT CREATE (t:test {prop: 585513}); +---- ok +-STATEMENT CREATE (t:test {prop: 653018}); +---- ok +-STATEMENT CREATE (t:test {prop: 772558}); +---- ok +-STATEMENT CREATE (t:test {prop: 236196}); +---- ok +-STATEMENT CREATE (t:test {prop: 920098}); +---- ok +-STATEMENT CREATE (t:test {prop: 398197}); +---- ok +-STATEMENT CREATE (t:test {prop: 512904}); +---- ok +-STATEMENT CREATE (t:test {prop: 305979}); +---- ok +-STATEMENT CREATE (t:test {prop: 542731}); +---- ok +-STATEMENT CREATE (t:test {prop: 442768}); +---- ok +-STATEMENT CREATE (t:test {prop: 18977}); +---- ok +-STATEMENT CREATE (t:test {prop: 123909}); +---- ok +-STATEMENT CREATE (t:test {prop: 894292}); +---- ok +-STATEMENT CREATE (t:test {prop: 328129}); +---- ok +-STATEMENT CREATE (t:test {prop: 245344}); +---- ok +-STATEMENT CREATE (t:test {prop: 459748}); +---- ok +-STATEMENT CREATE (t:test {prop: 83350}); +---- ok +-STATEMENT CREATE (t:test {prop: 217092}); +---- ok +-STATEMENT CREATE (t:test {prop: 63922}); +---- ok +-STATEMENT CREATE (t:test {prop: 736860}); +---- ok +-STATEMENT CREATE (t:test {prop: 282672}); +---- ok +-STATEMENT CREATE (t:test {prop: 977398}); +---- ok +-STATEMENT CREATE (t:test {prop: 749780}); +---- ok +-STATEMENT CREATE (t:test {prop: 877618}); +---- ok +-STATEMENT CREATE (t:test {prop: 10013}); +---- ok +-STATEMENT CREATE (t:test {prop: 61284}); +---- ok +-STATEMENT CREATE (t:test {prop: 872606}); +---- ok +-STATEMENT CREATE (t:test {prop: 462563}); +---- ok +-STATEMENT CREATE (t:test {prop: 477394}); +---- ok +-STATEMENT CREATE (t:test {prop: 824152}); +---- ok +-STATEMENT CREATE (t:test {prop: 198770}); +---- ok +-STATEMENT CREATE (t:test {prop: 211767}); +---- ok +-STATEMENT CREATE (t:test {prop: 822301}); +---- ok +-STATEMENT CREATE (t:test {prop: 756963}); +---- ok +-STATEMENT CREATE (t:test {prop: 211139}); +---- ok +-STATEMENT CREATE (t:test {prop: 10637}); +---- ok +-STATEMENT CREATE (t:test {prop: 67713}); +---- ok +-STATEMENT CREATE (t:test {prop: 194608}); +---- ok +-STATEMENT CREATE (t:test {prop: 511767}); +---- ok +-STATEMENT CREATE (t:test {prop: 978453}); +---- ok +-STATEMENT CREATE (t:test {prop: 901577}); +---- ok +-STATEMENT CREATE (t:test {prop: 529752}); +---- ok +-STATEMENT CREATE (t:test {prop: 777602}); +---- ok +-STATEMENT CREATE (t:test {prop: 567391}); +---- ok +-STATEMENT CREATE (t:test {prop: 318253}); +---- ok +-STATEMENT CREATE (t:test {prop: 287934}); +---- ok +-STATEMENT CREATE (t:test {prop: 827510}); +---- ok +-STATEMENT CREATE (t:test {prop: 70079}); +---- ok +-STATEMENT CREATE (t:test {prop: 247585}); +---- ok +-STATEMENT CREATE (t:test {prop: 60292}); +---- ok +-STATEMENT CREATE (t:test {prop: 146575}); +---- ok +-STATEMENT CREATE (t:test {prop: 8995}); +---- ok +-STATEMENT CREATE (t:test {prop: 114630}); +---- ok +-STATEMENT CREATE (t:test {prop: 766173}); +---- ok +-STATEMENT CREATE (t:test {prop: 397233}); +---- ok +-STATEMENT CREATE (t:test {prop: 522397}); +---- ok +-STATEMENT CREATE (t:test {prop: 800474}); +---- ok +-STATEMENT CREATE (t:test {prop: 397750}); +---- ok +-STATEMENT CREATE (t:test {prop: 340236}); +---- ok +-STATEMENT CREATE (t:test {prop: 289118}); +---- ok +-STATEMENT CREATE (t:test {prop: 600721}); +---- ok +-STATEMENT CREATE (t:test {prop: 577106}); +---- ok +-STATEMENT CREATE (t:test {prop: 69995}); +---- ok +-STATEMENT CREATE (t:test {prop: 86006}); +---- ok +-STATEMENT CREATE (t:test {prop: 218223}); +---- ok +-STATEMENT CREATE (t:test {prop: 117979}); +---- ok +-STATEMENT CREATE (t:test {prop: 410655}); +---- ok +-STATEMENT CREATE (t:test {prop: 943515}); +---- ok +-STATEMENT CREATE (t:test {prop: 707503}); +---- ok +-STATEMENT CREATE (t:test {prop: 546534}); +---- ok +-STATEMENT CREATE (t:test {prop: 745966}); +---- ok +-STATEMENT CREATE (t:test {prop: 954818}); +---- ok +-STATEMENT CREATE (t:test {prop: 371147}); +---- ok +-STATEMENT CREATE (t:test {prop: 599477}); +---- ok +-STATEMENT CREATE (t:test {prop: 61577}); +---- ok +-STATEMENT CREATE (t:test {prop: 370701}); +---- ok +-STATEMENT CREATE (t:test {prop: 555210}); +---- ok +-STATEMENT CREATE (t:test {prop: 723573}); +---- ok +-STATEMENT CREATE (t:test {prop: 990603}); +---- ok +-STATEMENT CREATE (t:test {prop: 401050}); +---- ok +-STATEMENT CREATE (t:test {prop: 456654}); +---- ok +-STATEMENT CREATE (t:test {prop: 466108}); +---- ok +-STATEMENT CREATE (t:test {prop: 196826}); +---- ok +-STATEMENT CREATE (t:test {prop: 824310}); +---- ok +-STATEMENT CREATE (t:test {prop: 143647}); +---- ok +-STATEMENT CREATE (t:test {prop: 892116}); +---- ok +-STATEMENT CREATE (t:test {prop: 225021}); +---- ok +-STATEMENT CREATE (t:test {prop: 635445}); +---- ok +-STATEMENT CREATE (t:test {prop: 739438}); +---- ok +-STATEMENT CREATE (t:test {prop: 131728}); +---- ok +-STATEMENT CREATE (t:test {prop: 863306}); +---- ok +-STATEMENT CREATE (t:test {prop: 672110}); +---- ok +-STATEMENT CREATE (t:test {prop: 648288}); +---- ok +-STATEMENT CREATE (t:test {prop: 839409}); +---- ok +-STATEMENT CREATE (t:test {prop: 111609}); +---- ok +-STATEMENT CREATE (t:test {prop: 846506}); +---- ok +-STATEMENT CREATE (t:test {prop: 459622}); +---- ok +-STATEMENT CREATE (t:test {prop: 355025}); +---- ok +-STATEMENT CREATE (t:test {prop: 546187}); +---- ok +-STATEMENT CREATE (t:test {prop: 630485}); +---- ok +-STATEMENT CREATE (t:test {prop: 389575}); +---- ok +-STATEMENT CREATE (t:test {prop: 76632}); +---- ok +-STATEMENT CREATE (t:test {prop: 478}); +---- ok +-STATEMENT CREATE (t:test {prop: 435873}); +---- ok +-STATEMENT CREATE (t:test {prop: 502760}); +---- ok +-STATEMENT CREATE (t:test {prop: 663080}); +---- ok +-STATEMENT CREATE (t:test {prop: 432089}); +---- ok +-STATEMENT CREATE (t:test {prop: 718983}); +---- ok +-STATEMENT CREATE (t:test {prop: 268134}); +---- ok +-STATEMENT CREATE (t:test {prop: 560395}); +---- ok +-STATEMENT CREATE (t:test {prop: 736027}); +---- ok +-STATEMENT CREATE (t:test {prop: 778153}); +---- ok +-STATEMENT CREATE (t:test {prop: 224261}); +---- ok +-STATEMENT CREATE (t:test {prop: 584785}); +---- ok +-STATEMENT CREATE (t:test {prop: 681420}); +---- ok +-STATEMENT CREATE (t:test {prop: 52829}); +---- ok +-STATEMENT CREATE (t:test {prop: 885501}); +---- ok +-STATEMENT CREATE (t:test {prop: 555299}); +---- ok +-STATEMENT CREATE (t:test {prop: 1220}); +---- ok +-STATEMENT CREATE (t:test {prop: 318686}); +---- ok +-STATEMENT CREATE (t:test {prop: 592005}); +---- ok +-STATEMENT CREATE (t:test {prop: 856821}); +---- ok +-STATEMENT CREATE (t:test {prop: 358921}); +---- ok +-STATEMENT CREATE (t:test {prop: 596277}); +---- ok +-STATEMENT CREATE (t:test {prop: 482327}); +---- ok +-STATEMENT CREATE (t:test {prop: 924602}); +---- ok +-STATEMENT CREATE (t:test {prop: 130615}); +---- ok +-STATEMENT CREATE (t:test {prop: 451508}); +---- ok +-STATEMENT CREATE (t:test {prop: 913044}); +---- ok +-STATEMENT CREATE (t:test {prop: 849789}); +---- ok +-STATEMENT CREATE (t:test {prop: 408496}); +---- ok +-STATEMENT CREATE (t:test {prop: 63223}); +---- ok +-STATEMENT CREATE (t:test {prop: 631407}); +---- ok +-STATEMENT CREATE (t:test {prop: 12827}); +---- ok +-STATEMENT CREATE (t:test {prop: 819154}); +---- ok +-STATEMENT CREATE (t:test {prop: 387811}); +---- ok +-STATEMENT CREATE (t:test {prop: 417555}); +---- ok +-STATEMENT CREATE (t:test {prop: 173346}); +---- ok +-STATEMENT CREATE (t:test {prop: 11872}); +---- ok +-STATEMENT CREATE (t:test {prop: 138143}); +---- ok +-STATEMENT CREATE (t:test {prop: 883705}); +---- ok +-STATEMENT CREATE (t:test {prop: 597340}); +---- ok +-STATEMENT CREATE (t:test {prop: 216552}); +---- ok +-STATEMENT CREATE (t:test {prop: 326567}); +---- ok +-STATEMENT CREATE (t:test {prop: 877738}); +---- ok +-STATEMENT CREATE (t:test {prop: 178941}); +---- ok +-STATEMENT CREATE (t:test {prop: 454521}); +---- ok +-STATEMENT CREATE (t:test {prop: 108259}); +---- ok +-STATEMENT CREATE (t:test {prop: 751859}); +---- ok +-STATEMENT CREATE (t:test {prop: 667437}); +---- ok +-STATEMENT CREATE (t:test {prop: 373297}); +---- ok +-STATEMENT CREATE (t:test {prop: 77829}); +---- ok +-STATEMENT CREATE (t:test {prop: 558340}); +---- ok +-STATEMENT CREATE (t:test {prop: 523187}); +---- ok +-STATEMENT CREATE (t:test {prop: 328374}); +---- ok +-STATEMENT CREATE (t:test {prop: 911420}); +---- ok +-STATEMENT CREATE (t:test {prop: 382334}); +---- ok +-STATEMENT CREATE (t:test {prop: 644005}); +---- ok +-STATEMENT CREATE (t:test {prop: 209782}); +---- ok +-STATEMENT CREATE (t:test {prop: 977230}); +---- ok +-STATEMENT CREATE (t:test {prop: 921032}); +---- ok +-STATEMENT CREATE (t:test {prop: 98893}); +---- ok +-STATEMENT CREATE (t:test {prop: 478431}); +---- ok +-STATEMENT CREATE (t:test {prop: 478165}); +---- ok +-STATEMENT CREATE (t:test {prop: 461699}); +---- ok +-STATEMENT CREATE (t:test {prop: 630187}); +---- ok +-STATEMENT CREATE (t:test {prop: 185843}); +---- ok +-STATEMENT CREATE (t:test {prop: 415670}); +---- ok +-STATEMENT CREATE (t:test {prop: 291180}); +---- ok +-STATEMENT CREATE (t:test {prop: 911516}); +---- ok +-STATEMENT CREATE (t:test {prop: 636744}); +---- ok +-STATEMENT CREATE (t:test {prop: 568915}); +---- ok +-STATEMENT CREATE (t:test {prop: 424377}); +---- ok +-STATEMENT CREATE (t:test {prop: 732617}); +---- ok +-STATEMENT CREATE (t:test {prop: 263721}); +---- ok +-STATEMENT CREATE (t:test {prop: 408115}); +---- ok +-STATEMENT CREATE (t:test {prop: 171380}); +---- ok +-STATEMENT CREATE (t:test {prop: 673546}); +---- ok +-STATEMENT CREATE (t:test {prop: 297215}); +---- ok +-STATEMENT CREATE (t:test {prop: 332667}); +---- ok +-STATEMENT CREATE (t:test {prop: 688127}); +---- ok +-STATEMENT CREATE (t:test {prop: 110227}); +---- ok +-STATEMENT CREATE (t:test {prop: 120203}); +---- ok +-STATEMENT CREATE (t:test {prop: 254247}); +---- ok +-STATEMENT CREATE (t:test {prop: 524731}); +---- ok +-STATEMENT CREATE (t:test {prop: 693186}); +---- ok +-STATEMENT CREATE (t:test {prop: 219621}); +---- ok +-STATEMENT CREATE (t:test {prop: 857594}); +---- ok +-STATEMENT CREATE (t:test {prop: 180261}); +---- ok +-STATEMENT CREATE (t:test {prop: 247405}); +---- ok +-STATEMENT CREATE (t:test {prop: 174377}); +---- ok +-STATEMENT CREATE (t:test {prop: 163859}); +---- ok +-STATEMENT CREATE (t:test {prop: 82316}); +---- ok +-STATEMENT CREATE (t:test {prop: 463015}); +---- ok +-STATEMENT CREATE (t:test {prop: 937517}); +---- ok +-STATEMENT CREATE (t:test {prop: 342407}); +---- ok +-STATEMENT CREATE (t:test {prop: 427458}); +---- ok +-STATEMENT CREATE (t:test {prop: 753520}); +---- ok +-STATEMENT CREATE (t:test {prop: 322445}); +---- ok +-STATEMENT CREATE (t:test {prop: 521772}); +---- ok +-STATEMENT CREATE (t:test {prop: 603868}); +---- ok +-STATEMENT CREATE (t:test {prop: 491978}); +---- ok +-STATEMENT CREATE (t:test {prop: 471843}); +---- ok +-STATEMENT CREATE (t:test {prop: 634649}); +---- ok +-STATEMENT CREATE (t:test {prop: 146409}); +---- ok +-STATEMENT CREATE (t:test {prop: 768747}); +---- ok +-STATEMENT CREATE (t:test {prop: 380494}); +---- ok +-STATEMENT CREATE (t:test {prop: 145565}); +---- ok +-STATEMENT CREATE (t:test {prop: 601119}); +---- ok +-STATEMENT CREATE (t:test {prop: 24744}); +---- ok +-STATEMENT CREATE (t:test {prop: 464392}); +---- ok +-STATEMENT CREATE (t:test {prop: 538787}); +---- ok +-STATEMENT CREATE (t:test {prop: 512116}); +---- ok +-STATEMENT CREATE (t:test {prop: 672181}); +---- ok +-STATEMENT CREATE (t:test {prop: 692979}); +---- ok +-STATEMENT CREATE (t:test {prop: 981739}); +---- ok +-STATEMENT CREATE (t:test {prop: 273804}); +---- ok +-STATEMENT CREATE (t:test {prop: 771112}); +---- ok +-STATEMENT CREATE (t:test {prop: 450824}); +---- ok +-STATEMENT CREATE (t:test {prop: 305428}); +---- ok +-STATEMENT CREATE (t:test {prop: 883754}); +---- ok +-STATEMENT CREATE (t:test {prop: 636041}); +---- ok +-STATEMENT CREATE (t:test {prop: 777701}); +---- ok +-STATEMENT CREATE (t:test {prop: 651584}); +---- ok +-STATEMENT CREATE (t:test {prop: 892876}); +---- ok +-STATEMENT CREATE (t:test {prop: 154647}); +---- ok +-STATEMENT CREATE (t:test {prop: 284314}); +---- ok +-STATEMENT CREATE (t:test {prop: 771437}); +---- ok +-STATEMENT CREATE (t:test {prop: 933172}); +---- ok +-STATEMENT CREATE (t:test {prop: 535886}); +---- ok +-STATEMENT CREATE (t:test {prop: 921146}); +---- ok +-STATEMENT CREATE (t:test {prop: 559381}); +---- ok +-STATEMENT CREATE (t:test {prop: 778952}); +---- ok +-STATEMENT CREATE (t:test {prop: 34850}); +---- ok +-STATEMENT CREATE (t:test {prop: 726882}); +---- ok +-STATEMENT CREATE (t:test {prop: 997268}); +---- ok +-STATEMENT CREATE (t:test {prop: 627294}); +---- ok +-STATEMENT CREATE (t:test {prop: 7370}); +---- ok +-STATEMENT CREATE (t:test {prop: 172190}); +---- ok +-STATEMENT CREATE (t:test {prop: 292901}); +---- ok +-STATEMENT CREATE (t:test {prop: 691457}); +---- ok +-STATEMENT CREATE (t:test {prop: 779844}); +---- ok +-STATEMENT CREATE (t:test {prop: 41132}); +---- ok +-STATEMENT CREATE (t:test {prop: 416372}); +---- ok +-STATEMENT CREATE (t:test {prop: 144722}); +---- ok +-STATEMENT CREATE (t:test {prop: 880342}); +---- ok +-STATEMENT CREATE (t:test {prop: 77353}); +---- ok +-STATEMENT CREATE (t:test {prop: 107709}); +---- ok +-STATEMENT CREATE (t:test {prop: 318965}); +---- ok +-STATEMENT CREATE (t:test {prop: 824006}); +---- ok +-STATEMENT CREATE (t:test {prop: 206556}); +---- ok +-STATEMENT CREATE (t:test {prop: 200980}); +---- ok +-STATEMENT CREATE (t:test {prop: 867952}); +---- ok +-STATEMENT CREATE (t:test {prop: 584767}); +---- ok +-STATEMENT CREATE (t:test {prop: 358753}); +---- ok +-STATEMENT CREATE (t:test {prop: 248658}); +---- ok +-STATEMENT CREATE (t:test {prop: 572341}); +---- ok +-STATEMENT CREATE (t:test {prop: 423885}); +---- ok +-STATEMENT CREATE (t:test {prop: 634861}); +---- ok +-STATEMENT CREATE (t:test {prop: 877479}); +---- ok +-STATEMENT CREATE (t:test {prop: 703792}); +---- ok +-STATEMENT CREATE (t:test {prop: 920016}); +---- ok +-STATEMENT CREATE (t:test {prop: 216225}); +---- ok +-STATEMENT CREATE (t:test {prop: 798490}); +---- ok +-STATEMENT CREATE (t:test {prop: 797396}); +---- ok +-STATEMENT CREATE (t:test {prop: 468336}); +---- ok +-STATEMENT CREATE (t:test {prop: 683049}); +---- ok +-STATEMENT CREATE (t:test {prop: 346802}); +---- ok +-STATEMENT CREATE (t:test {prop: 944251}); +---- ok +-STATEMENT CREATE (t:test {prop: 952915}); +---- ok +-STATEMENT CREATE (t:test {prop: 254715}); +---- ok +-STATEMENT CREATE (t:test {prop: 998167}); +---- ok +-STATEMENT CREATE (t:test {prop: 51207}); +---- ok +-STATEMENT CREATE (t:test {prop: 785778}); +---- ok +-STATEMENT CREATE (t:test {prop: 458416}); +---- ok +-STATEMENT CREATE (t:test {prop: 479788}); +---- ok +-STATEMENT CREATE (t:test {prop: 136034}); +---- ok +-STATEMENT CREATE (t:test {prop: 755761}); +---- ok +-STATEMENT CREATE (t:test {prop: 362717}); +---- ok +-STATEMENT CREATE (t:test {prop: 358544}); +---- ok +-STATEMENT CREATE (t:test {prop: 283252}); +---- ok +-STATEMENT CREATE (t:test {prop: 185815}); +---- ok +-STATEMENT CREATE (t:test {prop: 711342}); +---- ok +-STATEMENT CREATE (t:test {prop: 192008}); +---- ok +-STATEMENT CREATE (t:test {prop: 644583}); +---- ok +-STATEMENT CREATE (t:test {prop: 474577}); +---- ok +-STATEMENT CREATE (t:test {prop: 942003}); +---- ok +-STATEMENT CREATE (t:test {prop: 364615}); +---- ok +-STATEMENT CREATE (t:test {prop: 594673}); +---- ok +-STATEMENT CREATE (t:test {prop: 623772}); +---- ok +-STATEMENT CREATE (t:test {prop: 837381}); +---- ok +-STATEMENT CREATE (t:test {prop: 913537}); +---- ok +-STATEMENT CREATE (t:test {prop: 879787}); +---- ok +-STATEMENT CREATE (t:test {prop: 720885}); +---- ok +-STATEMENT CREATE (t:test {prop: 104918}); +---- ok +-STATEMENT CREATE (t:test {prop: 982001}); +---- ok +-STATEMENT CREATE (t:test {prop: 380788}); +---- ok +-STATEMENT CREATE (t:test {prop: 158957}); +---- ok +-STATEMENT CREATE (t:test {prop: 282029}); +---- ok +-STATEMENT CREATE (t:test {prop: 322165}); +---- ok +-STATEMENT CREATE (t:test {prop: 969603}); +---- ok +-STATEMENT CREATE (t:test {prop: 141378}); +---- ok +-STATEMENT CREATE (t:test {prop: 118501}); +---- ok +-STATEMENT CREATE (t:test {prop: 649633}); +---- ok +-STATEMENT CREATE (t:test {prop: 988681}); +---- ok +-STATEMENT CREATE (t:test {prop: 971095}); +---- ok +-STATEMENT CREATE (t:test {prop: 529685}); +---- ok +-STATEMENT CREATE (t:test {prop: 449444}); +---- ok +-STATEMENT CREATE (t:test {prop: 588657}); +---- ok +-STATEMENT CREATE (t:test {prop: 510523}); +---- ok +-STATEMENT CREATE (t:test {prop: 286995}); +---- ok +-STATEMENT CREATE (t:test {prop: 509259}); +---- ok +-STATEMENT CREATE (t:test {prop: 703384}); +---- ok +-STATEMENT CREATE (t:test {prop: 986241}); +---- ok +-STATEMENT CREATE (t:test {prop: 405347}); +---- ok +-STATEMENT CREATE (t:test {prop: 382944}); +---- ok +-STATEMENT CREATE (t:test {prop: 555734}); +---- ok +-STATEMENT CREATE (t:test {prop: 915486}); +---- ok +-STATEMENT CREATE (t:test {prop: 941527}); +---- ok +-STATEMENT CREATE (t:test {prop: 235575}); +---- ok +-STATEMENT CREATE (t:test {prop: 800547}); +---- ok +-STATEMENT CREATE (t:test {prop: 403153}); +---- ok +-STATEMENT CREATE (t:test {prop: 73246}); +---- ok +-STATEMENT CREATE (t:test {prop: 732873}); +---- ok +-STATEMENT CREATE (t:test {prop: 817558}); +---- ok +-STATEMENT CREATE (t:test {prop: 20802}); +---- ok +-STATEMENT CREATE (t:test {prop: 952177}); +---- ok +-STATEMENT CREATE (t:test {prop: 247935}); +---- ok +-STATEMENT CREATE (t:test {prop: 774613}); +---- ok +-STATEMENT CREATE (t:test {prop: 263204}); +---- ok +-STATEMENT CREATE (t:test {prop: 766591}); +---- ok +-STATEMENT CREATE (t:test {prop: 73939}); +---- ok +-STATEMENT CREATE (t:test {prop: 974462}); +---- ok +-STATEMENT CREATE (t:test {prop: 280192}); +---- ok +-STATEMENT CREATE (t:test {prop: 634515}); +---- ok +-STATEMENT CREATE (t:test {prop: 270311}); +---- ok +-STATEMENT CREATE (t:test {prop: 901357}); +---- ok +-STATEMENT CREATE (t:test {prop: 633990}); +---- ok +-STATEMENT CREATE (t:test {prop: 110160}); +---- ok +-STATEMENT CREATE (t:test {prop: 198598}); +---- ok +-STATEMENT CREATE (t:test {prop: 100455}); +---- ok +-STATEMENT CREATE (t:test {prop: 929050}); +---- ok +-STATEMENT CREATE (t:test {prop: 201841}); +---- ok +-STATEMENT CREATE (t:test {prop: 999233}); +---- ok +-STATEMENT CREATE (t:test {prop: 190485}); +---- ok +-STATEMENT CREATE (t:test {prop: 676616}); +---- ok +-STATEMENT CREATE (t:test {prop: 907350}); +---- ok +-STATEMENT CREATE (t:test {prop: 758720}); +---- ok +-STATEMENT CREATE (t:test {prop: 855265}); +---- ok +-STATEMENT CREATE (t:test {prop: 437765}); +---- ok +-STATEMENT CREATE (t:test {prop: 69862}); +---- ok +-STATEMENT CREATE (t:test {prop: 330192}); +---- ok +-STATEMENT CREATE (t:test {prop: 983778}); +---- ok +-STATEMENT CREATE (t:test {prop: 183774}); +---- ok +-STATEMENT CREATE (t:test {prop: 747399}); +---- ok +-STATEMENT CREATE (t:test {prop: 834967}); +---- ok +-STATEMENT CREATE (t:test {prop: 341264}); +---- ok +-STATEMENT CREATE (t:test {prop: 818106}); +---- ok +-STATEMENT CREATE (t:test {prop: 886965}); +---- ok +-STATEMENT CREATE (t:test {prop: 614082}); +---- ok +-STATEMENT CREATE (t:test {prop: 587656}); +---- ok +-STATEMENT CREATE (t:test {prop: 860816}); +---- ok +-STATEMENT CREATE (t:test {prop: 233688}); +---- ok +-STATEMENT CREATE (t:test {prop: 253116}); +---- ok +-STATEMENT CREATE (t:test {prop: 356618}); +---- ok +-STATEMENT CREATE (t:test {prop: 417937}); +---- ok +-STATEMENT CREATE (t:test {prop: 529478}); +---- ok +-STATEMENT CREATE (t:test {prop: 997678}); +---- ok +-STATEMENT CREATE (t:test {prop: 356371}); +---- ok +-STATEMENT CREATE (t:test {prop: 250293}); +---- ok +-STATEMENT CREATE (t:test {prop: 808728}); +---- ok +-STATEMENT CREATE (t:test {prop: 553373}); +---- ok +-STATEMENT CREATE (t:test {prop: 664656}); +---- ok +-STATEMENT CREATE (t:test {prop: 174402}); +---- ok +-STATEMENT CREATE (t:test {prop: 288071}); +---- ok +-STATEMENT CREATE (t:test {prop: 567084}); +---- ok +-STATEMENT CREATE (t:test {prop: 7111}); +---- ok +-STATEMENT CREATE (t:test {prop: 287429}); +---- ok +-STATEMENT CREATE (t:test {prop: 91624}); +---- ok +-STATEMENT CREATE (t:test {prop: 384621}); +---- ok +-STATEMENT CREATE (t:test {prop: 8537}); +---- ok +-STATEMENT CREATE (t:test {prop: 526082}); +---- ok +-STATEMENT CREATE (t:test {prop: 833718}); +---- ok +-STATEMENT CREATE (t:test {prop: 882579}); +---- ok +-STATEMENT CREATE (t:test {prop: 473671}); +---- ok +-STATEMENT CREATE (t:test {prop: 816546}); +---- ok +-STATEMENT CREATE (t:test {prop: 110281}); +---- ok +-STATEMENT CREATE (t:test {prop: 735315}); +---- ok +-STATEMENT CREATE (t:test {prop: 78491}); +---- ok +-STATEMENT CREATE (t:test {prop: 561732}); +---- ok +-STATEMENT CREATE (t:test {prop: 809414}); +---- ok +-STATEMENT CREATE (t:test {prop: 375203}); +---- ok +-STATEMENT CREATE (t:test {prop: 426017}); +---- ok +-STATEMENT CREATE (t:test {prop: 246223}); +---- ok +-STATEMENT CREATE (t:test {prop: 915591}); +---- ok +-STATEMENT CREATE (t:test {prop: 315104}); +---- ok +-STATEMENT CREATE (t:test {prop: 265070}); +---- ok +-STATEMENT CREATE (t:test {prop: 574499}); +---- ok +-STATEMENT CREATE (t:test {prop: 170017}); +---- ok +-STATEMENT CREATE (t:test {prop: 41889}); +---- ok +-STATEMENT CREATE (t:test {prop: 347315}); +---- ok +-STATEMENT CREATE (t:test {prop: 802298}); +---- ok +-STATEMENT CREATE (t:test {prop: 444864}); +---- ok +-STATEMENT CREATE (t:test {prop: 847183}); +---- ok +-STATEMENT CREATE (t:test {prop: 722764}); +---- ok +-STATEMENT CREATE (t:test {prop: 275834}); +---- ok +-STATEMENT CREATE (t:test {prop: 863456}); +---- ok +-STATEMENT CREATE (t:test {prop: 478832}); +---- ok +-STATEMENT CREATE (t:test {prop: 71924}); +---- ok +-STATEMENT CREATE (t:test {prop: 617125}); +---- ok +-STATEMENT CREATE (t:test {prop: 183408}); +---- ok +-STATEMENT CREATE (t:test {prop: 507310}); +---- ok +-STATEMENT CREATE (t:test {prop: 424303}); +---- ok +-STATEMENT CREATE (t:test {prop: 500776}); +---- ok +-STATEMENT CREATE (t:test {prop: 380456}); +---- ok +-STATEMENT CREATE (t:test {prop: 704311}); +---- ok +-STATEMENT CREATE (t:test {prop: 608395}); +---- ok +-STATEMENT CREATE (t:test {prop: 759592}); +---- ok +-STATEMENT CREATE (t:test {prop: 852814}); +---- ok +-STATEMENT CREATE (t:test {prop: 239753}); +---- ok +-STATEMENT CREATE (t:test {prop: 514161}); +---- ok +-STATEMENT CREATE (t:test {prop: 527362}); +---- ok +-STATEMENT CREATE (t:test {prop: 131442}); +---- ok +-STATEMENT CREATE (t:test {prop: 968632}); +---- ok +-STATEMENT CREATE (t:test {prop: 759329}); +---- ok +-STATEMENT CREATE (t:test {prop: 649351}); +---- ok +-STATEMENT CREATE (t:test {prop: 969544}); +---- ok +-STATEMENT CREATE (t:test {prop: 397291}); +---- ok +-STATEMENT CREATE (t:test {prop: 6757}); +---- ok +-STATEMENT CREATE (t:test {prop: 160681}); +---- ok +-STATEMENT CREATE (t:test {prop: 166193}); +---- ok +-STATEMENT CREATE (t:test {prop: 241054}); +---- ok +-STATEMENT CREATE (t:test {prop: 273698}); +---- ok +-STATEMENT CREATE (t:test {prop: 675350}); +---- ok +-STATEMENT CREATE (t:test {prop: 724757}); +---- ok +-STATEMENT CREATE (t:test {prop: 732581}); +---- ok +-STATEMENT CREATE (t:test {prop: 929205}); +---- ok +-STATEMENT CREATE (t:test {prop: 598711}); +---- ok +-STATEMENT CREATE (t:test {prop: 859617}); +---- ok +-STATEMENT CREATE (t:test {prop: 798622}); +---- ok +-STATEMENT CREATE (t:test {prop: 278112}); +---- ok +-STATEMENT CREATE (t:test {prop: 24090}); +---- ok +-STATEMENT CREATE (t:test {prop: 723038}); +---- ok +-STATEMENT CREATE (t:test {prop: 752055}); +---- ok +-STATEMENT CREATE (t:test {prop: 572195}); +---- ok +-STATEMENT CREATE (t:test {prop: 964438}); +---- ok +-STATEMENT CREATE (t:test {prop: 815080}); +---- ok +-STATEMENT CREATE (t:test {prop: 607425}); +---- ok +-STATEMENT CREATE (t:test {prop: 339014}); +---- ok +-STATEMENT CREATE (t:test {prop: 444658}); +---- ok +-STATEMENT CREATE (t:test {prop: 39869}); +---- ok +-STATEMENT CREATE (t:test {prop: 12041}); +---- ok +-STATEMENT CREATE (t:test {prop: 77263}); +---- ok +-STATEMENT CREATE (t:test {prop: 231801}); +---- ok +-STATEMENT CREATE (t:test {prop: 958396}); +---- ok +-STATEMENT CREATE (t:test {prop: 347474}); +---- ok +-STATEMENT CREATE (t:test {prop: 442707}); +---- ok +-STATEMENT CREATE (t:test {prop: 168432}); +---- ok +-STATEMENT CREATE (t:test {prop: 870668}); +---- ok +-STATEMENT CREATE (t:test {prop: 925414}); +---- ok +-STATEMENT CREATE (t:test {prop: 986511}); +---- ok +-STATEMENT CREATE (t:test {prop: 655822}); +---- ok +-STATEMENT CREATE (t:test {prop: 204078}); +---- ok +-STATEMENT CREATE (t:test {prop: 58719}); +---- ok +-STATEMENT CREATE (t:test {prop: 910750}); +---- ok +-STATEMENT CREATE (t:test {prop: 912572}); +---- ok +-STATEMENT CREATE (t:test {prop: 52507}); +---- ok +-STATEMENT CREATE (t:test {prop: 135035}); +---- ok +-STATEMENT CREATE (t:test {prop: 800915}); +---- ok +-STATEMENT CREATE (t:test {prop: 23312}); +---- ok +-STATEMENT CREATE (t:test {prop: 868243}); +---- ok +-STATEMENT CREATE (t:test {prop: 883684}); +---- ok +-STATEMENT CREATE (t:test {prop: 431445}); +---- ok +-STATEMENT CREATE (t:test {prop: 367878}); +---- ok +-STATEMENT CREATE (t:test {prop: 808946}); +---- ok +-STATEMENT CREATE (t:test {prop: 10013}); +---- ok +-STATEMENT CREATE (t:test {prop: 341352}); +---- ok +-STATEMENT CREATE (t:test {prop: 547587}); +---- ok +-STATEMENT CREATE (t:test {prop: 484603}); +---- ok +-STATEMENT CREATE (t:test {prop: 355358}); +---- ok +-STATEMENT CREATE (t:test {prop: 384135}); +---- ok +-STATEMENT CREATE (t:test {prop: 115335}); +---- ok +-STATEMENT CREATE (t:test {prop: 919393}); +---- ok +-STATEMENT CREATE (t:test {prop: 141217}); +---- ok +-STATEMENT CREATE (t:test {prop: 684765}); +---- ok +-STATEMENT CREATE (t:test {prop: 295924}); +---- ok +-STATEMENT CREATE (t:test {prop: 861958}); +---- ok +-STATEMENT CREATE (t:test {prop: 787919}); +---- ok +-STATEMENT CREATE (t:test {prop: 415301}); +---- ok +-STATEMENT CREATE (t:test {prop: 408322}); +---- ok +-STATEMENT CREATE (t:test {prop: 765904}); +---- ok +-STATEMENT CREATE (t:test {prop: 625968}); +---- ok +-STATEMENT CREATE (t:test {prop: 516465}); +---- ok +-STATEMENT CREATE (t:test {prop: 726511}); +---- ok +-STATEMENT CREATE (t:test {prop: 168817}); +---- ok +-STATEMENT CREATE (t:test {prop: 779647}); +---- ok +-STATEMENT CREATE (t:test {prop: 782063}); +---- ok +-STATEMENT CREATE (t:test {prop: 196095}); +---- ok +-STATEMENT CREATE (t:test {prop: 928125}); +---- ok +-STATEMENT CREATE (t:test {prop: 117103}); +---- ok +-STATEMENT CREATE (t:test {prop: 287471}); +---- ok +-STATEMENT CREATE (t:test {prop: 541047}); +---- ok +-STATEMENT CREATE (t:test {prop: 923659}); +---- ok +-STATEMENT CREATE (t:test {prop: 507363}); +---- ok +-STATEMENT CREATE (t:test {prop: 902712}); +---- ok +-STATEMENT CREATE (t:test {prop: 716250}); +---- ok +-STATEMENT CREATE (t:test {prop: 717739}); +---- ok +-STATEMENT CREATE (t:test {prop: 241844}); +---- ok +-STATEMENT CREATE (t:test {prop: 132937}); +---- ok +-STATEMENT CREATE (t:test {prop: 792437}); +---- ok +-STATEMENT CREATE (t:test {prop: 442355}); +---- ok +-STATEMENT CREATE (t:test {prop: 420957}); +---- ok +-STATEMENT CREATE (t:test {prop: 255519}); +---- ok +-STATEMENT CREATE (t:test {prop: 21877}); +---- ok +-STATEMENT CREATE (t:test {prop: 109936}); +---- ok +-STATEMENT CREATE (t:test {prop: 556538}); +---- ok +-STATEMENT CREATE (t:test {prop: 196119}); +---- ok +-STATEMENT CREATE (t:test {prop: 324356}); +---- ok +-STATEMENT CREATE (t:test {prop: 964222}); +---- ok +-STATEMENT CREATE (t:test {prop: 86485}); +---- ok +-STATEMENT CREATE (t:test {prop: 253250}); +---- ok +-STATEMENT CREATE (t:test {prop: 736061}); +---- ok +-STATEMENT CREATE (t:test {prop: 553820}); +---- ok +-STATEMENT CREATE (t:test {prop: 971571}); +---- ok +-STATEMENT CREATE (t:test {prop: 683028}); +---- ok +-STATEMENT CREATE (t:test {prop: 165023}); +---- ok +-STATEMENT CREATE (t:test {prop: 864129}); +---- ok +-STATEMENT CREATE (t:test {prop: 501997}); +---- ok +-STATEMENT CREATE (t:test {prop: 569079}); +---- ok +-STATEMENT CREATE (t:test {prop: 64037}); +---- ok +-STATEMENT CREATE (t:test {prop: 359683}); +---- ok +-STATEMENT CREATE (t:test {prop: 491905}); +---- ok +-STATEMENT CREATE (t:test {prop: 688538}); +---- ok +-STATEMENT CREATE (t:test {prop: 44063}); +---- ok +-STATEMENT CREATE (t:test {prop: 997795}); +---- ok +-STATEMENT CREATE (t:test {prop: 508990}); +---- ok +-STATEMENT CREATE (t:test {prop: 440888}); +---- ok +-STATEMENT CREATE (t:test {prop: 204216}); +---- ok +-STATEMENT CREATE (t:test {prop: 5234}); +---- ok +-STATEMENT CREATE (t:test {prop: 293239}); +---- ok +-STATEMENT CREATE (t:test {prop: 963648}); +---- ok +-STATEMENT CREATE (t:test {prop: 202600}); +---- ok +-STATEMENT CREATE (t:test {prop: 283223}); +---- ok +-STATEMENT CREATE (t:test {prop: 937070}); +---- ok +-STATEMENT CREATE (t:test {prop: 675684}); +---- ok +-STATEMENT CREATE (t:test {prop: 532592}); +---- ok +-STATEMENT CREATE (t:test {prop: 899162}); +---- ok +-STATEMENT CREATE (t:test {prop: 502879}); +---- ok +-STATEMENT CREATE (t:test {prop: 372469}); +---- ok +-STATEMENT CREATE (t:test {prop: 523078}); +---- ok +-STATEMENT CREATE (t:test {prop: 235919}); +---- ok +-STATEMENT CREATE (t:test {prop: 940614}); +---- ok +-STATEMENT CREATE (t:test {prop: 440877}); +---- ok +-STATEMENT CREATE (t:test {prop: 233073}); +---- ok +-STATEMENT CREATE (t:test {prop: 84273}); +---- ok +-STATEMENT CREATE (t:test {prop: 212447}); +---- ok +-STATEMENT CREATE (t:test {prop: 635762}); +---- ok +-STATEMENT CREATE (t:test {prop: 195455}); +---- ok +-STATEMENT CREATE (t:test {prop: 609699}); +---- ok +-STATEMENT CREATE (t:test {prop: 876573}); +---- ok +-STATEMENT CREATE (t:test {prop: 622201}); +---- ok +-STATEMENT CREATE (t:test {prop: 596856}); +---- ok +-STATEMENT CREATE (t:test {prop: 502475}); +---- ok +-STATEMENT CREATE (t:test {prop: 173739}); +---- ok +-STATEMENT CREATE (t:test {prop: 421770}); +---- ok +-STATEMENT CREATE (t:test {prop: 43566}); +---- ok +-STATEMENT CREATE (t:test {prop: 1663}); +---- ok +-STATEMENT CREATE (t:test {prop: 78644}); +---- ok +-STATEMENT CREATE (t:test {prop: 961572}); +---- ok +-STATEMENT CREATE (t:test {prop: 710190}); +---- ok +-STATEMENT CREATE (t:test {prop: 414012}); +---- ok +-STATEMENT CREATE (t:test {prop: 879915}); +---- ok +-STATEMENT CREATE (t:test {prop: 668792}); +---- ok +-STATEMENT CREATE (t:test {prop: 288543}); +---- ok +-STATEMENT CREATE (t:test {prop: 93907}); +---- ok +-STATEMENT CREATE (t:test {prop: 276011}); +---- ok +-STATEMENT CREATE (t:test {prop: 151464}); +---- ok +-STATEMENT CREATE (t:test {prop: 776446}); +---- ok +-STATEMENT CREATE (t:test {prop: 553586}); +---- ok +-STATEMENT CREATE (t:test {prop: 568691}); +---- ok +-STATEMENT CREATE (t:test {prop: 887107}); +---- ok +-STATEMENT CREATE (t:test {prop: 823193}); +---- ok +-STATEMENT CREATE (t:test {prop: 721938}); +---- ok +-STATEMENT CREATE (t:test {prop: 349395}); +---- ok +-STATEMENT CREATE (t:test {prop: 837539}); +---- ok +-STATEMENT CREATE (t:test {prop: 838908}); +---- ok +-STATEMENT CREATE (t:test {prop: 949082}); +---- ok +-STATEMENT CREATE (t:test {prop: 211231}); +---- ok +-STATEMENT CREATE (t:test {prop: 168574}); +---- ok +-STATEMENT CREATE (t:test {prop: 536729}); +---- ok +-STATEMENT CREATE (t:test {prop: 180675}); +---- ok +-STATEMENT CREATE (t:test {prop: 958226}); +---- ok +-STATEMENT CREATE (t:test {prop: 570549}); +---- ok +-STATEMENT CREATE (t:test {prop: 603120}); +---- ok +-STATEMENT CREATE (t:test {prop: 566070}); +---- ok +-STATEMENT CREATE (t:test {prop: 414552}); +---- ok +-STATEMENT CREATE (t:test {prop: 797297}); +---- ok +-STATEMENT CREATE (t:test {prop: 518758}); +---- ok +-STATEMENT CREATE (t:test {prop: 504908}); +---- ok +-STATEMENT CREATE (t:test {prop: 979950}); +---- ok +-STATEMENT CREATE (t:test {prop: 696848}); +---- ok +-STATEMENT CREATE (t:test {prop: 249401}); +---- ok +-STATEMENT CREATE (t:test {prop: 408868}); +---- ok +-STATEMENT CREATE (t:test {prop: 353745}); +---- ok +-STATEMENT CREATE (t:test {prop: 685196}); +---- ok +-STATEMENT CREATE (t:test {prop: 5964}); +---- ok +-STATEMENT CREATE (t:test {prop: 142030}); +---- ok +-STATEMENT CREATE (t:test {prop: 265563}); +---- ok +-STATEMENT CREATE (t:test {prop: 254968}); +---- ok +-STATEMENT CREATE (t:test {prop: 389658}); +---- ok +-STATEMENT CREATE (t:test {prop: 283659}); +---- ok +-STATEMENT CREATE (t:test {prop: 769225}); +---- ok +-STATEMENT CREATE (t:test {prop: 155262}); +---- ok +-STATEMENT CREATE (t:test {prop: 174575}); +---- ok +-STATEMENT CREATE (t:test {prop: 82094}); +---- ok +-STATEMENT CREATE (t:test {prop: 553872}); +---- ok +-STATEMENT CREATE (t:test {prop: 113697}); +---- ok +-STATEMENT CREATE (t:test {prop: 413659}); +---- ok +-STATEMENT CREATE (t:test {prop: 418742}); +---- ok +-STATEMENT CREATE (t:test {prop: 617353}); +---- ok +-STATEMENT CREATE (t:test {prop: 366929}); +---- ok +-STATEMENT CREATE (t:test {prop: 25324}); +---- ok +-STATEMENT CREATE (t:test {prop: 431430}); +---- ok +-STATEMENT CREATE (t:test {prop: 714135}); +---- ok +-STATEMENT CREATE (t:test {prop: 65919}); +---- ok +-STATEMENT CREATE (t:test {prop: 753316}); +---- ok +-STATEMENT CREATE (t:test {prop: 776744}); +---- ok +-STATEMENT CREATE (t:test {prop: 595627}); +---- ok +-STATEMENT CREATE (t:test {prop: 490597}); +---- ok +-STATEMENT CREATE (t:test {prop: 13318}); +---- ok +-STATEMENT CREATE (t:test {prop: 389173}); +---- ok +-STATEMENT CREATE (t:test {prop: 440096}); +---- ok +-STATEMENT CREATE (t:test {prop: 425270}); +---- ok +-STATEMENT CREATE (t:test {prop: 604035}); +---- ok +-STATEMENT CREATE (t:test {prop: 794793}); +---- ok +-STATEMENT CREATE (t:test {prop: 175454}); +---- ok +-STATEMENT CREATE (t:test {prop: 417201}); +---- ok +-STATEMENT CREATE (t:test {prop: 981173}); +---- ok +-STATEMENT CREATE (t:test {prop: 555871}); +---- ok +-STATEMENT CREATE (t:test {prop: 46501}); +---- ok +-STATEMENT CREATE (t:test {prop: 325031}); +---- ok +-STATEMENT CREATE (t:test {prop: 257154}); +---- ok +-STATEMENT CREATE (t:test {prop: 43421}); +---- ok +-STATEMENT CREATE (t:test {prop: 240662}); +---- ok +-STATEMENT CREATE (t:test {prop: 426801}); +---- ok +-STATEMENT CREATE (t:test {prop: 532607}); +---- ok +-STATEMENT CREATE (t:test {prop: 632935}); +---- ok +-STATEMENT CREATE (t:test {prop: 23138}); +---- ok +-STATEMENT CREATE (t:test {prop: 584061}); +---- ok +-STATEMENT CREATE (t:test {prop: 120980}); +---- ok +-STATEMENT CREATE (t:test {prop: 497221}); +---- ok +-STATEMENT CREATE (t:test {prop: 217949}); +---- ok +-STATEMENT CREATE (t:test {prop: 526030}); +---- ok +-STATEMENT CREATE (t:test {prop: 216722}); +---- ok +-STATEMENT CREATE (t:test {prop: 344908}); +---- ok +-STATEMENT CREATE (t:test {prop: 600490}); +---- ok +-STATEMENT CREATE (t:test {prop: 379194}); +---- ok +-STATEMENT CREATE (t:test {prop: 945647}); +---- ok +-STATEMENT CREATE (t:test {prop: 339005}); +---- ok +-STATEMENT CREATE (t:test {prop: 232221}); +---- ok +-STATEMENT CREATE (t:test {prop: 340993}); +---- ok +-STATEMENT CREATE (t:test {prop: 536875}); +---- ok +-STATEMENT CREATE (t:test {prop: 93096}); +---- ok +-STATEMENT CREATE (t:test {prop: 816709}); +---- ok +-STATEMENT CREATE (t:test {prop: 657846}); +---- ok +-STATEMENT CREATE (t:test {prop: 719749}); +---- ok +-STATEMENT CREATE (t:test {prop: 116862}); +---- ok +-STATEMENT CREATE (t:test {prop: 462839}); +---- ok +-STATEMENT CREATE (t:test {prop: 59020}); +---- ok +-STATEMENT CREATE (t:test {prop: 279612}); +---- ok +-STATEMENT CREATE (t:test {prop: 838232}); +---- ok +-STATEMENT CREATE (t:test {prop: 277765}); +---- ok +-STATEMENT CREATE (t:test {prop: 822629}); +---- ok +-STATEMENT CREATE (t:test {prop: 959854}); +---- ok +-STATEMENT CREATE (t:test {prop: 382722}); +---- ok +-STATEMENT CREATE (t:test {prop: 573594}); +---- ok +-STATEMENT CREATE (t:test {prop: 629742}); +---- ok +-STATEMENT CREATE (t:test {prop: 224117}); +---- ok +-STATEMENT CREATE (t:test {prop: 456789}); +---- ok +-STATEMENT CREATE (t:test {prop: 764960}); +---- ok +-STATEMENT CREATE (t:test {prop: 737480}); +---- ok +-STATEMENT CREATE (t:test {prop: 358691}); +---- ok +-STATEMENT CREATE (t:test {prop: 63582}); +---- ok +-STATEMENT CREATE (t:test {prop: 83023}); +---- ok +-STATEMENT CREATE (t:test {prop: 156883}); +---- ok +-STATEMENT CREATE (t:test {prop: 155297}); +---- ok +-STATEMENT CREATE (t:test {prop: 390185}); +---- ok +-STATEMENT CREATE (t:test {prop: 564778}); +---- ok +-STATEMENT CREATE (t:test {prop: 186048}); +---- ok +-STATEMENT CREATE (t:test {prop: 525212}); +---- ok +-STATEMENT CREATE (t:test {prop: 866869}); +---- ok +-STATEMENT CREATE (t:test {prop: 795919}); +---- ok +-STATEMENT CREATE (t:test {prop: 369879}); +---- ok +-STATEMENT CREATE (t:test {prop: 153284}); +---- ok +-STATEMENT CREATE (t:test {prop: 430138}); +---- ok +-STATEMENT CREATE (t:test {prop: 955226}); +---- ok +-STATEMENT CREATE (t:test {prop: 213927}); +---- ok +-STATEMENT CREATE (t:test {prop: 59326}); +---- ok +-STATEMENT CREATE (t:test {prop: 226480}); +---- ok +-STATEMENT CREATE (t:test {prop: 316388}); +---- ok +-STATEMENT CREATE (t:test {prop: 711284}); +---- ok +-STATEMENT CREATE (t:test {prop: 63965}); +---- ok +-STATEMENT CREATE (t:test {prop: 906016}); +---- ok +-STATEMENT CREATE (t:test {prop: 128517}); +---- ok +-STATEMENT CREATE (t:test {prop: 508553}); +---- ok +-STATEMENT CREATE (t:test {prop: 119614}); +---- ok +-STATEMENT CREATE (t:test {prop: 465117}); +---- ok +-STATEMENT CREATE (t:test {prop: 40089}); +---- ok +-STATEMENT CREATE (t:test {prop: 88417}); +---- ok +-STATEMENT CREATE (t:test {prop: 725975}); +---- ok +-STATEMENT CREATE (t:test {prop: 491740}); +---- ok +-STATEMENT CREATE (t:test {prop: 435981}); +---- ok +-STATEMENT CREATE (t:test {prop: 800643}); +---- ok +-STATEMENT CREATE (t:test {prop: 179930}); +---- ok +-STATEMENT CREATE (t:test {prop: 146984}); +---- ok +-STATEMENT CREATE (t:test {prop: 44354}); +---- ok +-STATEMENT CREATE (t:test {prop: 215128}); +---- ok +-STATEMENT CREATE (t:test {prop: 963031}); +---- ok +-STATEMENT CREATE (t:test {prop: 175526}); +---- ok +-STATEMENT CREATE (t:test {prop: 786732}); +---- ok +-STATEMENT CREATE (t:test {prop: 134115}); +---- ok +-STATEMENT CREATE (t:test {prop: 246290}); +---- ok +-STATEMENT CREATE (t:test {prop: 714973}); +---- ok +-STATEMENT CREATE (t:test {prop: 578255}); +---- ok +-STATEMENT CREATE (t:test {prop: 797135}); +---- ok +-STATEMENT CREATE (t:test {prop: 841308}); +---- ok +-STATEMENT CREATE (t:test {prop: 559619}); +---- ok +-STATEMENT CREATE (t:test {prop: 755826}); +---- ok +-STATEMENT CREATE (t:test {prop: 649420}); +---- ok +-STATEMENT CREATE (t:test {prop: 363635}); +---- ok +-STATEMENT CREATE (t:test {prop: 924660}); +---- ok +-STATEMENT CREATE (t:test {prop: 116765}); +---- ok +-STATEMENT CREATE (t:test {prop: 792518}); +---- ok +-STATEMENT CREATE (t:test {prop: 704612}); +---- ok +-STATEMENT CREATE (t:test {prop: 693428}); +---- ok +-STATEMENT CREATE (t:test {prop: 660856}); +---- ok +-STATEMENT CREATE (t:test {prop: 451689}); +---- ok +-STATEMENT CREATE (t:test {prop: 660811}); +---- ok +-STATEMENT CREATE (t:test {prop: 305890}); +---- ok +-STATEMENT CREATE (t:test {prop: 271048}); +---- ok +-STATEMENT CREATE (t:test {prop: 811133}); +---- ok +-STATEMENT CREATE (t:test {prop: 377173}); +---- ok +-STATEMENT CREATE (t:test {prop: 819186}); +---- ok +-STATEMENT CREATE (t:test {prop: 136380}); +---- ok +-STATEMENT CREATE (t:test {prop: 745911}); +---- ok +-STATEMENT CREATE (t:test {prop: 488324}); +---- ok +-STATEMENT CREATE (t:test {prop: 997226}); +---- ok +-STATEMENT CREATE (t:test {prop: 928440}); +---- ok +-STATEMENT CREATE (t:test {prop: 348585}); +---- ok +-STATEMENT CREATE (t:test {prop: 663868}); +---- ok +-STATEMENT CREATE (t:test {prop: 719479}); +---- ok +-STATEMENT CREATE (t:test {prop: 908717}); +---- ok +-STATEMENT CREATE (t:test {prop: 112260}); +---- ok +-STATEMENT CREATE (t:test {prop: 450563}); +---- ok +-STATEMENT CREATE (t:test {prop: 674187}); +---- ok +-STATEMENT CREATE (t:test {prop: 574604}); +---- ok +-STATEMENT CREATE (t:test {prop: 277931}); +---- ok +-STATEMENT CREATE (t:test {prop: 238873}); +---- ok +-STATEMENT CREATE (t:test {prop: 446629}); +---- ok +-STATEMENT CREATE (t:test {prop: 648086}); +---- ok +-STATEMENT CREATE (t:test {prop: 729303}); +---- ok +-STATEMENT CREATE (t:test {prop: 604576}); +---- ok +-STATEMENT CREATE (t:test {prop: 558166}); +---- ok +-STATEMENT CREATE (t:test {prop: 587884}); +---- ok +-STATEMENT CREATE (t:test {prop: 252874}); +---- ok +-STATEMENT CREATE (t:test {prop: 665421}); +---- ok +-STATEMENT CREATE (t:test {prop: 181940}); +---- ok +-STATEMENT CREATE (t:test {prop: 769861}); +---- ok +-STATEMENT CREATE (t:test {prop: 363585}); +---- ok +-STATEMENT CREATE (t:test {prop: 324710}); +---- ok +-STATEMENT CREATE (t:test {prop: 134053}); +---- ok +-STATEMENT CREATE (t:test {prop: 448368}); +---- ok +-STATEMENT CREATE (t:test {prop: 617668}); +---- ok +-STATEMENT CREATE (t:test {prop: 140384}); +---- ok +-STATEMENT CREATE (t:test {prop: 132493}); +---- ok +-STATEMENT CREATE (t:test {prop: 441506}); +---- ok +-STATEMENT CREATE (t:test {prop: 909480}); +---- ok +-STATEMENT CREATE (t:test {prop: 149528}); +---- ok +-STATEMENT CREATE (t:test {prop: 77565}); +---- ok +-STATEMENT CREATE (t:test {prop: 27400}); +---- ok +-STATEMENT CREATE (t:test {prop: 42381}); +---- ok +-STATEMENT CREATE (t:test {prop: 686513}); +---- ok +-STATEMENT CREATE (t:test {prop: 989940}); +---- ok +-STATEMENT CREATE (t:test {prop: 485843}); +---- ok +-STATEMENT CREATE (t:test {prop: 618008}); +---- ok +-STATEMENT CREATE (t:test {prop: 504841}); +---- ok +-STATEMENT CREATE (t:test {prop: 940179}); +---- ok +-STATEMENT CREATE (t:test {prop: 520197}); +---- ok +-STATEMENT CREATE (t:test {prop: 969684}); +---- ok +-STATEMENT CREATE (t:test {prop: 380483}); +---- ok +-STATEMENT CREATE (t:test {prop: 381044}); +---- ok +-STATEMENT CREATE (t:test {prop: 883320}); +---- ok +-STATEMENT CREATE (t:test {prop: 339132}); +---- ok +-STATEMENT CREATE (t:test {prop: 736270}); +---- ok +-STATEMENT CREATE (t:test {prop: 329280}); +---- ok +-STATEMENT CREATE (t:test {prop: 357269}); +---- ok +-STATEMENT CREATE (t:test {prop: 753727}); +---- ok +-STATEMENT CREATE (t:test {prop: 802108}); +---- ok +-STATEMENT CREATE (t:test {prop: 22654}); +---- ok +-STATEMENT CREATE (t:test {prop: 854718}); +---- ok +-STATEMENT CREATE (t:test {prop: 267454}); +---- ok +-STATEMENT CREATE (t:test {prop: 339707}); +---- ok +-STATEMENT CREATE (t:test {prop: 447958}); +---- ok +-STATEMENT CREATE (t:test {prop: 441887}); +---- ok +-STATEMENT CREATE (t:test {prop: 879693}); +---- ok +-STATEMENT CREATE (t:test {prop: 207578}); +---- ok +-STATEMENT CREATE (t:test {prop: 511114}); +---- ok +-STATEMENT CREATE (t:test {prop: 986272}); +---- ok +-STATEMENT CREATE (t:test {prop: 203071}); +---- ok +-STATEMENT CREATE (t:test {prop: 755336}); +---- ok +-STATEMENT CREATE (t:test {prop: 627251}); +---- ok +-STATEMENT CREATE (t:test {prop: 692234}); +---- ok +-STATEMENT CREATE (t:test {prop: 718852}); +---- ok +-STATEMENT CREATE (t:test {prop: 883037}); +---- ok +-STATEMENT CREATE (t:test {prop: 38089}); +---- ok +-STATEMENT CREATE (t:test {prop: 197761}); +---- ok +-STATEMENT CREATE (t:test {prop: 301754}); +---- ok +-STATEMENT CREATE (t:test {prop: 814639}); +---- ok +-STATEMENT CREATE (t:test {prop: 233369}); +---- ok +-STATEMENT CREATE (t:test {prop: 952093}); +---- ok +-STATEMENT CREATE (t:test {prop: 477250}); +---- ok +-STATEMENT CREATE (t:test {prop: 111779}); +---- ok +-STATEMENT CREATE (t:test {prop: 76606}); +---- ok +-STATEMENT CREATE (t:test {prop: 583038}); +---- ok +-STATEMENT CREATE (t:test {prop: 672139}); +---- ok +-STATEMENT CREATE (t:test {prop: 427861}); +---- ok +-STATEMENT CREATE (t:test {prop: 338829}); +---- ok +-STATEMENT CREATE (t:test {prop: 593705}); +---- ok +-STATEMENT CREATE (t:test {prop: 598488}); +---- ok +-STATEMENT CREATE (t:test {prop: 354653}); +---- ok +-STATEMENT CREATE (t:test {prop: 963883}); +---- ok +-STATEMENT CREATE (t:test {prop: 666593}); +---- ok +-STATEMENT CREATE (t:test {prop: 812867}); +---- ok +-STATEMENT CREATE (t:test {prop: 675290}); +---- ok +-STATEMENT CREATE (t:test {prop: 399325}); +---- ok +-STATEMENT CREATE (t:test {prop: 4846}); +---- ok +-STATEMENT CREATE (t:test {prop: 141232}); +---- ok +-STATEMENT CREATE (t:test {prop: 668957}); +---- ok +-STATEMENT CREATE (t:test {prop: 915986}); +---- ok +-STATEMENT CREATE (t:test {prop: 963775}); +---- ok +-STATEMENT CREATE (t:test {prop: 33396}); +---- ok +-STATEMENT CREATE (t:test {prop: 985555}); +---- ok +-STATEMENT CREATE (t:test {prop: 690892}); +---- ok +-STATEMENT CREATE (t:test {prop: 451914}); +---- ok +-STATEMENT CREATE (t:test {prop: 147779}); +---- ok +-STATEMENT CREATE (t:test {prop: 890650}); +---- ok +-STATEMENT CREATE (t:test {prop: 102421}); +---- ok +-STATEMENT CREATE (t:test {prop: 386298}); +---- ok +-STATEMENT CREATE (t:test {prop: 74340}); +---- ok +-STATEMENT CREATE (t:test {prop: 700815}); +---- ok +-STATEMENT CREATE (t:test {prop: 186806}); +---- ok +-STATEMENT CREATE (t:test {prop: 700491}); +---- ok +-STATEMENT CREATE (t:test {prop: 872652}); +---- ok +-STATEMENT CREATE (t:test {prop: 844964}); +---- ok +-STATEMENT CREATE (t:test {prop: 804349}); +---- ok +-STATEMENT CREATE (t:test {prop: 936880}); +---- ok +-STATEMENT CREATE (t:test {prop: 201984}); +---- ok +-STATEMENT CREATE (t:test {prop: 935749}); +---- ok +-STATEMENT CREATE (t:test {prop: 126155}); +---- ok +-STATEMENT CREATE (t:test {prop: 233113}); +---- ok +-STATEMENT CREATE (t:test {prop: 831692}); +---- ok +-STATEMENT CREATE (t:test {prop: 85321}); +---- ok +-STATEMENT CREATE (t:test {prop: 878787}); +---- ok +-STATEMENT CREATE (t:test {prop: 957180}); +---- ok +-STATEMENT CREATE (t:test {prop: 804517}); +---- ok +-STATEMENT CREATE (t:test {prop: 42613}); +---- ok +-STATEMENT CREATE (t:test {prop: 499203}); +---- ok +-STATEMENT CREATE (t:test {prop: 635942}); +---- ok +-STATEMENT CREATE (t:test {prop: 33470}); +---- ok +-STATEMENT CREATE (t:test {prop: 639997}); +---- ok +-STATEMENT CREATE (t:test {prop: 487943}); +---- ok +-STATEMENT CREATE (t:test {prop: 559922}); +---- ok +-STATEMENT CREATE (t:test {prop: 496091}); +---- ok +-STATEMENT CREATE (t:test {prop: 740050}); +---- ok +-STATEMENT CREATE (t:test {prop: 521585}); +---- ok +-STATEMENT CREATE (t:test {prop: 481386}); +---- ok +-STATEMENT CREATE (t:test {prop: 615686}); +---- ok +-STATEMENT CREATE (t:test {prop: 505727}); +---- ok +-STATEMENT CREATE (t:test {prop: 297636}); +---- ok +-STATEMENT CREATE (t:test {prop: 517486}); +---- ok +-STATEMENT CREATE (t:test {prop: 46401}); +---- ok +-STATEMENT CREATE (t:test {prop: 795382}); +---- ok +-STATEMENT CREATE (t:test {prop: 161397}); +---- ok +-STATEMENT CREATE (t:test {prop: 558718}); +---- ok +-STATEMENT CREATE (t:test {prop: 831056}); +---- ok +-STATEMENT CREATE (t:test {prop: 564992}); +---- ok +-STATEMENT CREATE (t:test {prop: 88419}); +---- ok +-STATEMENT CREATE (t:test {prop: 944380}); +---- ok +-STATEMENT CREATE (t:test {prop: 591131}); +---- ok +-STATEMENT CREATE (t:test {prop: 709798}); +---- ok +-STATEMENT CREATE (t:test {prop: 205593}); +---- ok +-STATEMENT CREATE (t:test {prop: 305943}); +---- ok +-STATEMENT CREATE (t:test {prop: 30192}); +---- ok +-STATEMENT CREATE (t:test {prop: 9768}); +---- ok +-STATEMENT CREATE (t:test {prop: 848175}); +---- ok +-STATEMENT CREATE (t:test {prop: 693731}); +---- ok +-STATEMENT CREATE (t:test {prop: 440376}); +---- ok +-STATEMENT CREATE (t:test {prop: 102928}); +---- ok +-STATEMENT CREATE (t:test {prop: 628955}); +---- ok +-STATEMENT CREATE (t:test {prop: 234294}); +---- ok +-STATEMENT CREATE (t:test {prop: 704412}); +---- ok +-STATEMENT CREATE (t:test {prop: 742259}); +---- ok +-STATEMENT CREATE (t:test {prop: 740878}); +---- ok +-STATEMENT CREATE (t:test {prop: 703290}); +---- ok +-STATEMENT CREATE (t:test {prop: 579286}); +---- ok +-STATEMENT CREATE (t:test {prop: 729761}); +---- ok +-STATEMENT CREATE (t:test {prop: 888605}); +---- ok +-STATEMENT CREATE (t:test {prop: 973405}); +---- ok +-STATEMENT CREATE (t:test {prop: 30744}); +---- ok +-STATEMENT CREATE (t:test {prop: 796041}); +---- ok +-STATEMENT CREATE (t:test {prop: 217426}); +---- ok +-STATEMENT CREATE (t:test {prop: 103509}); +---- ok +-STATEMENT CREATE (t:test {prop: 512728}); +---- ok +-STATEMENT CREATE (t:test {prop: 759271}); +---- ok +-STATEMENT CREATE (t:test {prop: 158201}); +---- ok +-STATEMENT CREATE (t:test {prop: 33185}); +---- ok +-STATEMENT CREATE (t:test {prop: 464936}); +---- ok +-STATEMENT CREATE (t:test {prop: 673185}); +---- ok +-STATEMENT CREATE (t:test {prop: 318843}); +---- ok +-STATEMENT CREATE (t:test {prop: 982780}); +---- ok +-STATEMENT CREATE (t:test {prop: 313389}); +---- ok +-STATEMENT CREATE (t:test {prop: 940014}); +---- ok +-STATEMENT CREATE (t:test {prop: 549110}); +---- ok +-STATEMENT CREATE (t:test {prop: 512608}); +---- ok +-STATEMENT CREATE (t:test {prop: 890876}); +---- ok +-STATEMENT CREATE (t:test {prop: 293365}); +---- ok +-STATEMENT CREATE (t:test {prop: 312388}); +---- ok +-STATEMENT CREATE (t:test {prop: 867063}); +---- ok +-STATEMENT CREATE (t:test {prop: 441213}); +---- ok +-STATEMENT CREATE (t:test {prop: 837462}); +---- ok +-STATEMENT CREATE (t:test {prop: 282281}); +---- ok +-STATEMENT CREATE (t:test {prop: 236122}); +---- ok +-STATEMENT CREATE (t:test {prop: 194160}); +---- ok +-STATEMENT CREATE (t:test {prop: 83145}); +---- ok +-STATEMENT CREATE (t:test {prop: 804240}); +---- ok +-STATEMENT CREATE (t:test {prop: 642850}); +---- ok +-STATEMENT CREATE (t:test {prop: 951931}); +---- ok +-STATEMENT CREATE (t:test {prop: 427218}); +---- ok +-STATEMENT CREATE (t:test {prop: 271096}); +---- ok +-STATEMENT CREATE (t:test {prop: 604756}); +---- ok +-STATEMENT CREATE (t:test {prop: 323147}); +---- ok +-STATEMENT CREATE (t:test {prop: 89903}); +---- ok +-STATEMENT CREATE (t:test {prop: 106334}); +---- ok +-STATEMENT CREATE (t:test {prop: 469514}); +---- ok +-STATEMENT CREATE (t:test {prop: 581307}); +---- ok +-STATEMENT CREATE (t:test {prop: 17501}); +---- ok +-STATEMENT CREATE (t:test {prop: 757021}); +---- ok +-STATEMENT CREATE (t:test {prop: 27319}); +---- ok +-STATEMENT CREATE (t:test {prop: 243042}); +---- ok +-STATEMENT CREATE (t:test {prop: 716513}); +---- ok +-STATEMENT CREATE (t:test {prop: 561028}); +---- ok +-STATEMENT CREATE (t:test {prop: 453286}); +---- ok +-STATEMENT CREATE (t:test {prop: 52060}); +---- ok +-STATEMENT CREATE (t:test {prop: 215772}); +---- ok +-STATEMENT CREATE (t:test {prop: 334172}); +---- ok +-STATEMENT CREATE (t:test {prop: 704140}); +---- ok +-STATEMENT CREATE (t:test {prop: 48298}); +---- ok +-STATEMENT CREATE (t:test {prop: 790133}); +---- ok +-STATEMENT CREATE (t:test {prop: 577301}); +---- ok +-STATEMENT CREATE (t:test {prop: 891790}); +---- ok +-STATEMENT CREATE (t:test {prop: 572843}); +---- ok +-STATEMENT CREATE (t:test {prop: 786415}); +---- ok +-STATEMENT CREATE (t:test {prop: 117005}); +---- ok +-STATEMENT CREATE (t:test {prop: 706283}); +---- ok +-STATEMENT CREATE (t:test {prop: 47533}); +---- ok +-STATEMENT CREATE (t:test {prop: 280617}); +---- ok +-STATEMENT CREATE (t:test {prop: 595770}); +---- ok +-STATEMENT CREATE (t:test {prop: 171412}); +---- ok +-STATEMENT CREATE (t:test {prop: 558945}); +---- ok +-STATEMENT CREATE (t:test {prop: 670869}); +---- ok +-STATEMENT CREATE (t:test {prop: 694104}); +---- ok +-STATEMENT CREATE (t:test {prop: 374780}); +---- ok +-STATEMENT CREATE (t:test {prop: 223435}); +---- ok +-STATEMENT CREATE (t:test {prop: 801114}); +---- ok +-STATEMENT CREATE (t:test {prop: 975353}); +---- ok +-STATEMENT CREATE (t:test {prop: 639020}); +---- ok +-STATEMENT CREATE (t:test {prop: 966720}); +---- ok +-STATEMENT CREATE (t:test {prop: 312370}); +---- ok +-STATEMENT CREATE (t:test {prop: 986501}); +---- ok +-STATEMENT CREATE (t:test {prop: 294404}); +---- ok +-STATEMENT CREATE (t:test {prop: 892333}); +---- ok +-STATEMENT CREATE (t:test {prop: 147601}); +---- ok +-STATEMENT CREATE (t:test {prop: 535230}); +---- ok +-STATEMENT CREATE (t:test {prop: 973607}); +---- ok +-STATEMENT CREATE (t:test {prop: 209187}); +---- ok +-STATEMENT CREATE (t:test {prop: 758482}); +---- ok +-STATEMENT CREATE (t:test {prop: 177169}); +---- ok +-STATEMENT CREATE (t:test {prop: 139553}); +---- ok +-STATEMENT CREATE (t:test {prop: 340702}); +---- ok +-STATEMENT CREATE (t:test {prop: 380761}); +---- ok +-STATEMENT CREATE (t:test {prop: 151884}); +---- ok +-STATEMENT CREATE (t:test {prop: 534715}); +---- ok +-STATEMENT CREATE (t:test {prop: 966420}); +---- ok +-STATEMENT CREATE (t:test {prop: 619278}); +---- ok +-STATEMENT CREATE (t:test {prop: 41507}); +---- ok +-STATEMENT CREATE (t:test {prop: 270526}); +---- ok +-STATEMENT CREATE (t:test {prop: 872016}); +---- ok +-STATEMENT CREATE (t:test {prop: 462166}); +---- ok +-STATEMENT CREATE (t:test {prop: 788409}); +---- ok +-STATEMENT CREATE (t:test {prop: 520642}); +---- ok +-STATEMENT CREATE (t:test {prop: 870238}); +---- ok +-STATEMENT CREATE (t:test {prop: 192644}); +---- ok +-STATEMENT CREATE (t:test {prop: 721405}); +---- ok +-STATEMENT CREATE (t:test {prop: 402477}); +---- ok +-STATEMENT CREATE (t:test {prop: 572322}); +---- ok +-STATEMENT CREATE (t:test {prop: 102909}); +---- ok +-STATEMENT CREATE (t:test {prop: 139680}); +---- ok +-STATEMENT CREATE (t:test {prop: 538968}); +---- ok +-STATEMENT CREATE (t:test {prop: 58375}); +---- ok +-STATEMENT CREATE (t:test {prop: 68315}); +---- ok +-STATEMENT CREATE (t:test {prop: 643723}); +---- ok +-STATEMENT CREATE (t:test {prop: 916698}); +---- ok +-STATEMENT CREATE (t:test {prop: 314929}); +---- ok +-STATEMENT CREATE (t:test {prop: 489548}); +---- ok +-STATEMENT CREATE (t:test {prop: 693138}); +---- ok +-STATEMENT CREATE (t:test {prop: 852603}); +---- ok +-STATEMENT CREATE (t:test {prop: 221800}); +---- ok +-STATEMENT CREATE (t:test {prop: 283180}); +---- ok +-STATEMENT CREATE (t:test {prop: 458033}); +---- ok +-STATEMENT CREATE (t:test {prop: 106761}); +---- ok +-STATEMENT CREATE (t:test {prop: 457977}); +---- ok +-STATEMENT CREATE (t:test {prop: 83851}); +---- ok +-STATEMENT CREATE (t:test {prop: 90818}); +---- ok +-STATEMENT CREATE (t:test {prop: 655829}); +---- ok +-STATEMENT CREATE (t:test {prop: 278600}); +---- ok +-STATEMENT CREATE (t:test {prop: 315228}); +---- ok +-STATEMENT CREATE (t:test {prop: 267692}); +---- ok +-STATEMENT CREATE (t:test {prop: 322011}); +---- ok +-STATEMENT CREATE (t:test {prop: 796709}); +---- ok +-STATEMENT CREATE (t:test {prop: 648544}); +---- ok +-STATEMENT CREATE (t:test {prop: 797572}); +---- ok +-STATEMENT CREATE (t:test {prop: 575581}); +---- ok +-STATEMENT CREATE (t:test {prop: 501704}); +---- ok +-STATEMENT CREATE (t:test {prop: 541607}); +---- ok +-STATEMENT CREATE (t:test {prop: 883525}); +---- ok +-STATEMENT CREATE (t:test {prop: 786717}); +---- ok +-STATEMENT CREATE (t:test {prop: 436369}); +---- ok +-STATEMENT CREATE (t:test {prop: 514334}); +---- ok +-STATEMENT CREATE (t:test {prop: 281874}); +---- ok +-STATEMENT CREATE (t:test {prop: 441615}); +---- ok +-STATEMENT CREATE (t:test {prop: 194102}); +---- ok +-STATEMENT CREATE (t:test {prop: 507035}); +---- ok +-STATEMENT CREATE (t:test {prop: 662279}); +---- ok +-STATEMENT CREATE (t:test {prop: 951091}); +---- ok +-STATEMENT CREATE (t:test {prop: 144605}); +---- ok +-STATEMENT CREATE (t:test {prop: 707029}); +---- ok +-STATEMENT CREATE (t:test {prop: 435854}); +---- ok +-STATEMENT CREATE (t:test {prop: 746772}); +---- ok +-STATEMENT CREATE (t:test {prop: 244186}); +---- ok +-STATEMENT CREATE (t:test {prop: 625141}); +---- ok +-STATEMENT CREATE (t:test {prop: 397082}); +---- ok +-STATEMENT CREATE (t:test {prop: 508388}); +---- ok +-STATEMENT CREATE (t:test {prop: 657624}); +---- ok +-STATEMENT CREATE (t:test {prop: 318978}); +---- ok +-STATEMENT CREATE (t:test {prop: 433471}); +---- ok +-STATEMENT CREATE (t:test {prop: 551958}); +---- ok +-STATEMENT CREATE (t:test {prop: 711341}); +---- ok +-STATEMENT CREATE (t:test {prop: 979200}); +---- ok +-STATEMENT CREATE (t:test {prop: 220485}); +---- ok +-STATEMENT CREATE (t:test {prop: 452482}); +---- ok +-STATEMENT CREATE (t:test {prop: 384122}); +---- ok +-STATEMENT CREATE (t:test {prop: 539330}); +---- ok +-STATEMENT CREATE (t:test {prop: 485079}); +---- ok +-STATEMENT CREATE (t:test {prop: 635146}); +---- ok +-STATEMENT CREATE (t:test {prop: 784007}); +---- ok +-STATEMENT CREATE (t:test {prop: 707090}); +---- ok +-STATEMENT CREATE (t:test {prop: 518374}); +---- ok +-STATEMENT CREATE (t:test {prop: 19977}); +---- ok +-STATEMENT CREATE (t:test {prop: 509580}); +---- ok +-STATEMENT CREATE (t:test {prop: 420047}); +---- ok +-STATEMENT CREATE (t:test {prop: 589346}); +---- ok +-STATEMENT CREATE (t:test {prop: 242757}); +---- ok +-STATEMENT CREATE (t:test {prop: 768963}); +---- ok +-STATEMENT CREATE (t:test {prop: 357817}); +---- ok +-STATEMENT CREATE (t:test {prop: 234004}); +---- ok +-STATEMENT CREATE (t:test {prop: 200467}); +---- ok +-STATEMENT CREATE (t:test {prop: 967768}); +---- ok +-STATEMENT CREATE (t:test {prop: 451582}); +---- ok +-STATEMENT CREATE (t:test {prop: 764578}); +---- ok +-STATEMENT CREATE (t:test {prop: 679013}); +---- ok +-STATEMENT CREATE (t:test {prop: 940310}); +---- ok +-STATEMENT CREATE (t:test {prop: 270408}); +---- ok +-STATEMENT CREATE (t:test {prop: 302669}); +---- ok +-STATEMENT CREATE (t:test {prop: 929262}); +---- ok +-STATEMENT CREATE (t:test {prop: 927710}); +---- ok +-STATEMENT CREATE (t:test {prop: 838482}); +---- ok +-STATEMENT CREATE (t:test {prop: 732681}); +---- ok +-STATEMENT CREATE (t:test {prop: 623416}); +---- ok +-STATEMENT CREATE (t:test {prop: 324346}); +---- ok +-STATEMENT CREATE (t:test {prop: 176095}); +---- ok +-STATEMENT CREATE (t:test {prop: 906265}); +---- ok +-STATEMENT CREATE (t:test {prop: 734618}); +---- ok +-STATEMENT CREATE (t:test {prop: 522601}); +---- ok +-STATEMENT CREATE (t:test {prop: 219376}); +---- ok +-STATEMENT CREATE (t:test {prop: 458087}); +---- ok +-STATEMENT CREATE (t:test {prop: 363914}); +---- ok +-STATEMENT CREATE (t:test {prop: 342444}); +---- ok +-STATEMENT CREATE (t:test {prop: 876355}); +---- ok +-STATEMENT CREATE (t:test {prop: 632700}); +---- ok +-STATEMENT CREATE (t:test {prop: 129700}); +---- ok +-STATEMENT CREATE (t:test {prop: 108735}); +---- ok +-STATEMENT CREATE (t:test {prop: 879547}); +---- ok +-STATEMENT CREATE (t:test {prop: 221869}); +---- ok +-STATEMENT CREATE (t:test {prop: 840275}); +---- ok +-STATEMENT CREATE (t:test {prop: 516608}); +---- ok +-STATEMENT CREATE (t:test {prop: 661422}); +---- ok +-STATEMENT CREATE (t:test {prop: 158403}); +---- ok +-STATEMENT CREATE (t:test {prop: 938476}); +---- ok +-STATEMENT CREATE (t:test {prop: 455122}); +---- ok +-STATEMENT CREATE (t:test {prop: 28172}); +---- ok +-STATEMENT CREATE (t:test {prop: 940124}); +---- ok +-STATEMENT CREATE (t:test {prop: 514992}); +---- ok +-STATEMENT CREATE (t:test {prop: 702774}); +---- ok +-STATEMENT CREATE (t:test {prop: 252257}); +---- ok +-STATEMENT CREATE (t:test {prop: 896652}); +---- ok +-STATEMENT CREATE (t:test {prop: 220212}); +---- ok +-STATEMENT CREATE (t:test {prop: 556299}); +---- ok +-STATEMENT CREATE (t:test {prop: 725818}); +---- ok +-STATEMENT CREATE (t:test {prop: 361499}); +---- ok +-STATEMENT CREATE (t:test {prop: 853667}); +---- ok +-STATEMENT CREATE (t:test {prop: 989393}); +---- ok +-STATEMENT CREATE (t:test {prop: 817876}); +---- ok +-STATEMENT CREATE (t:test {prop: 176820}); +---- ok +-STATEMENT CREATE (t:test {prop: 166532}); +---- ok +-STATEMENT CREATE (t:test {prop: 206459}); +---- ok +-STATEMENT CREATE (t:test {prop: 839395}); +---- ok +-STATEMENT CREATE (t:test {prop: 147016}); +---- ok +-STATEMENT CREATE (t:test {prop: 22865}); +---- ok +-STATEMENT CREATE (t:test {prop: 672798}); +---- ok +-STATEMENT CREATE (t:test {prop: 173107}); +---- ok +-STATEMENT CREATE (t:test {prop: 601489}); +---- ok +-STATEMENT CREATE (t:test {prop: 478100}); +---- ok +-STATEMENT CREATE (t:test {prop: 909340}); +---- ok +-STATEMENT CREATE (t:test {prop: 565183}); +---- ok +-STATEMENT CREATE (t:test {prop: 128780}); +---- ok +-STATEMENT CREATE (t:test {prop: 386062}); +---- ok +-STATEMENT CREATE (t:test {prop: 726828}); +---- ok +-STATEMENT CREATE (t:test {prop: 953093}); +---- ok +-STATEMENT CREATE (t:test {prop: 579724}); +---- ok +-STATEMENT CREATE (t:test {prop: 222855}); +---- ok +-STATEMENT CREATE (t:test {prop: 307064}); +---- ok +-STATEMENT CREATE (t:test {prop: 493850}); +---- ok +-STATEMENT CREATE (t:test {prop: 490953}); +---- ok +-STATEMENT CREATE (t:test {prop: 570965}); +---- ok +-STATEMENT CREATE (t:test {prop: 593999}); +---- ok +-STATEMENT CREATE (t:test {prop: 668668}); +---- ok +-STATEMENT CREATE (t:test {prop: 528897}); +---- ok +-STATEMENT CREATE (t:test {prop: 960897}); +---- ok +-STATEMENT CREATE (t:test {prop: 534674}); +---- ok +-STATEMENT CREATE (t:test {prop: 959821}); +---- ok +-STATEMENT CREATE (t:test {prop: 268912}); +---- ok +-STATEMENT CREATE (t:test {prop: 301880}); +---- ok +-STATEMENT CREATE (t:test {prop: 624961}); +---- ok +-STATEMENT CREATE (t:test {prop: 977396}); +---- ok +-STATEMENT CREATE (t:test {prop: 326247}); +---- ok +-STATEMENT CREATE (t:test {prop: 700544}); +---- ok +-STATEMENT CREATE (t:test {prop: 103252}); +---- ok +-STATEMENT CREATE (t:test {prop: 254767}); +---- ok +-STATEMENT CREATE (t:test {prop: 270289}); +---- ok +-STATEMENT CREATE (t:test {prop: 460919}); +---- ok +-STATEMENT CREATE (t:test {prop: 409083}); +---- ok +-STATEMENT CREATE (t:test {prop: 989891}); +---- ok +-STATEMENT CREATE (t:test {prop: 60004}); +---- ok +-STATEMENT CREATE (t:test {prop: 841614}); +---- ok +-STATEMENT CREATE (t:test {prop: 607497}); +---- ok +-STATEMENT CREATE (t:test {prop: 677064}); +---- ok +-STATEMENT CREATE (t:test {prop: 646795}); +---- ok +-STATEMENT CREATE (t:test {prop: 548131}); +---- ok +-STATEMENT CREATE (t:test {prop: 66656}); +---- ok +-STATEMENT CREATE (t:test {prop: 426488}); +---- ok +-STATEMENT CREATE (t:test {prop: 149584}); +---- ok +-STATEMENT CREATE (t:test {prop: 933458}); +---- ok +-STATEMENT CREATE (t:test {prop: 780693}); +---- ok +-STATEMENT CREATE (t:test {prop: 417990}); +---- ok +-STATEMENT CREATE (t:test {prop: 363210}); +---- ok +-STATEMENT CREATE (t:test {prop: 30937}); +---- ok +-STATEMENT CREATE (t:test {prop: 687898}); +---- ok +-STATEMENT CREATE (t:test {prop: 918384}); +---- ok +-STATEMENT CREATE (t:test {prop: 359348}); +---- ok +-STATEMENT CREATE (t:test {prop: 910041}); +---- ok +-STATEMENT CREATE (t:test {prop: 189823}); +---- ok +-STATEMENT CREATE (t:test {prop: 880075}); +---- ok +-STATEMENT CREATE (t:test {prop: 102431}); +---- ok +-STATEMENT CREATE (t:test {prop: 354141}); +---- ok +-STATEMENT CREATE (t:test {prop: 339734}); +---- ok +-STATEMENT CREATE (t:test {prop: 52982}); +---- ok +-STATEMENT CREATE (t:test {prop: 864825}); +---- ok +-STATEMENT CREATE (t:test {prop: 157643}); +---- ok +-STATEMENT CREATE (t:test {prop: 579563}); +---- ok +-STATEMENT CREATE (t:test {prop: 914095}); +---- ok +-STATEMENT CREATE (t:test {prop: 438283}); +---- ok +-STATEMENT CREATE (t:test {prop: 271249}); +---- ok +-STATEMENT CREATE (t:test {prop: 217259}); +---- ok +-STATEMENT CREATE (t:test {prop: 303587}); +---- ok +-STATEMENT CREATE (t:test {prop: 131963}); +---- ok +-STATEMENT CREATE (t:test {prop: 622814}); +---- ok +-STATEMENT CREATE (t:test {prop: 994829}); +---- ok +-STATEMENT CREATE (t:test {prop: 242677}); +---- ok +-STATEMENT CREATE (t:test {prop: 636383}); +---- ok +-STATEMENT CREATE (t:test {prop: 337113}); +---- ok +-STATEMENT CREATE (t:test {prop: 988046}); +---- ok +-STATEMENT CREATE (t:test {prop: 660094}); +---- ok +-STATEMENT CREATE (t:test {prop: 806104}); +---- ok +-STATEMENT CREATE (t:test {prop: 82405}); +---- ok +-STATEMENT CREATE (t:test {prop: 86998}); +---- ok +-STATEMENT CREATE (t:test {prop: 213773}); +---- ok +-STATEMENT CREATE (t:test {prop: 922428}); +---- ok +-STATEMENT CREATE (t:test {prop: 630936}); +---- ok +-STATEMENT CREATE (t:test {prop: 520192}); +---- ok +-STATEMENT CREATE (t:test {prop: 37953}); +---- ok +-STATEMENT CREATE (t:test {prop: 420498}); +---- ok +-STATEMENT CREATE (t:test {prop: 359270}); +---- ok +-STATEMENT CREATE (t:test {prop: 306338}); +---- ok +-STATEMENT CREATE (t:test {prop: 498989}); +---- ok +-STATEMENT CREATE (t:test {prop: 202280}); +---- ok +-STATEMENT CREATE (t:test {prop: 476068}); +---- ok +-STATEMENT CREATE (t:test {prop: 407519}); +---- ok +-STATEMENT CREATE (t:test {prop: 458904}); +---- ok +-STATEMENT CREATE (t:test {prop: 427075}); +---- ok +-STATEMENT CREATE (t:test {prop: 637291}); +---- ok +-STATEMENT CREATE (t:test {prop: 788125}); +---- ok +-STATEMENT CREATE (t:test {prop: 701034}); +---- ok +-STATEMENT CREATE (t:test {prop: 598755}); +---- ok +-STATEMENT CREATE (t:test {prop: 733843}); +---- ok +-STATEMENT CREATE (t:test {prop: 912889}); +---- ok +-STATEMENT CREATE (t:test {prop: 936971}); +---- ok +-STATEMENT CREATE (t:test {prop: 443780}); +---- ok +-STATEMENT CREATE (t:test {prop: 197993}); +---- ok +-STATEMENT CREATE (t:test {prop: 630798}); +---- ok +-STATEMENT CREATE (t:test {prop: 738234}); +---- ok +-STATEMENT CREATE (t:test {prop: 755639}); +---- ok +-STATEMENT CREATE (t:test {prop: 203390}); +---- ok +-STATEMENT CREATE (t:test {prop: 887849}); +---- ok +-STATEMENT CREATE (t:test {prop: 254438}); +---- ok +-STATEMENT CREATE (t:test {prop: 159440}); +---- ok +-STATEMENT CREATE (t:test {prop: 245536}); +---- ok +-STATEMENT CREATE (t:test {prop: 440461}); +---- ok +-STATEMENT CREATE (t:test {prop: 197273}); +---- ok +-STATEMENT CREATE (t:test {prop: 416303}); +---- ok +-STATEMENT CREATE (t:test {prop: 439380}); +---- ok +-STATEMENT CREATE (t:test {prop: 817032}); +---- ok +-STATEMENT CREATE (t:test {prop: 861513}); +---- ok +-STATEMENT CREATE (t:test {prop: 617062}); +---- ok +-STATEMENT CREATE (t:test {prop: 722819}); +---- ok +-STATEMENT CREATE (t:test {prop: 219408}); +---- ok +-STATEMENT CREATE (t:test {prop: 495488}); +---- ok +-STATEMENT CREATE (t:test {prop: 640464}); +---- ok +-STATEMENT CREATE (t:test {prop: 188831}); +---- ok +-STATEMENT CREATE (t:test {prop: 350343}); +---- ok +-STATEMENT CREATE (t:test {prop: 695787}); +---- ok +-STATEMENT CREATE (t:test {prop: 671039}); +---- ok +-STATEMENT CREATE (t:test {prop: 87711}); +---- ok +-STATEMENT CREATE (t:test {prop: 786982}); +---- ok +-STATEMENT CREATE (t:test {prop: 379531}); +---- ok +-STATEMENT CREATE (t:test {prop: 350335}); +---- ok +-STATEMENT CREATE (t:test {prop: 97732}); +---- ok +-STATEMENT CREATE (t:test {prop: 7103}); +---- ok +-STATEMENT CREATE (t:test {prop: 917952}); +---- ok +-STATEMENT CREATE (t:test {prop: 136675}); +---- ok +-STATEMENT CREATE (t:test {prop: 694148}); +---- ok +-STATEMENT CREATE (t:test {prop: 595695}); +---- ok +-STATEMENT CREATE (t:test {prop: 524122}); +---- ok +-STATEMENT CREATE (t:test {prop: 73725}); +---- ok +-STATEMENT CREATE (t:test {prop: 917310}); +---- ok +-STATEMENT CREATE (t:test {prop: 44674}); +---- ok +-STATEMENT CREATE (t:test {prop: 817623}); +---- ok +-STATEMENT CREATE (t:test {prop: 99439}); +---- ok +-STATEMENT CREATE (t:test {prop: 654238}); +---- ok +-STATEMENT CREATE (t:test {prop: 717928}); +---- ok +-STATEMENT CREATE (t:test {prop: 54250}); +---- ok +-STATEMENT CREATE (t:test {prop: 579568}); +---- ok +-STATEMENT CREATE (t:test {prop: 174495}); +---- ok +-STATEMENT CREATE (t:test {prop: 815121}); +---- ok +-STATEMENT CREATE (t:test {prop: 832497}); +---- ok +-STATEMENT CREATE (t:test {prop: 946370}); +---- ok +-STATEMENT CREATE (t:test {prop: 97958}); +---- ok +-STATEMENT CREATE (t:test {prop: 482376}); +---- ok +-STATEMENT CREATE (t:test {prop: 351240}); +---- ok +-STATEMENT CREATE (t:test {prop: 829832}); +---- ok +-STATEMENT CREATE (t:test {prop: 376926}); +---- ok +-STATEMENT CREATE (t:test {prop: 413123}); +---- ok +-STATEMENT CREATE (t:test {prop: 406837}); +---- ok +-STATEMENT CREATE (t:test {prop: 53065}); +---- ok +-STATEMENT CREATE (t:test {prop: 475371}); +---- ok +-STATEMENT CREATE (t:test {prop: 562149}); +---- ok +-STATEMENT CREATE (t:test {prop: 664548}); +---- ok +-STATEMENT CREATE (t:test {prop: 254516}); +---- ok +-STATEMENT CREATE (t:test {prop: 21968}); +---- ok +-STATEMENT CREATE (t:test {prop: 203831}); +---- ok +-STATEMENT CREATE (t:test {prop: 43033}); +---- ok +-STATEMENT CREATE (t:test {prop: 116343}); +---- ok +-STATEMENT CREATE (t:test {prop: 587827}); +---- ok +-STATEMENT CREATE (t:test {prop: 552339}); +---- ok +-STATEMENT CREATE (t:test {prop: 843812}); +---- ok +-STATEMENT CREATE (t:test {prop: 728369}); +---- ok +-STATEMENT CREATE (t:test {prop: 599588}); +---- ok +-STATEMENT CREATE (t:test {prop: 217655}); +---- ok +-STATEMENT CREATE (t:test {prop: 345036}); +---- ok +-STATEMENT CREATE (t:test {prop: 434470}); +---- ok +-STATEMENT CREATE (t:test {prop: 432548}); +---- ok +-STATEMENT CREATE (t:test {prop: 177049}); +---- ok +-STATEMENT CREATE (t:test {prop: 507546}); +---- ok +-STATEMENT CREATE (t:test {prop: 404164}); +---- ok +-STATEMENT CREATE (t:test {prop: 13073}); +---- ok +-STATEMENT CREATE (t:test {prop: 101587}); +---- ok +-STATEMENT CREATE (t:test {prop: 124538}); +---- ok +-STATEMENT CREATE (t:test {prop: 309177}); +---- ok +-STATEMENT CREATE (t:test {prop: 367619}); +---- ok +-STATEMENT CREATE (t:test {prop: 149463}); +---- ok +-STATEMENT CREATE (t:test {prop: 546763}); +---- ok +-STATEMENT CREATE (t:test {prop: 144619}); +---- ok +-STATEMENT CREATE (t:test {prop: 419507}); +---- ok +-STATEMENT CREATE (t:test {prop: 728130}); +---- ok +-STATEMENT CREATE (t:test {prop: 967265}); +---- ok +-STATEMENT CREATE (t:test {prop: 574534}); +---- ok +-STATEMENT CREATE (t:test {prop: 794893}); +---- ok +-STATEMENT CREATE (t:test {prop: 736645}); +---- ok +-STATEMENT CREATE (t:test {prop: 656193}); +---- ok +-STATEMENT CREATE (t:test {prop: 791758}); +---- ok +-STATEMENT CREATE (t:test {prop: 532991}); +---- ok +-STATEMENT CREATE (t:test {prop: 255631}); +---- ok +-STATEMENT CREATE (t:test {prop: 502875}); +---- ok +-STATEMENT CREATE (t:test {prop: 315633}); +---- ok +-STATEMENT CREATE (t:test {prop: 855656}); +---- ok +-STATEMENT CREATE (t:test {prop: 800396}); +---- ok +-STATEMENT CREATE (t:test {prop: 59362}); +---- ok +-STATEMENT CREATE (t:test {prop: 393856}); +---- ok +-STATEMENT CREATE (t:test {prop: 320436}); +---- ok +-STATEMENT CREATE (t:test {prop: 343703}); +---- ok +-STATEMENT CREATE (t:test {prop: 272776}); +---- ok +-STATEMENT CREATE (t:test {prop: 229107}); +---- ok +-STATEMENT CREATE (t:test {prop: 345351}); +---- ok +-STATEMENT CREATE (t:test {prop: 86581}); +---- ok +-STATEMENT CREATE (t:test {prop: 137472}); +---- ok +-STATEMENT CREATE (t:test {prop: 488921}); +---- ok +-STATEMENT CREATE (t:test {prop: 861566}); +---- ok +-STATEMENT CREATE (t:test {prop: 333847}); +---- ok +-STATEMENT CREATE (t:test {prop: 438771}); +---- ok +-STATEMENT CREATE (t:test {prop: 694430}); +---- ok +-STATEMENT CREATE (t:test {prop: 309178}); +---- ok +-STATEMENT CREATE (t:test {prop: 441751}); +---- ok +-STATEMENT CREATE (t:test {prop: 605024}); +---- ok +-STATEMENT CREATE (t:test {prop: 675665}); +---- ok +-STATEMENT CREATE (t:test {prop: 832180}); +---- ok +-STATEMENT CREATE (t:test {prop: 302304}); +---- ok +-STATEMENT CREATE (t:test {prop: 782842}); +---- ok +-STATEMENT CREATE (t:test {prop: 982314}); +---- ok +-STATEMENT CREATE (t:test {prop: 538520}); +---- ok +-STATEMENT CREATE (t:test {prop: 384790}); +---- ok +-STATEMENT CREATE (t:test {prop: 902370}); +---- ok +-STATEMENT CREATE (t:test {prop: 967741}); +---- ok +-STATEMENT CREATE (t:test {prop: 899890}); +---- ok +-STATEMENT CREATE (t:test {prop: 715689}); +---- ok +-STATEMENT CREATE (t:test {prop: 395190}); +---- ok +-STATEMENT CREATE (t:test {prop: 418799}); +---- ok +-STATEMENT CREATE (t:test {prop: 668799}); +---- ok +-STATEMENT CREATE (t:test {prop: 52844}); +---- ok +-STATEMENT CREATE (t:test {prop: 327028}); +---- ok +-STATEMENT CREATE (t:test {prop: 774455}); +---- ok +-STATEMENT CREATE (t:test {prop: 928285}); +---- ok +-STATEMENT CREATE (t:test {prop: 790847}); +---- ok +-STATEMENT CREATE (t:test {prop: 807013}); +---- ok +-STATEMENT CREATE (t:test {prop: 856572}); +---- ok +-STATEMENT CREATE (t:test {prop: 486113}); +---- ok +-STATEMENT CREATE (t:test {prop: 412134}); +---- ok +-STATEMENT CREATE (t:test {prop: 680454}); +---- ok +-STATEMENT CREATE (t:test {prop: 817474}); +---- ok +-STATEMENT CREATE (t:test {prop: 710814}); +---- ok +-STATEMENT CREATE (t:test {prop: 955610}); +---- ok +-STATEMENT CREATE (t:test {prop: 207034}); +---- ok +-STATEMENT CREATE (t:test {prop: 118628}); +---- ok +-STATEMENT CREATE (t:test {prop: 758027}); +---- ok +-STATEMENT CREATE (t:test {prop: 154716}); +---- ok +-STATEMENT CREATE (t:test {prop: 94886}); +---- ok +-STATEMENT CREATE (t:test {prop: 816593}); +---- ok +-STATEMENT CREATE (t:test {prop: 991940}); +---- ok +-STATEMENT CREATE (t:test {prop: 794319}); +---- ok +-STATEMENT CREATE (t:test {prop: 672561}); +---- ok +-STATEMENT CREATE (t:test {prop: 661770}); +---- ok +-STATEMENT CREATE (t:test {prop: 711937}); +---- ok +-STATEMENT CREATE (t:test {prop: 134855}); +---- ok +-STATEMENT CREATE (t:test {prop: 653450}); +---- ok +-STATEMENT CREATE (t:test {prop: 905556}); +---- ok +-STATEMENT CREATE (t:test {prop: 839155}); +---- ok +-STATEMENT CREATE (t:test {prop: 97286}); +---- ok +-STATEMENT CREATE (t:test {prop: 941306}); +---- ok +-STATEMENT CREATE (t:test {prop: 641821}); +---- ok +-STATEMENT CREATE (t:test {prop: 633898}); +---- ok +-STATEMENT CREATE (t:test {prop: 784219}); +---- ok +-STATEMENT CREATE (t:test {prop: 556483}); +---- ok +-STATEMENT CREATE (t:test {prop: 484652}); +---- ok +-STATEMENT CREATE (t:test {prop: 98221}); +---- ok +-STATEMENT CREATE (t:test {prop: 929541}); +---- ok +-STATEMENT CREATE (t:test {prop: 6598}); +---- ok +-STATEMENT CREATE (t:test {prop: 173479}); +---- ok +-STATEMENT CREATE (t:test {prop: 926364}); +---- ok +-STATEMENT CREATE (t:test {prop: 565778}); +---- ok +-STATEMENT CREATE (t:test {prop: 889791}); +---- ok +-STATEMENT CREATE (t:test {prop: 500948}); +---- ok +-STATEMENT CREATE (t:test {prop: 286073}); +---- ok +-STATEMENT CREATE (t:test {prop: 281238}); +---- ok +-STATEMENT CREATE (t:test {prop: 965674}); +---- ok +-STATEMENT CREATE (t:test {prop: 183963}); +---- ok +-STATEMENT CREATE (t:test {prop: 583574}); +---- ok +-STATEMENT CREATE (t:test {prop: 847350}); +---- ok +-STATEMENT CREATE (t:test {prop: 152378}); +---- ok +-STATEMENT CREATE (t:test {prop: 786589}); +---- ok +-STATEMENT CREATE (t:test {prop: 384874}); +---- ok +-STATEMENT CREATE (t:test {prop: 620295}); +---- ok +-STATEMENT CREATE (t:test {prop: 88349}); +---- ok +-STATEMENT CREATE (t:test {prop: 404898}); +---- ok +-STATEMENT CREATE (t:test {prop: 466567}); +---- ok +-STATEMENT CREATE (t:test {prop: 151511}); +---- ok +-STATEMENT CREATE (t:test {prop: 778038}); +---- ok +-STATEMENT CREATE (t:test {prop: 655031}); +---- ok +-STATEMENT CREATE (t:test {prop: 66903}); +---- ok +-STATEMENT CREATE (t:test {prop: 407534}); +---- ok +-STATEMENT CREATE (t:test {prop: 748699}); +---- ok +-STATEMENT CREATE (t:test {prop: 76174}); +---- ok +-STATEMENT CREATE (t:test {prop: 450800}); +---- ok +-STATEMENT CREATE (t:test {prop: 787153}); +---- ok +-STATEMENT CREATE (t:test {prop: 561895}); +---- ok +-STATEMENT CREATE (t:test {prop: 86584}); +---- ok +-STATEMENT CREATE (t:test {prop: 122130}); +---- ok +-STATEMENT CREATE (t:test {prop: 792714}); +---- ok +-STATEMENT CREATE (t:test {prop: 430716}); +---- ok +-STATEMENT CREATE (t:test {prop: 19231}); +---- ok +-STATEMENT CREATE (t:test {prop: 91852}); +---- ok +-STATEMENT CREATE (t:test {prop: 597149}); +---- ok +-STATEMENT CREATE (t:test {prop: 340732}); +---- ok +-STATEMENT CREATE (t:test {prop: 449305}); +---- ok +-STATEMENT CREATE (t:test {prop: 139761}); +---- ok +-STATEMENT CREATE (t:test {prop: 871156}); +---- ok +-STATEMENT CREATE (t:test {prop: 700053}); +---- ok +-STATEMENT CREATE (t:test {prop: 572790}); +---- ok +-STATEMENT CREATE (t:test {prop: 252764}); +---- ok +-STATEMENT CREATE (t:test {prop: 863261}); +---- ok +-STATEMENT CREATE (t:test {prop: 936767}); +---- ok +-STATEMENT CREATE (t:test {prop: 288614}); +---- ok +-STATEMENT CREATE (t:test {prop: 173532}); +---- ok +-STATEMENT CREATE (t:test {prop: 137693}); +---- ok +-STATEMENT CREATE (t:test {prop: 35022}); +---- ok +-STATEMENT CREATE (t:test {prop: 38738}); +---- ok +-STATEMENT CREATE (t:test {prop: 454057}); +---- ok +-STATEMENT CREATE (t:test {prop: 799919}); +---- ok +-STATEMENT CREATE (t:test {prop: 817993}); +---- ok +-STATEMENT CREATE (t:test {prop: 431313}); +---- ok +-STATEMENT CREATE (t:test {prop: 744998}); +---- ok +-STATEMENT CREATE (t:test {prop: 56902}); +---- ok +-STATEMENT CREATE (t:test {prop: 564776}); +---- ok +-STATEMENT CREATE (t:test {prop: 35395}); +---- ok +-STATEMENT CREATE (t:test {prop: 14286}); +---- ok +-STATEMENT CREATE (t:test {prop: 237618}); +---- ok +-STATEMENT CREATE (t:test {prop: 186490}); +---- ok +-STATEMENT CREATE (t:test {prop: 551453}); +---- ok +-STATEMENT CREATE (t:test {prop: 392297}); +---- ok +-STATEMENT CREATE (t:test {prop: 218562}); +---- ok +-STATEMENT CREATE (t:test {prop: 98294}); +---- ok +-STATEMENT CREATE (t:test {prop: 858513}); +---- ok +-STATEMENT CREATE (t:test {prop: 535959}); +---- ok +-STATEMENT CREATE (t:test {prop: 869145}); +---- ok +-STATEMENT CREATE (t:test {prop: 666184}); +---- ok +-STATEMENT CREATE (t:test {prop: 804708}); +---- ok +-STATEMENT CREATE (t:test {prop: 566911}); +---- ok +-STATEMENT CREATE (t:test {prop: 882276}); +---- ok +-STATEMENT CREATE (t:test {prop: 984685}); +---- ok +-STATEMENT CREATE (t:test {prop: 250341}); +---- ok +-STATEMENT CREATE (t:test {prop: 110429}); +---- ok +-STATEMENT CREATE (t:test {prop: 134878}); +---- ok +-STATEMENT CREATE (t:test {prop: 51654}); +---- ok +-STATEMENT CREATE (t:test {prop: 580121}); +---- ok +-STATEMENT CREATE (t:test {prop: 594494}); +---- ok +-STATEMENT CREATE (t:test {prop: 313626}); +---- ok +-STATEMENT CREATE (t:test {prop: 333552}); +---- ok +-STATEMENT CREATE (t:test {prop: 109014}); +---- ok +-STATEMENT CREATE (t:test {prop: 140305}); +---- ok +-STATEMENT CREATE (t:test {prop: 220774}); +---- ok +-STATEMENT CREATE (t:test {prop: 623584}); +---- ok +-STATEMENT CREATE (t:test {prop: 395857}); +---- ok +-STATEMENT CREATE (t:test {prop: 343965}); +---- ok +-STATEMENT CREATE (t:test {prop: 126735}); +---- ok +-STATEMENT CREATE (t:test {prop: 783729}); +---- ok +-STATEMENT CREATE (t:test {prop: 818439}); +---- ok +-STATEMENT CREATE (t:test {prop: 530337}); +---- ok +-STATEMENT CREATE (t:test {prop: 220551}); +---- ok +-STATEMENT CREATE (t:test {prop: 619189}); +---- ok +-STATEMENT CREATE (t:test {prop: 339470}); +---- ok +-STATEMENT CREATE (t:test {prop: 546689}); +---- ok +-STATEMENT CREATE (t:test {prop: 127910}); +---- ok +-STATEMENT CREATE (t:test {prop: 623681}); +---- ok +-STATEMENT CREATE (t:test {prop: 27214}); +---- ok +-STATEMENT CREATE (t:test {prop: 818685}); +---- ok +-STATEMENT CREATE (t:test {prop: 917667}); +---- ok +-STATEMENT CREATE (t:test {prop: 520703}); +---- ok +-STATEMENT CREATE (t:test {prop: 134470}); +---- ok +-STATEMENT CREATE (t:test {prop: 402722}); +---- ok +-STATEMENT CREATE (t:test {prop: 221161}); +---- ok +-STATEMENT CREATE (t:test {prop: 323996}); +---- ok +-STATEMENT CREATE (t:test {prop: 176840}); +---- ok +-STATEMENT CREATE (t:test {prop: 800424}); +---- ok +-STATEMENT CREATE (t:test {prop: 871914}); +---- ok +-STATEMENT CREATE (t:test {prop: 165009}); +---- ok +-STATEMENT CREATE (t:test {prop: 588274}); +---- ok +-STATEMENT CREATE (t:test {prop: 221413}); +---- ok +-STATEMENT CREATE (t:test {prop: 192914}); +---- ok +-STATEMENT CREATE (t:test {prop: 697630}); +---- ok +-STATEMENT CREATE (t:test {prop: 997973}); +---- ok +-STATEMENT CREATE (t:test {prop: 237959}); +---- ok +-STATEMENT CREATE (t:test {prop: 14669}); +---- ok +-STATEMENT CREATE (t:test {prop: 878750}); +---- ok +-STATEMENT CREATE (t:test {prop: 717886}); +---- ok +-STATEMENT CREATE (t:test {prop: 353705}); +---- ok +-STATEMENT CREATE (t:test {prop: 940973}); +---- ok +-STATEMENT CREATE (t:test {prop: 349757}); +---- ok +-STATEMENT CREATE (t:test {prop: 219752}); +---- ok +-STATEMENT CREATE (t:test {prop: 297444}); +---- ok +-STATEMENT CREATE (t:test {prop: 419663}); +---- ok +-STATEMENT CREATE (t:test {prop: 895870}); +---- ok +-STATEMENT CREATE (t:test {prop: 470768}); +---- ok +-STATEMENT CREATE (t:test {prop: 527004}); +---- ok +-STATEMENT CREATE (t:test {prop: 286042}); +---- ok +-STATEMENT CREATE (t:test {prop: 196616}); +---- ok +-STATEMENT CREATE (t:test {prop: 688746}); +---- ok +-STATEMENT CREATE (t:test {prop: 342202}); +---- ok +-STATEMENT CREATE (t:test {prop: 60417}); +---- ok +-STATEMENT CREATE (t:test {prop: 846882}); +---- ok +-STATEMENT CREATE (t:test {prop: 130958}); +---- ok +-STATEMENT CREATE (t:test {prop: 159779}); +---- ok +-STATEMENT CREATE (t:test {prop: 933254}); +---- ok +-STATEMENT CREATE (t:test {prop: 209722}); +---- ok +-STATEMENT CREATE (t:test {prop: 817937}); +---- ok +-STATEMENT CREATE (t:test {prop: 497649}); +---- ok +-STATEMENT CREATE (t:test {prop: 961238}); +---- ok +-STATEMENT CREATE (t:test {prop: 368441}); +---- ok +-STATEMENT CREATE (t:test {prop: 928726}); +---- ok +-STATEMENT CREATE (t:test {prop: 806346}); +---- ok +-STATEMENT CREATE (t:test {prop: 135346}); +---- ok +-STATEMENT CREATE (t:test {prop: 318816}); +---- ok +-STATEMENT CREATE (t:test {prop: 785645}); +---- ok +-STATEMENT CREATE (t:test {prop: 139795}); +---- ok +-STATEMENT CREATE (t:test {prop: 746391}); +---- ok +-STATEMENT CREATE (t:test {prop: 201469}); +---- ok +-STATEMENT CREATE (t:test {prop: 456428}); +---- ok +-STATEMENT CREATE (t:test {prop: 158543}); +---- ok +-STATEMENT CREATE (t:test {prop: 597146}); +---- ok +-STATEMENT CREATE (t:test {prop: 891739}); +---- ok +-STATEMENT CREATE (t:test {prop: 434470}); +---- ok +-STATEMENT CREATE (t:test {prop: 369443}); +---- ok +-STATEMENT CREATE (t:test {prop: 306029}); +---- ok +-STATEMENT CREATE (t:test {prop: 92398}); +---- ok +-STATEMENT CREATE (t:test {prop: 739338}); +---- ok +-STATEMENT CREATE (t:test {prop: 775247}); +---- ok +-STATEMENT CREATE (t:test {prop: 510588}); +---- ok +-STATEMENT CREATE (t:test {prop: 937003}); +---- ok +-STATEMENT CREATE (t:test {prop: 543518}); +---- ok +-STATEMENT CREATE (t:test {prop: 469810}); +---- ok +-STATEMENT CREATE (t:test {prop: 937197}); +---- ok +-STATEMENT CREATE (t:test {prop: 976304}); +---- ok +-STATEMENT CREATE (t:test {prop: 176279}); +---- ok +-STATEMENT CREATE (t:test {prop: 552453}); +---- ok +-STATEMENT CREATE (t:test {prop: 113803}); +---- ok +-STATEMENT CREATE (t:test {prop: 286130}); +---- ok +-STATEMENT CREATE (t:test {prop: 233391}); +---- ok +-STATEMENT CREATE (t:test {prop: 796962}); +---- ok +-STATEMENT CREATE (t:test {prop: 362407}); +---- ok +-STATEMENT CREATE (t:test {prop: 620348}); +---- ok +-STATEMENT CREATE (t:test {prop: 196708}); +---- ok +-STATEMENT CREATE (t:test {prop: 606230}); +---- ok +-STATEMENT CREATE (t:test {prop: 128359}); +---- ok +-STATEMENT CREATE (t:test {prop: 572323}); +---- ok +-STATEMENT CREATE (t:test {prop: 575470}); +---- ok +-STATEMENT CREATE (t:test {prop: 784421}); +---- ok +-STATEMENT CREATE (t:test {prop: 77788}); +---- ok +-STATEMENT CREATE (t:test {prop: 174524}); +---- ok +-STATEMENT CREATE (t:test {prop: 303215}); +---- ok +-STATEMENT CREATE (t:test {prop: 925356}); +---- ok +-STATEMENT CREATE (t:test {prop: 791997}); +---- ok +-STATEMENT CREATE (t:test {prop: 31244}); +---- ok +-STATEMENT CREATE (t:test {prop: 321229}); +---- ok +-STATEMENT CREATE (t:test {prop: 956316}); +---- ok +-STATEMENT CREATE (t:test {prop: 717169}); +---- ok +-STATEMENT CREATE (t:test {prop: 419139}); +---- ok +-STATEMENT CREATE (t:test {prop: 815272}); +---- ok +-STATEMENT CREATE (t:test {prop: 753408}); +---- ok +-STATEMENT CREATE (t:test {prop: 392563}); +---- ok +-STATEMENT CREATE (t:test {prop: 128193}); +---- ok +-STATEMENT CREATE (t:test {prop: 19556}); +---- ok +-STATEMENT CREATE (t:test {prop: 399258}); +---- ok +-STATEMENT CREATE (t:test {prop: 552807}); +---- ok +-STATEMENT CREATE (t:test {prop: 534298}); +---- ok +-STATEMENT CREATE (t:test {prop: 668914}); +---- ok +-STATEMENT CREATE (t:test {prop: 884039}); +---- ok +-STATEMENT CREATE (t:test {prop: 466746}); +---- ok +-STATEMENT CREATE (t:test {prop: 857384}); +---- ok +-STATEMENT CREATE (t:test {prop: 343159}); +---- ok +-STATEMENT CREATE (t:test {prop: 820088}); +---- ok +-STATEMENT CREATE (t:test {prop: 190964}); +---- ok +-STATEMENT CREATE (t:test {prop: 727970}); +---- ok +-STATEMENT CREATE (t:test {prop: 30249}); +---- ok +-STATEMENT CREATE (t:test {prop: 37595}); +---- ok +-STATEMENT CREATE (t:test {prop: 150758}); +---- ok +-STATEMENT CREATE (t:test {prop: 782681}); +---- ok +-STATEMENT CREATE (t:test {prop: 427666}); +---- ok +-STATEMENT CREATE (t:test {prop: 235823}); +---- ok +-STATEMENT CREATE (t:test {prop: 89995}); +---- ok +-STATEMENT CREATE (t:test {prop: 692024}); +---- ok +-STATEMENT CREATE (t:test {prop: 939477}); +---- ok +-STATEMENT CREATE (t:test {prop: 558387}); +---- ok +-STATEMENT CREATE (t:test {prop: 470420}); +---- ok +-STATEMENT CREATE (t:test {prop: 446599}); +---- ok +-STATEMENT CREATE (t:test {prop: 657029}); +---- ok +-STATEMENT CREATE (t:test {prop: 172486}); +---- ok +-STATEMENT CREATE (t:test {prop: 897751}); +---- ok +-STATEMENT CREATE (t:test {prop: 601720}); +---- ok +-STATEMENT CREATE (t:test {prop: 291913}); +---- ok +-STATEMENT CREATE (t:test {prop: 308275}); +---- ok +-STATEMENT CREATE (t:test {prop: 645188}); +---- ok +-STATEMENT CREATE (t:test {prop: 3434}); +---- ok +-STATEMENT CREATE (t:test {prop: 482967}); +---- ok +-STATEMENT CREATE (t:test {prop: 22466}); +---- ok +-STATEMENT CREATE (t:test {prop: 615469}); +---- ok +-STATEMENT CREATE (t:test {prop: 506035}); +---- ok +-STATEMENT CREATE (t:test {prop: 628265}); +---- ok +-STATEMENT CREATE (t:test {prop: 275644}); +---- ok +-STATEMENT CREATE (t:test {prop: 20267}); +---- ok +-STATEMENT CREATE (t:test {prop: 352712}); +---- ok +-STATEMENT CREATE (t:test {prop: 283028}); +---- ok +-STATEMENT CREATE (t:test {prop: 382385}); +---- ok +-STATEMENT CREATE (t:test {prop: 771315}); +---- ok +-STATEMENT CREATE (t:test {prop: 727633}); +---- ok +-STATEMENT CREATE (t:test {prop: 878772}); +---- ok +-STATEMENT CREATE (t:test {prop: 730537}); +---- ok +-STATEMENT CREATE (t:test {prop: 271456}); +---- ok +-STATEMENT CREATE (t:test {prop: 96436}); +---- ok +-STATEMENT CREATE (t:test {prop: 355295}); +---- ok +-STATEMENT CREATE (t:test {prop: 144911}); +---- ok +-STATEMENT CREATE (t:test {prop: 593337}); +---- ok +-STATEMENT CREATE (t:test {prop: 195188}); +---- ok +-STATEMENT CREATE (t:test {prop: 97531}); +---- ok +-STATEMENT CREATE (t:test {prop: 212146}); +---- ok +-STATEMENT CREATE (t:test {prop: 547102}); +---- ok +-STATEMENT CREATE (t:test {prop: 681581}); +---- ok +-STATEMENT CREATE (t:test {prop: 230819}); +---- ok +-STATEMENT CREATE (t:test {prop: 893197}); +---- ok +-STATEMENT CREATE (t:test {prop: 296777}); +---- ok +-STATEMENT CREATE (t:test {prop: 709417}); +---- ok +-STATEMENT CREATE (t:test {prop: 332712}); +---- ok +-STATEMENT CREATE (t:test {prop: 880738}); +---- ok +-STATEMENT CREATE (t:test {prop: 803990}); +---- ok +-STATEMENT CREATE (t:test {prop: 380580}); +---- ok +-STATEMENT CREATE (t:test {prop: 12163}); +---- ok +-STATEMENT CREATE (t:test {prop: 832171}); +---- ok +-STATEMENT CREATE (t:test {prop: 323711}); +---- ok +-STATEMENT CREATE (t:test {prop: 120167}); +---- ok +-STATEMENT CREATE (t:test {prop: 779904}); +---- ok +-STATEMENT CREATE (t:test {prop: 274399}); +---- ok +-STATEMENT CREATE (t:test {prop: 761150}); +---- ok +-STATEMENT CREATE (t:test {prop: 4839}); +---- ok +-STATEMENT CREATE (t:test {prop: 780644}); +---- ok +-STATEMENT CREATE (t:test {prop: 239910}); +---- ok +-STATEMENT CREATE (t:test {prop: 824046}); +---- ok +-STATEMENT CREATE (t:test {prop: 299738}); +---- ok +-STATEMENT CREATE (t:test {prop: 892346}); +---- ok +-STATEMENT CREATE (t:test {prop: 253811}); +---- ok +-STATEMENT CREATE (t:test {prop: 77327}); +---- ok +-STATEMENT CREATE (t:test {prop: 656053}); +---- ok +-STATEMENT CREATE (t:test {prop: 795410}); +---- ok +-STATEMENT CREATE (t:test {prop: 937643}); +---- ok +-STATEMENT CREATE (t:test {prop: 777631}); +---- ok +-STATEMENT CREATE (t:test {prop: 241481}); +---- ok +-STATEMENT CREATE (t:test {prop: 554152}); +---- ok +-STATEMENT CREATE (t:test {prop: 232271}); +---- ok +-STATEMENT CREATE (t:test {prop: 934510}); +---- ok +-STATEMENT CREATE (t:test {prop: 520377}); +---- ok +-STATEMENT CREATE (t:test {prop: 633775}); +---- ok +-STATEMENT CREATE (t:test {prop: 452863}); +---- ok +-STATEMENT CREATE (t:test {prop: 206645}); +---- ok +-STATEMENT CREATE (t:test {prop: 422182}); +---- ok +-STATEMENT CREATE (t:test {prop: 985385}); +---- ok +-STATEMENT CREATE (t:test {prop: 758769}); +---- ok +-STATEMENT CREATE (t:test {prop: 335512}); +---- ok +-STATEMENT CREATE (t:test {prop: 495408}); +---- ok +-STATEMENT CREATE (t:test {prop: 219844}); +---- ok +-STATEMENT CREATE (t:test {prop: 321772}); +---- ok +-STATEMENT CREATE (t:test {prop: 982993}); +---- ok +-STATEMENT CREATE (t:test {prop: 68056}); +---- ok +-STATEMENT CREATE (t:test {prop: 167886}); +---- ok +-STATEMENT CREATE (t:test {prop: 163470}); +---- ok +-STATEMENT CREATE (t:test {prop: 259636}); +---- ok +-STATEMENT CREATE (t:test {prop: 930199}); +---- ok +-STATEMENT CREATE (t:test {prop: 108807}); +---- ok +-STATEMENT CREATE (t:test {prop: 900443}); +---- ok +-STATEMENT CREATE (t:test {prop: 489429}); +---- ok +-STATEMENT CREATE (t:test {prop: 581546}); +---- ok +-STATEMENT CREATE (t:test {prop: 808448}); +---- ok +-STATEMENT CREATE (t:test {prop: 614361}); +---- ok +-STATEMENT CREATE (t:test {prop: 264009}); +---- ok +-STATEMENT CREATE (t:test {prop: 268121}); +---- ok +-STATEMENT CREATE (t:test {prop: 237926}); +---- ok +-STATEMENT CREATE (t:test {prop: 373733}); +---- ok +-STATEMENT CREATE (t:test {prop: 684619}); +---- ok +-STATEMENT CREATE (t:test {prop: 902378}); +---- ok +-STATEMENT CREATE (t:test {prop: 971199}); +---- ok +-STATEMENT CREATE (t:test {prop: 124465}); +---- ok +-STATEMENT CREATE (t:test {prop: 477562}); +---- ok +-STATEMENT CREATE (t:test {prop: 572313}); +---- ok +-STATEMENT CREATE (t:test {prop: 200351}); +---- ok +-STATEMENT CREATE (t:test {prop: 840068}); +---- ok +-STATEMENT CREATE (t:test {prop: 795453}); +---- ok +-STATEMENT CREATE (t:test {prop: 327266}); +---- ok +-STATEMENT CREATE (t:test {prop: 566742}); +---- ok +-STATEMENT CREATE (t:test {prop: 212913}); +---- ok +-STATEMENT CREATE (t:test {prop: 318862}); +---- ok +-STATEMENT CREATE (t:test {prop: 27231}); +---- ok +-STATEMENT CREATE (t:test {prop: 904731}); +---- ok +-STATEMENT CREATE (t:test {prop: 60023}); +---- ok +-STATEMENT CREATE (t:test {prop: 209520}); +---- ok +-STATEMENT CREATE (t:test {prop: 141423}); +---- ok +-STATEMENT CREATE (t:test {prop: 484672}); +---- ok +-STATEMENT CREATE (t:test {prop: 419371}); +---- ok +-STATEMENT CREATE (t:test {prop: 708830}); +---- ok +-STATEMENT CREATE (t:test {prop: 745258}); +---- ok +-STATEMENT CREATE (t:test {prop: 664288}); +---- ok +-STATEMENT CREATE (t:test {prop: 380204}); +---- ok +-STATEMENT CREATE (t:test {prop: 118409}); +---- ok +-STATEMENT CREATE (t:test {prop: 437545}); +---- ok +-STATEMENT CREATE (t:test {prop: 301348}); +---- ok +-STATEMENT CREATE (t:test {prop: 809048}); +---- ok +-STATEMENT CREATE (t:test {prop: 760144}); +---- ok +-STATEMENT CREATE (t:test {prop: 884989}); +---- ok +-STATEMENT CREATE (t:test {prop: 433479}); +---- ok +-STATEMENT CREATE (t:test {prop: 742971}); +---- ok +-STATEMENT CREATE (t:test {prop: 664880}); +---- ok +-STATEMENT CREATE (t:test {prop: 717288}); +---- ok +-STATEMENT CREATE (t:test {prop: 284422}); +---- ok +-STATEMENT CREATE (t:test {prop: 1761}); +---- ok +-STATEMENT CREATE (t:test {prop: 644279}); +---- ok +-STATEMENT CREATE (t:test {prop: 306906}); +---- ok +-STATEMENT CREATE (t:test {prop: 269389}); +---- ok +-STATEMENT CREATE (t:test {prop: 669335}); +---- ok +-STATEMENT CREATE (t:test {prop: 650374}); +---- ok +-STATEMENT CREATE (t:test {prop: 674330}); +---- ok +-STATEMENT CREATE (t:test {prop: 548801}); +---- ok +-STATEMENT CREATE (t:test {prop: 811291}); +---- ok +-STATEMENT CREATE (t:test {prop: 974320}); +---- ok +-STATEMENT CREATE (t:test {prop: 315700}); +---- ok +-STATEMENT CREATE (t:test {prop: 274786}); +---- ok +-STATEMENT CREATE (t:test {prop: 173835}); +---- ok +-STATEMENT CREATE (t:test {prop: 150208}); +---- ok +-STATEMENT CREATE (t:test {prop: 747886}); +---- ok +-STATEMENT CREATE (t:test {prop: 761369}); +---- ok +-STATEMENT CREATE (t:test {prop: 690593}); +---- ok +-STATEMENT CREATE (t:test {prop: 509182}); +---- ok +-STATEMENT CREATE (t:test {prop: 719534}); +---- ok +-STATEMENT CREATE (t:test {prop: 500950}); +---- ok +-STATEMENT CREATE (t:test {prop: 929917}); +---- ok +-STATEMENT CREATE (t:test {prop: 456901}); +---- ok +-STATEMENT CREATE (t:test {prop: 766561}); +---- ok +-STATEMENT CREATE (t:test {prop: 324442}); +---- ok +-STATEMENT CREATE (t:test {prop: 430288}); +---- ok +-STATEMENT CREATE (t:test {prop: 146702}); +---- ok +-STATEMENT CREATE (t:test {prop: 995166}); +---- ok +-STATEMENT CREATE (t:test {prop: 863749}); +---- ok +-STATEMENT CREATE (t:test {prop: 479960}); +---- ok +-STATEMENT CREATE (t:test {prop: 603867}); +---- ok +-STATEMENT CREATE (t:test {prop: 2195}); +---- ok +-STATEMENT CREATE (t:test {prop: 993614}); +---- ok +-STATEMENT CREATE (t:test {prop: 340580}); +---- ok +-STATEMENT CREATE (t:test {prop: 365985}); +---- ok +-STATEMENT CREATE (t:test {prop: 269938}); +---- ok +-STATEMENT CREATE (t:test {prop: 869521}); +---- ok +-STATEMENT CREATE (t:test {prop: 557002}); +---- ok +-STATEMENT CREATE (t:test {prop: 723124}); +---- ok +-STATEMENT CREATE (t:test {prop: 278477}); +---- ok +-STATEMENT CREATE (t:test {prop: 268643}); +---- ok +-STATEMENT CREATE (t:test {prop: 713690}); +---- ok +-STATEMENT CREATE (t:test {prop: 798299}); +---- ok +-STATEMENT CREATE (t:test {prop: 71127}); +---- ok +-STATEMENT CREATE (t:test {prop: 512828}); +---- ok +-STATEMENT CREATE (t:test {prop: 750198}); +---- ok +-STATEMENT CREATE (t:test {prop: 754210}); +---- ok +-STATEMENT CREATE (t:test {prop: 496410}); +---- ok +-STATEMENT CREATE (t:test {prop: 43544}); +---- ok +-STATEMENT CREATE (t:test {prop: 179948}); +---- ok +-STATEMENT CREATE (t:test {prop: 308490}); +---- ok +-STATEMENT CREATE (t:test {prop: 147474}); +---- ok +-STATEMENT CREATE (t:test {prop: 265590}); +---- ok +-STATEMENT CREATE (t:test {prop: 810255}); +---- ok +-STATEMENT CREATE (t:test {prop: 940634}); +---- ok +-STATEMENT CREATE (t:test {prop: 540888}); +---- ok +-STATEMENT CREATE (t:test {prop: 95794}); +---- ok +-STATEMENT CREATE (t:test {prop: 881878}); +---- ok +-STATEMENT CREATE (t:test {prop: 373499}); +---- ok +-STATEMENT CREATE (t:test {prop: 791261}); +---- ok +-STATEMENT CREATE (t:test {prop: 530229}); +---- ok +-STATEMENT CREATE (t:test {prop: 552755}); +---- ok +-STATEMENT CREATE (t:test {prop: 316295}); +---- ok +-STATEMENT CREATE (t:test {prop: 151975}); +---- ok +-STATEMENT CREATE (t:test {prop: 562826}); +---- ok +-STATEMENT CREATE (t:test {prop: 771877}); +---- ok +-STATEMENT CREATE (t:test {prop: 382975}); +---- ok +-STATEMENT CREATE (t:test {prop: 440525}); +---- ok +-STATEMENT CREATE (t:test {prop: 960604}); +---- ok +-STATEMENT CREATE (t:test {prop: 575034}); +---- ok +-STATEMENT CREATE (t:test {prop: 631950}); +---- ok +-STATEMENT CREATE (t:test {prop: 782762}); +---- ok +-STATEMENT CREATE (t:test {prop: 630574}); +---- ok +-STATEMENT CREATE (t:test {prop: 760790}); +---- ok +-STATEMENT CREATE (t:test {prop: 241489}); +---- ok +-STATEMENT CREATE (t:test {prop: 614085}); +---- ok +-STATEMENT CREATE (t:test {prop: 982827}); +---- ok +-STATEMENT CREATE (t:test {prop: 384599}); +---- ok +-STATEMENT CREATE (t:test {prop: 784926}); +---- ok +-STATEMENT CREATE (t:test {prop: 704460}); +---- ok +-STATEMENT CREATE (t:test {prop: 273834}); +---- ok +-STATEMENT CREATE (t:test {prop: 332767}); +---- ok +-STATEMENT CREATE (t:test {prop: 129881}); +---- ok +-STATEMENT CREATE (t:test {prop: 384980}); +---- ok +-STATEMENT CREATE (t:test {prop: 531856}); +---- ok +-STATEMENT CREATE (t:test {prop: 506483}); +---- ok +-STATEMENT CREATE (t:test {prop: 924949}); +---- ok +-STATEMENT CREATE (t:test {prop: 669037}); +---- ok +-STATEMENT CREATE (t:test {prop: 758086}); +---- ok +-STATEMENT CREATE (t:test {prop: 471476}); +---- ok +-STATEMENT CREATE (t:test {prop: 542600}); +---- ok +-STATEMENT CREATE (t:test {prop: 561818}); +---- ok +-STATEMENT CREATE (t:test {prop: 494902}); +---- ok +-STATEMENT CREATE (t:test {prop: 325230}); +---- ok +-STATEMENT CREATE (t:test {prop: 298027}); +---- ok +-STATEMENT CREATE (t:test {prop: 546207}); +---- ok +-STATEMENT CREATE (t:test {prop: 498199}); +---- ok +-STATEMENT CREATE (t:test {prop: 874482}); +---- ok +-STATEMENT CREATE (t:test {prop: 265035}); +---- ok +-STATEMENT CREATE (t:test {prop: 89844}); +---- ok +-STATEMENT CREATE (t:test {prop: 307894}); +---- ok +-STATEMENT CREATE (t:test {prop: 256647}); +---- ok +-STATEMENT CREATE (t:test {prop: 217820}); +---- ok +-STATEMENT CREATE (t:test {prop: 810695}); +---- ok +-STATEMENT CREATE (t:test {prop: 287305}); +---- ok +-STATEMENT CREATE (t:test {prop: 127019}); +---- ok +-STATEMENT CREATE (t:test {prop: 65217}); +---- ok +-STATEMENT CREATE (t:test {prop: 680781}); +---- ok +-STATEMENT CREATE (t:test {prop: 662241}); +---- ok +-STATEMENT CREATE (t:test {prop: 300777}); +---- ok +-STATEMENT CREATE (t:test {prop: 505357}); +---- ok +-STATEMENT CREATE (t:test {prop: 507745}); +---- ok +-STATEMENT CREATE (t:test {prop: 555746}); +---- ok +-STATEMENT CREATE (t:test {prop: 8526}); +---- ok +-STATEMENT CREATE (t:test {prop: 561425}); +---- ok +-STATEMENT CREATE (t:test {prop: 595521}); +---- ok +-STATEMENT CREATE (t:test {prop: 259853}); +---- ok +-STATEMENT CREATE (t:test {prop: 357914}); +---- ok +-STATEMENT CREATE (t:test {prop: 874885}); +---- ok +-STATEMENT CREATE (t:test {prop: 292971}); +---- ok +-STATEMENT CREATE (t:test {prop: 391049}); +---- ok +-STATEMENT CREATE (t:test {prop: 889987}); +---- ok +-STATEMENT CREATE (t:test {prop: 745779}); +---- ok +-STATEMENT CREATE (t:test {prop: 824778}); +---- ok +-STATEMENT CREATE (t:test {prop: 89549}); +---- ok +-STATEMENT CREATE (t:test {prop: 687521}); +---- ok +-STATEMENT CREATE (t:test {prop: 194987}); +---- ok +-STATEMENT CREATE (t:test {prop: 755664}); +---- ok +-STATEMENT CREATE (t:test {prop: 346019}); +---- ok +-STATEMENT CREATE (t:test {prop: 323425}); +---- ok +-STATEMENT CREATE (t:test {prop: 82884}); +---- ok +-STATEMENT CREATE (t:test {prop: 281275}); +---- ok +-STATEMENT CREATE (t:test {prop: 75403}); +---- ok +-STATEMENT CREATE (t:test {prop: 169943}); +---- ok +-STATEMENT CREATE (t:test {prop: 361944}); +---- ok +-STATEMENT CREATE (t:test {prop: 572366}); +---- ok +-STATEMENT CREATE (t:test {prop: 218731}); +---- ok +-STATEMENT CREATE (t:test {prop: 614224}); +---- ok +-STATEMENT CREATE (t:test {prop: 434680}); +---- ok +-STATEMENT CREATE (t:test {prop: 389874}); +---- ok +-STATEMENT CREATE (t:test {prop: 236909}); +---- ok +-STATEMENT CREATE (t:test {prop: 560432}); +---- ok +-STATEMENT CREATE (t:test {prop: 897786}); +---- ok +-STATEMENT CREATE (t:test {prop: 922323}); +---- ok +-STATEMENT CREATE (t:test {prop: 370066}); +---- ok +-STATEMENT CREATE (t:test {prop: 484203}); +---- ok +-STATEMENT CREATE (t:test {prop: 53803}); +---- ok +-STATEMENT CREATE (t:test {prop: 630707}); +---- ok +-STATEMENT CREATE (t:test {prop: 731110}); +---- ok +-STATEMENT CREATE (t:test {prop: 260727}); +---- ok +-STATEMENT CREATE (t:test {prop: 669056}); +---- ok +-STATEMENT CREATE (t:test {prop: 904379}); +---- ok +-STATEMENT CREATE (t:test {prop: 905870}); +---- ok +-STATEMENT CREATE (t:test {prop: 991517}); +---- ok +-STATEMENT CREATE (t:test {prop: 904342}); +---- ok +-STATEMENT CREATE (t:test {prop: 425875}); +---- ok +-STATEMENT CREATE (t:test {prop: 806927}); +---- ok +-STATEMENT CREATE (t:test {prop: 48880}); +---- ok +-STATEMENT CREATE (t:test {prop: 437849}); +---- ok +-STATEMENT CREATE (t:test {prop: 332282}); +---- ok +-STATEMENT CREATE (t:test {prop: 59436}); +---- ok +-STATEMENT CREATE (t:test {prop: 737651}); +---- ok +-STATEMENT CREATE (t:test {prop: 382022}); +---- ok +-STATEMENT CREATE (t:test {prop: 333479}); +---- ok +-STATEMENT CREATE (t:test {prop: 958697}); +---- ok +-STATEMENT CREATE (t:test {prop: 89955}); +---- ok +-STATEMENT CREATE (t:test {prop: 760444}); +---- ok +-STATEMENT CREATE (t:test {prop: 204646}); +---- ok +-STATEMENT CREATE (t:test {prop: 990923}); +---- ok +-STATEMENT CREATE (t:test {prop: 746691}); +---- ok +-STATEMENT CREATE (t:test {prop: 801187}); +---- ok +-STATEMENT CREATE (t:test {prop: 753354}); +---- ok +-STATEMENT CREATE (t:test {prop: 245238}); +---- ok +-STATEMENT CREATE (t:test {prop: 750171}); +---- ok +-STATEMENT CREATE (t:test {prop: 720197}); +---- ok +-STATEMENT CREATE (t:test {prop: 434119}); +---- ok +-STATEMENT CREATE (t:test {prop: 439636}); +---- ok +-STATEMENT CREATE (t:test {prop: 96062}); +---- ok +-STATEMENT CREATE (t:test {prop: 665689}); +---- ok +-STATEMENT CREATE (t:test {prop: 299090}); +---- ok +-STATEMENT CREATE (t:test {prop: 319159}); +---- ok +-STATEMENT CREATE (t:test {prop: 34288}); +---- ok +-STATEMENT CREATE (t:test {prop: 636125}); +---- ok +-STATEMENT CREATE (t:test {prop: 457797}); +---- ok +-STATEMENT CREATE (t:test {prop: 218939}); +---- ok +-STATEMENT CREATE (t:test {prop: 614395}); +---- ok +-STATEMENT CREATE (t:test {prop: 632369}); +---- ok +-STATEMENT CREATE (t:test {prop: 797386}); +---- ok +-STATEMENT CREATE (t:test {prop: 477391}); +---- ok +-STATEMENT CREATE (t:test {prop: 236883}); +---- ok +-STATEMENT CREATE (t:test {prop: 614749}); +---- ok +-STATEMENT CREATE (t:test {prop: 907067}); +---- ok +-STATEMENT CREATE (t:test {prop: 208555}); +---- ok +-STATEMENT CREATE (t:test {prop: 808814}); +---- ok +-STATEMENT CREATE (t:test {prop: 4495}); +---- ok +-STATEMENT CREATE (t:test {prop: 606794}); +---- ok +-STATEMENT CREATE (t:test {prop: 218943}); +---- ok +-STATEMENT CREATE (t:test {prop: 483734}); +---- ok +-STATEMENT CREATE (t:test {prop: 752239}); +---- ok +-STATEMENT CREATE (t:test {prop: 788234}); +---- ok +-STATEMENT CREATE (t:test {prop: 634463}); +---- ok +-STATEMENT CREATE (t:test {prop: 326046}); +---- ok +-STATEMENT CREATE (t:test {prop: 976531}); +---- ok +-STATEMENT CREATE (t:test {prop: 628417}); +---- ok +-STATEMENT CREATE (t:test {prop: 833826}); +---- ok +-STATEMENT CREATE (t:test {prop: 620374}); +---- ok +-STATEMENT CREATE (t:test {prop: 567590}); +---- ok +-STATEMENT CREATE (t:test {prop: 604618}); +---- ok +-STATEMENT CREATE (t:test {prop: 747497}); +---- ok +-STATEMENT CREATE (t:test {prop: 486988}); +---- ok +-STATEMENT CREATE (t:test {prop: 109535}); +---- ok +-STATEMENT CREATE (t:test {prop: 496197}); +---- ok +-STATEMENT CREATE (t:test {prop: 738963}); +---- ok +-STATEMENT CREATE (t:test {prop: 273892}); +---- ok +-STATEMENT CREATE (t:test {prop: 189246}); +---- ok +-STATEMENT CREATE (t:test {prop: 232509}); +---- ok +-STATEMENT CREATE (t:test {prop: 500174}); +---- ok +-STATEMENT CREATE (t:test {prop: 581074}); +---- ok +-STATEMENT CREATE (t:test {prop: 429953}); +---- ok +-STATEMENT CREATE (t:test {prop: 260031}); +---- ok +-STATEMENT CREATE (t:test {prop: 623680}); +---- ok +-STATEMENT CREATE (t:test {prop: 886209}); +---- ok +-STATEMENT CREATE (t:test {prop: 901904}); +---- ok +-STATEMENT CREATE (t:test {prop: 596979}); +---- ok +-STATEMENT CREATE (t:test {prop: 764464}); +---- ok +-STATEMENT CREATE (t:test {prop: 475082}); +---- ok +-STATEMENT CREATE (t:test {prop: 423942}); +---- ok +-STATEMENT CREATE (t:test {prop: 269150}); +---- ok +-STATEMENT CREATE (t:test {prop: 504777}); +---- ok +-STATEMENT CREATE (t:test {prop: 17338}); +---- ok +-STATEMENT CREATE (t:test {prop: 9637}); +---- ok +-STATEMENT CREATE (t:test {prop: 300252}); +---- ok +-STATEMENT CREATE (t:test {prop: 304908}); +---- ok +-STATEMENT CREATE (t:test {prop: 878501}); +---- ok +-STATEMENT CREATE (t:test {prop: 371476}); +---- ok +-STATEMENT CREATE (t:test {prop: 573979}); +---- ok +-STATEMENT CREATE (t:test {prop: 778991}); +---- ok +-STATEMENT CREATE (t:test {prop: 960744}); +---- ok +-STATEMENT CREATE (t:test {prop: 975141}); +---- ok +-STATEMENT CREATE (t:test {prop: 850884}); +---- ok +-STATEMENT CREATE (t:test {prop: 415192}); +---- ok +-STATEMENT CREATE (t:test {prop: 495494}); +---- ok +-STATEMENT CREATE (t:test {prop: 992602}); +---- ok +-STATEMENT CREATE (t:test {prop: 793277}); +---- ok +-STATEMENT CREATE (t:test {prop: 612732}); +---- ok +-STATEMENT CREATE (t:test {prop: 105831}); +---- ok +-STATEMENT CREATE (t:test {prop: 327762}); +---- ok +-STATEMENT CREATE (t:test {prop: 645826}); +---- ok +-STATEMENT CREATE (t:test {prop: 146625}); +---- ok +-STATEMENT CREATE (t:test {prop: 354489}); +---- ok +-STATEMENT CREATE (t:test {prop: 492603}); +---- ok +-STATEMENT CREATE (t:test {prop: 725150}); +---- ok +-STATEMENT CREATE (t:test {prop: 167161}); +---- ok +-STATEMENT CREATE (t:test {prop: 394122}); +---- ok +-STATEMENT CREATE (t:test {prop: 785527}); +---- ok +-STATEMENT CREATE (t:test {prop: 187229}); +---- ok +-STATEMENT CREATE (t:test {prop: 102192}); +---- ok +-STATEMENT CREATE (t:test {prop: 49245}); +---- ok +-STATEMENT CREATE (t:test {prop: 360388}); +---- ok +-STATEMENT CREATE (t:test {prop: 769748}); +---- ok +-STATEMENT CREATE (t:test {prop: 376161}); +---- ok +-STATEMENT CREATE (t:test {prop: 908088}); +---- ok +-STATEMENT CREATE (t:test {prop: 532328}); +---- ok +-STATEMENT CREATE (t:test {prop: 370076}); +---- ok +-STATEMENT CREATE (t:test {prop: 947230}); +---- ok +-STATEMENT CREATE (t:test {prop: 632690}); +---- ok +-STATEMENT CREATE (t:test {prop: 42604}); +---- ok +-STATEMENT CREATE (t:test {prop: 326072}); +---- ok +-STATEMENT CREATE (t:test {prop: 646582}); +---- ok +-STATEMENT CREATE (t:test {prop: 51452}); +---- ok +-STATEMENT CREATE (t:test {prop: 391618}); +---- ok +-STATEMENT CREATE (t:test {prop: 755368}); +---- ok +-STATEMENT CREATE (t:test {prop: 889259}); +---- ok +-STATEMENT CREATE (t:test {prop: 552195}); +---- ok +-STATEMENT CREATE (t:test {prop: 658125}); +---- ok +-STATEMENT CREATE (t:test {prop: 286871}); +---- ok +-STATEMENT CREATE (t:test {prop: 929406}); +---- ok +-STATEMENT CREATE (t:test {prop: 311029}); +---- ok +-STATEMENT CREATE (t:test {prop: 501339}); +---- ok +-STATEMENT CREATE (t:test {prop: 853487}); +---- ok +-STATEMENT CREATE (t:test {prop: 964435}); +---- ok +-STATEMENT CREATE (t:test {prop: 594886}); +---- ok +-STATEMENT CREATE (t:test {prop: 733877}); +---- ok +-STATEMENT CREATE (t:test {prop: 219852}); +---- ok +-STATEMENT CREATE (t:test {prop: 934651}); +---- ok +-STATEMENT CREATE (t:test {prop: 819591}); +---- ok +-STATEMENT CREATE (t:test {prop: 549760}); +---- ok +-STATEMENT CREATE (t:test {prop: 138436}); +---- ok +-STATEMENT CREATE (t:test {prop: 34891}); +---- ok +-STATEMENT CREATE (t:test {prop: 467588}); +---- ok +-STATEMENT CREATE (t:test {prop: 928302}); +---- ok +-STATEMENT CREATE (t:test {prop: 487822}); +---- ok +-STATEMENT CREATE (t:test {prop: 322249}); +---- ok +-STATEMENT CREATE (t:test {prop: 623834}); +---- ok +-STATEMENT CREATE (t:test {prop: 357490}); +---- ok +-STATEMENT CREATE (t:test {prop: 61461}); +---- ok +-STATEMENT CREATE (t:test {prop: 867039}); +---- ok +-STATEMENT CREATE (t:test {prop: 990000}); +---- ok +-STATEMENT CREATE (t:test {prop: 68168}); +---- ok +-STATEMENT CREATE (t:test {prop: 100576}); +---- ok +-STATEMENT CREATE (t:test {prop: 472431}); +---- ok +-STATEMENT CREATE (t:test {prop: 645998}); +---- ok +-STATEMENT CREATE (t:test {prop: 407648}); +---- ok +-STATEMENT CREATE (t:test {prop: 34604}); +---- ok +-STATEMENT CREATE (t:test {prop: 622750}); +---- ok +-STATEMENT CREATE (t:test {prop: 950319}); +---- ok +-STATEMENT CREATE (t:test {prop: 556042}); +---- ok +-STATEMENT CREATE (t:test {prop: 144215}); +---- ok +-STATEMENT CREATE (t:test {prop: 940580}); +---- ok +-STATEMENT CREATE (t:test {prop: 428599}); +---- ok +-STATEMENT CREATE (t:test {prop: 633695}); +---- ok +-STATEMENT CREATE (t:test {prop: 938826}); +---- ok +-STATEMENT CREATE (t:test {prop: 623797}); +---- ok +-STATEMENT CREATE (t:test {prop: 574968}); +---- ok +-STATEMENT CREATE (t:test {prop: 533149}); +---- ok +-STATEMENT CREATE (t:test {prop: 579194}); +---- ok +-STATEMENT CREATE (t:test {prop: 569163}); +---- ok +-STATEMENT CREATE (t:test {prop: 280437}); +---- ok +-STATEMENT CREATE (t:test {prop: 833828}); +---- ok +-STATEMENT CREATE (t:test {prop: 618510}); +---- ok +-STATEMENT CREATE (t:test {prop: 956161}); +---- ok +-STATEMENT CREATE (t:test {prop: 197670}); +---- ok +-STATEMENT CREATE (t:test {prop: 677520}); +---- ok +-STATEMENT CREATE (t:test {prop: 259571}); +---- ok +-STATEMENT CREATE (t:test {prop: 107314}); +---- ok +-STATEMENT CREATE (t:test {prop: 9704}); +---- ok +-STATEMENT CREATE (t:test {prop: 982568}); +---- ok +-STATEMENT CREATE (t:test {prop: 162026}); +---- ok +-STATEMENT CREATE (t:test {prop: 232002}); +---- ok +-STATEMENT CREATE (t:test {prop: 900429}); +---- ok +-STATEMENT CREATE (t:test {prop: 673846}); +---- ok +-STATEMENT CREATE (t:test {prop: 795941}); +---- ok +-STATEMENT CREATE (t:test {prop: 936612}); +---- ok +-STATEMENT CREATE (t:test {prop: 959377}); +---- ok +-STATEMENT CREATE (t:test {prop: 406750}); +---- ok +-STATEMENT CREATE (t:test {prop: 776599}); +---- ok +-STATEMENT CREATE (t:test {prop: 451855}); +---- ok +-STATEMENT CREATE (t:test {prop: 640583}); +---- ok +-STATEMENT CREATE (t:test {prop: 914089}); +---- ok +-STATEMENT CREATE (t:test {prop: 432926}); +---- ok +-STATEMENT CREATE (t:test {prop: 943100}); +---- ok +-STATEMENT CREATE (t:test {prop: 961565}); +---- ok +-STATEMENT CREATE (t:test {prop: 386717}); +---- ok +-STATEMENT CREATE (t:test {prop: 497680}); +---- ok +-STATEMENT CREATE (t:test {prop: 8800}); +---- ok +-STATEMENT CREATE (t:test {prop: 385892}); +---- ok +-STATEMENT CREATE (t:test {prop: 905932}); +---- ok +-STATEMENT CREATE (t:test {prop: 362980}); +---- ok +-STATEMENT CREATE (t:test {prop: 532186}); +---- ok +-STATEMENT CREATE (t:test {prop: 228897}); +---- ok +-STATEMENT CREATE (t:test {prop: 165958}); +---- ok +-STATEMENT CREATE (t:test {prop: 570252}); +---- ok +-STATEMENT CREATE (t:test {prop: 395756}); +---- ok +-STATEMENT CREATE (t:test {prop: 661378}); +---- ok +-STATEMENT CREATE (t:test {prop: 582059}); +---- ok +-STATEMENT CREATE (t:test {prop: 971775}); +---- ok +-STATEMENT CREATE (t:test {prop: 813048}); +---- ok +-STATEMENT CREATE (t:test {prop: 768649}); +---- ok +-STATEMENT CREATE (t:test {prop: 199871}); +---- ok +-STATEMENT CREATE (t:test {prop: 128016}); +---- ok +-STATEMENT CREATE (t:test {prop: 90354}); +---- ok +-STATEMENT CREATE (t:test {prop: 100904}); +---- ok +-STATEMENT CREATE (t:test {prop: 453560}); +---- ok +-STATEMENT CREATE (t:test {prop: 108084}); +---- ok +-STATEMENT CREATE (t:test {prop: 338778}); +---- ok +-STATEMENT CREATE (t:test {prop: 585197}); +---- ok +-STATEMENT CREATE (t:test {prop: 666421}); +---- ok +-STATEMENT CREATE (t:test {prop: 550388}); +---- ok +-STATEMENT CREATE (t:test {prop: 346603}); +---- ok +-STATEMENT CREATE (t:test {prop: 327889}); +---- ok +-STATEMENT CREATE (t:test {prop: 519485}); +---- ok +-STATEMENT CREATE (t:test {prop: 141745}); +---- ok +-STATEMENT CREATE (t:test {prop: 21664}); +---- ok +-STATEMENT CREATE (t:test {prop: 834470}); +---- ok +-STATEMENT CREATE (t:test {prop: 547715}); +---- ok +-STATEMENT CREATE (t:test {prop: 586975}); +---- ok +-STATEMENT CREATE (t:test {prop: 508413}); +---- ok +-STATEMENT CREATE (t:test {prop: 194750}); +---- ok +-STATEMENT CREATE (t:test {prop: 988334}); +---- ok +-STATEMENT CREATE (t:test {prop: 151581}); +---- ok +-STATEMENT CREATE (t:test {prop: 134692}); +---- ok +-STATEMENT CREATE (t:test {prop: 543644}); +---- ok +-STATEMENT CREATE (t:test {prop: 541258}); +---- ok +-STATEMENT CREATE (t:test {prop: 371080}); +---- ok +-STATEMENT CREATE (t:test {prop: 51860}); +---- ok +-STATEMENT CREATE (t:test {prop: 906142}); +---- ok +-STATEMENT CREATE (t:test {prop: 411201}); +---- ok +-STATEMENT CREATE (t:test {prop: 144667}); +---- ok +-STATEMENT CREATE (t:test {prop: 737389}); +---- ok +-STATEMENT CREATE (t:test {prop: 125345}); +---- ok +-STATEMENT CREATE (t:test {prop: 197370}); +---- ok +-STATEMENT CREATE (t:test {prop: 553197}); +---- ok +-STATEMENT CREATE (t:test {prop: 428304}); +---- ok +-STATEMENT CREATE (t:test {prop: 219743}); +---- ok +-STATEMENT CREATE (t:test {prop: 123512}); +---- ok +-STATEMENT CREATE (t:test {prop: 461532}); +---- ok +-STATEMENT CREATE (t:test {prop: 552543}); +---- ok +-STATEMENT CREATE (t:test {prop: 191515}); +---- ok +-STATEMENT CREATE (t:test {prop: 552984}); +---- ok +-STATEMENT CREATE (t:test {prop: 397495}); +---- ok +-STATEMENT CREATE (t:test {prop: 427318}); +---- ok +-STATEMENT CREATE (t:test {prop: 567582}); +---- ok +-STATEMENT CREATE (t:test {prop: 279759}); +---- ok +-STATEMENT CREATE (t:test {prop: 240940}); +---- ok +-STATEMENT CREATE (t:test {prop: 289181}); +---- ok +-STATEMENT CREATE (t:test {prop: 814392}); +---- ok +-STATEMENT CREATE (t:test {prop: 835788}); +---- ok +-STATEMENT CREATE (t:test {prop: 634871}); +---- ok +-STATEMENT CREATE (t:test {prop: 737299}); +---- ok +-STATEMENT CREATE (t:test {prop: 839963}); +---- ok +-STATEMENT CREATE (t:test {prop: 128027}); +---- ok +-STATEMENT CREATE (t:test {prop: 38976}); +---- ok +-STATEMENT CREATE (t:test {prop: 953538}); +---- ok +-STATEMENT CREATE (t:test {prop: 38471}); +---- ok +-STATEMENT CREATE (t:test {prop: 591143}); +---- ok +-STATEMENT CREATE (t:test {prop: 921012}); +---- ok +-STATEMENT CREATE (t:test {prop: 61771}); +---- ok +-STATEMENT CREATE (t:test {prop: 857227}); +---- ok +-STATEMENT CREATE (t:test {prop: 911381}); +---- ok +-STATEMENT CREATE (t:test {prop: 224493}); +---- ok +-STATEMENT CREATE (t:test {prop: 924850}); +---- ok +-STATEMENT CREATE (t:test {prop: 471769}); +---- ok +-STATEMENT CREATE (t:test {prop: 318394}); +---- ok +-STATEMENT CREATE (t:test {prop: 816080}); +---- ok +-STATEMENT CREATE (t:test {prop: 833378}); +---- ok +-STATEMENT CREATE (t:test {prop: 706556}); +---- ok +-STATEMENT CREATE (t:test {prop: 61654}); +---- ok +-STATEMENT CREATE (t:test {prop: 441489}); +---- ok +-STATEMENT CREATE (t:test {prop: 831429}); +---- ok +-STATEMENT CREATE (t:test {prop: 591137}); +---- ok +-STATEMENT CREATE (t:test {prop: 289640}); +---- ok +-STATEMENT CREATE (t:test {prop: 346239}); +---- ok +-STATEMENT CREATE (t:test {prop: 380691}); +---- ok +-STATEMENT CREATE (t:test {prop: 754250}); +---- ok +-STATEMENT CREATE (t:test {prop: 705140}); +---- ok +-STATEMENT CREATE (t:test {prop: 943374}); +---- ok +-STATEMENT CREATE (t:test {prop: 47774}); +---- ok +-STATEMENT CREATE (t:test {prop: 468133}); +---- ok +-STATEMENT CREATE (t:test {prop: 62081}); +---- ok +-STATEMENT CREATE (t:test {prop: 622803}); +---- ok +-STATEMENT CREATE (t:test {prop: 851604}); +---- ok +-STATEMENT CREATE (t:test {prop: 29283}); +---- ok +-STATEMENT CREATE (t:test {prop: 773928}); +---- ok +-STATEMENT CREATE (t:test {prop: 544431}); +---- ok +-STATEMENT CREATE (t:test {prop: 472881}); +---- ok +-STATEMENT CREATE (t:test {prop: 292574}); +---- ok +-STATEMENT CREATE (t:test {prop: 605901}); +---- ok +-STATEMENT CREATE (t:test {prop: 547119}); +---- ok +-STATEMENT CREATE (t:test {prop: 680039}); +---- ok +-STATEMENT CREATE (t:test {prop: 344033}); +---- ok +-STATEMENT CREATE (t:test {prop: 992349}); +---- ok +-STATEMENT CREATE (t:test {prop: 385639}); +---- ok +-STATEMENT CREATE (t:test {prop: 474245}); +---- ok +-STATEMENT CREATE (t:test {prop: 547119}); +---- ok +-STATEMENT CREATE (t:test {prop: 401560}); +---- ok +-STATEMENT CREATE (t:test {prop: 448118}); +---- ok +-STATEMENT CREATE (t:test {prop: 396103}); +---- ok +-STATEMENT CREATE (t:test {prop: 993348}); +---- ok +-STATEMENT CREATE (t:test {prop: 342736}); +---- ok +-STATEMENT CREATE (t:test {prop: 960686}); +---- ok +-STATEMENT CREATE (t:test {prop: 377162}); +---- ok +-STATEMENT CREATE (t:test {prop: 506965}); +---- ok +-STATEMENT CREATE (t:test {prop: 990963}); +---- ok +-STATEMENT CREATE (t:test {prop: 180400}); +---- ok +-STATEMENT CREATE (t:test {prop: 771146}); +---- ok +-STATEMENT CREATE (t:test {prop: 233870}); +---- ok +-STATEMENT CREATE (t:test {prop: 431601}); +---- ok +-STATEMENT CREATE (t:test {prop: 817283}); +---- ok +-STATEMENT CREATE (t:test {prop: 923965}); +---- ok +-STATEMENT CREATE (t:test {prop: 90218}); +---- ok +-STATEMENT CREATE (t:test {prop: 549524}); +---- ok +-STATEMENT CREATE (t:test {prop: 752106}); +---- ok +-STATEMENT CREATE (t:test {prop: 959393}); +---- ok +-STATEMENT CREATE (t:test {prop: 775956}); +---- ok +-STATEMENT CREATE (t:test {prop: 438903}); +---- ok +-STATEMENT CREATE (t:test {prop: 222788}); +---- ok +-STATEMENT CREATE (t:test {prop: 280597}); +---- ok +-STATEMENT CREATE (t:test {prop: 59149}); +---- ok +-STATEMENT CREATE (t:test {prop: 49899}); +---- ok +-STATEMENT CREATE (t:test {prop: 396243}); +---- ok +-STATEMENT CREATE (t:test {prop: 730633}); +---- ok +-STATEMENT CREATE (t:test {prop: 835319}); +---- ok +-STATEMENT CREATE (t:test {prop: 603102}); +---- ok +-STATEMENT CREATE (t:test {prop: 11718}); +---- ok +-STATEMENT CREATE (t:test {prop: 1681}); +---- ok +-STATEMENT CREATE (t:test {prop: 936535}); +---- ok +-STATEMENT CREATE (t:test {prop: 849208}); +---- ok +-STATEMENT CREATE (t:test {prop: 398211}); +---- ok +-STATEMENT CREATE (t:test {prop: 28062}); +---- ok +-STATEMENT CREATE (t:test {prop: 691954}); +---- ok +-STATEMENT CREATE (t:test {prop: 225569}); +---- ok +-STATEMENT CREATE (t:test {prop: 735922}); +---- ok +-STATEMENT CREATE (t:test {prop: 260550}); +---- ok +-STATEMENT CREATE (t:test {prop: 886251}); +---- ok +-STATEMENT CREATE (t:test {prop: 215572}); +---- ok +-STATEMENT CREATE (t:test {prop: 22865}); +---- ok +-STATEMENT CREATE (t:test {prop: 687021}); +---- ok +-STATEMENT CREATE (t:test {prop: 84655}); +---- ok +-STATEMENT CREATE (t:test {prop: 537092}); +---- ok +-STATEMENT CREATE (t:test {prop: 531870}); +---- ok +-STATEMENT CREATE (t:test {prop: 492492}); +---- ok +-STATEMENT CREATE (t:test {prop: 469611}); +---- ok +-STATEMENT CREATE (t:test {prop: 438585}); +---- ok +-STATEMENT CREATE (t:test {prop: 404831}); +---- ok +-STATEMENT CREATE (t:test {prop: 309193}); +---- ok +-STATEMENT CREATE (t:test {prop: 254136}); +---- ok +-STATEMENT CREATE (t:test {prop: 514974}); +---- ok +-STATEMENT CREATE (t:test {prop: 207910}); +---- ok +-STATEMENT CREATE (t:test {prop: 823978}); +---- ok +-STATEMENT CREATE (t:test {prop: 981212}); +---- ok +-STATEMENT CREATE (t:test {prop: 504102}); +---- ok +-STATEMENT CREATE (t:test {prop: 292888}); +---- ok +-STATEMENT CREATE (t:test {prop: 73790}); +---- ok +-STATEMENT CREATE (t:test {prop: 179174}); +---- ok +-STATEMENT CREATE (t:test {prop: 63323}); +---- ok +-STATEMENT CREATE (t:test {prop: 110454}); +---- ok +-STATEMENT CREATE (t:test {prop: 678593}); +---- ok +-STATEMENT CREATE (t:test {prop: 438320}); +---- ok +-STATEMENT CREATE (t:test {prop: 715103}); +---- ok +-STATEMENT CREATE (t:test {prop: 345642}); +---- ok +-STATEMENT CREATE (t:test {prop: 899499}); +---- ok +-STATEMENT CREATE (t:test {prop: 754687}); +---- ok +-STATEMENT CREATE (t:test {prop: 592302}); +---- ok +-STATEMENT CREATE (t:test {prop: 538914}); +---- ok +-STATEMENT CREATE (t:test {prop: 495025}); +---- ok +-STATEMENT CREATE (t:test {prop: 768234}); +---- ok +-STATEMENT CREATE (t:test {prop: 453065}); +---- ok +-STATEMENT CREATE (t:test {prop: 357912}); +---- ok +-STATEMENT CREATE (t:test {prop: 355541}); +---- ok +-STATEMENT CREATE (t:test {prop: 273109}); +---- ok +-STATEMENT CREATE (t:test {prop: 226859}); +---- ok +-STATEMENT CREATE (t:test {prop: 597680}); +---- ok +-STATEMENT CREATE (t:test {prop: 141128}); +---- ok +-STATEMENT CREATE (t:test {prop: 951732}); +---- ok +-STATEMENT CREATE (t:test {prop: 979222}); +---- ok +-STATEMENT CREATE (t:test {prop: 896553}); +---- ok +-STATEMENT CREATE (t:test {prop: 621496}); +---- ok +-STATEMENT CREATE (t:test {prop: 338268}); +---- ok +-STATEMENT CREATE (t:test {prop: 502825}); +---- ok +-STATEMENT CREATE (t:test {prop: 709303}); +---- ok +-STATEMENT CREATE (t:test {prop: 836161}); +---- ok +-STATEMENT CREATE (t:test {prop: 134591}); +---- ok +-STATEMENT CREATE (t:test {prop: 988698}); +---- ok +-STATEMENT CREATE (t:test {prop: 503429}); +---- ok +-STATEMENT CREATE (t:test {prop: 762521}); +---- ok +-STATEMENT CREATE (t:test {prop: 889113}); +---- ok +-STATEMENT CREATE (t:test {prop: 802569}); +---- ok +-STATEMENT CREATE (t:test {prop: 506447}); +---- ok +-STATEMENT CREATE (t:test {prop: 424769}); +---- ok +-STATEMENT CREATE (t:test {prop: 15789}); +---- ok +-STATEMENT CREATE (t:test {prop: 625731}); +---- ok +-STATEMENT CREATE (t:test {prop: 458524}); +---- ok +-STATEMENT CREATE (t:test {prop: 456883}); +---- ok +-STATEMENT CREATE (t:test {prop: 814109}); +---- ok +-STATEMENT CREATE (t:test {prop: 32278}); +---- ok +-STATEMENT CREATE (t:test {prop: 876191}); +---- ok +-STATEMENT CREATE (t:test {prop: 629954}); +---- ok +-STATEMENT CREATE (t:test {prop: 388081}); +---- ok +-STATEMENT CREATE (t:test {prop: 402761}); +---- ok +-STATEMENT CREATE (t:test {prop: 266622}); +---- ok +-STATEMENT CREATE (t:test {prop: 343197}); +---- ok +-STATEMENT CREATE (t:test {prop: 535614}); +---- ok +-STATEMENT CREATE (t:test {prop: 316787}); +---- ok +-STATEMENT CREATE (t:test {prop: 269660}); +---- ok +-STATEMENT CREATE (t:test {prop: 782877}); +---- ok +-STATEMENT CREATE (t:test {prop: 564488}); +---- ok +-STATEMENT CREATE (t:test {prop: 363734}); +---- ok +-STATEMENT CREATE (t:test {prop: 402776}); +---- ok +-STATEMENT CREATE (t:test {prop: 455387}); +---- ok +-STATEMENT CREATE (t:test {prop: 2751}); +---- ok +-STATEMENT CREATE (t:test {prop: 814611}); +---- ok +-STATEMENT CREATE (t:test {prop: 449344}); +---- ok +-STATEMENT CREATE (t:test {prop: 756155}); +---- ok +-STATEMENT CREATE (t:test {prop: 319568}); +---- ok +-STATEMENT CREATE (t:test {prop: 77411}); +---- ok +-STATEMENT CREATE (t:test {prop: 688522}); +---- ok +-STATEMENT CREATE (t:test {prop: 206587}); +---- ok +-STATEMENT CREATE (t:test {prop: 918881}); +---- ok +-STATEMENT CREATE (t:test {prop: 362408}); +---- ok +-STATEMENT CREATE (t:test {prop: 783410}); +---- ok +-STATEMENT CREATE (t:test {prop: 561064}); +---- ok +-STATEMENT CREATE (t:test {prop: 256226}); +---- ok +-STATEMENT CREATE (t:test {prop: 172501}); +---- ok +-STATEMENT CREATE (t:test {prop: 890669}); +---- ok +-STATEMENT CREATE (t:test {prop: 822758}); +---- ok +-STATEMENT CREATE (t:test {prop: 513336}); +---- ok +-STATEMENT CREATE (t:test {prop: 936281}); +---- ok +-STATEMENT CREATE (t:test {prop: 722596}); +---- ok +-STATEMENT CREATE (t:test {prop: 884645}); +---- ok +-STATEMENT CREATE (t:test {prop: 644050}); +---- ok +-STATEMENT CREATE (t:test {prop: 83560}); +---- ok +-STATEMENT CREATE (t:test {prop: 460256}); +---- ok +-STATEMENT CREATE (t:test {prop: 101760}); +---- ok +-STATEMENT CREATE (t:test {prop: 480151}); +---- ok +-STATEMENT CREATE (t:test {prop: 45666}); +---- ok +-STATEMENT CREATE (t:test {prop: 184917}); +---- ok +-STATEMENT CREATE (t:test {prop: 815701}); +---- ok +-STATEMENT CREATE (t:test {prop: 311739}); +---- ok +-STATEMENT CREATE (t:test {prop: 769521}); +---- ok +-STATEMENT CREATE (t:test {prop: 124134}); +---- ok +-STATEMENT CREATE (t:test {prop: 635223}); +---- ok +-STATEMENT CREATE (t:test {prop: 378}); +---- ok +-STATEMENT CREATE (t:test {prop: 154957}); +---- ok +-STATEMENT CREATE (t:test {prop: 365727}); +---- ok +-STATEMENT CREATE (t:test {prop: 671426}); +---- ok +-STATEMENT CREATE (t:test {prop: 317796}); +---- ok +-STATEMENT CREATE (t:test {prop: 514380}); +---- ok +-STATEMENT CREATE (t:test {prop: 40964}); +---- ok +-STATEMENT CREATE (t:test {prop: 106897}); +---- ok +-STATEMENT CREATE (t:test {prop: 601735}); +---- ok +-STATEMENT CREATE (t:test {prop: 456410}); +---- ok +-STATEMENT CREATE (t:test {prop: 588998}); +---- ok +-STATEMENT CREATE (t:test {prop: 794777}); +---- ok +-STATEMENT CREATE (t:test {prop: 339570}); +---- ok +-STATEMENT CREATE (t:test {prop: 656822}); +---- ok +-STATEMENT CREATE (t:test {prop: 74262}); +---- ok +-STATEMENT CREATE (t:test {prop: 731132}); +---- ok +-STATEMENT CREATE (t:test {prop: 689383}); +---- ok +-STATEMENT CREATE (t:test {prop: 161839}); +---- ok +-STATEMENT CREATE (t:test {prop: 909772}); +---- ok +-STATEMENT CREATE (t:test {prop: 872762}); +---- ok +-STATEMENT CREATE (t:test {prop: 321770}); +---- ok +-STATEMENT CREATE (t:test {prop: 624112}); +---- ok +-STATEMENT CREATE (t:test {prop: 651859}); +---- ok +-STATEMENT CREATE (t:test {prop: 501442}); +---- ok +-STATEMENT CREATE (t:test {prop: 984634}); +---- ok +-STATEMENT CREATE (t:test {prop: 115585}); +---- ok +-STATEMENT CREATE (t:test {prop: 374948}); +---- ok +-STATEMENT CREATE (t:test {prop: 288847}); +---- ok +-STATEMENT CREATE (t:test {prop: 110679}); +---- ok +-STATEMENT CREATE (t:test {prop: 774309}); +---- ok +-STATEMENT CREATE (t:test {prop: 635700}); +---- ok +-STATEMENT CREATE (t:test {prop: 180555}); +---- ok +-STATEMENT CREATE (t:test {prop: 883016}); +---- ok +-STATEMENT CREATE (t:test {prop: 984667}); +---- ok +-STATEMENT CREATE (t:test {prop: 292551}); +---- ok +-STATEMENT CREATE (t:test {prop: 456339}); +---- ok +-STATEMENT CREATE (t:test {prop: 725924}); +---- ok +-STATEMENT CREATE (t:test {prop: 239169}); +---- ok +-STATEMENT CREATE (t:test {prop: 200059}); +---- ok +-STATEMENT CREATE (t:test {prop: 819305}); +---- ok +-STATEMENT CREATE (t:test {prop: 536802}); +---- ok +-STATEMENT CREATE (t:test {prop: 513784}); +---- ok +-STATEMENT CREATE (t:test {prop: 103420}); +---- ok +-STATEMENT CREATE (t:test {prop: 257250}); +---- ok +-STATEMENT CREATE (t:test {prop: 552941}); +---- ok +-STATEMENT CREATE (t:test {prop: 849401}); +---- ok +-STATEMENT CREATE (t:test {prop: 863298}); +---- ok +-STATEMENT CREATE (t:test {prop: 733622}); +---- ok +-STATEMENT CREATE (t:test {prop: 102679}); +---- ok +-STATEMENT CREATE (t:test {prop: 819429}); +---- ok +-STATEMENT CREATE (t:test {prop: 592156}); +---- ok +-STATEMENT CREATE (t:test {prop: 774059}); +---- ok +-STATEMENT CREATE (t:test {prop: 923741}); +---- ok +-STATEMENT CREATE (t:test {prop: 690000}); +---- ok +-STATEMENT CREATE (t:test {prop: 312330}); +---- ok +-STATEMENT CREATE (t:test {prop: 180261}); +---- ok +-STATEMENT CREATE (t:test {prop: 280335}); +---- ok +-STATEMENT CREATE (t:test {prop: 231825}); +---- ok +-STATEMENT CREATE (t:test {prop: 214521}); +---- ok +-STATEMENT CREATE (t:test {prop: 953056}); +---- ok +-STATEMENT CREATE (t:test {prop: 886631}); +---- ok +-STATEMENT CREATE (t:test {prop: 362023}); +---- ok +-STATEMENT CREATE (t:test {prop: 546904}); +---- ok +-STATEMENT CREATE (t:test {prop: 977390}); +---- ok +-STATEMENT CREATE (t:test {prop: 552702}); +---- ok +-STATEMENT CREATE (t:test {prop: 48992}); +---- ok +-STATEMENT CREATE (t:test {prop: 459186}); +---- ok +-STATEMENT CREATE (t:test {prop: 66572}); +---- ok +-STATEMENT CREATE (t:test {prop: 967790}); +---- ok +-STATEMENT CREATE (t:test {prop: 383722}); +---- ok +-STATEMENT CREATE (t:test {prop: 433878}); +---- ok +-STATEMENT CREATE (t:test {prop: 507994}); +---- ok +-STATEMENT CREATE (t:test {prop: 529602}); +---- ok +-STATEMENT CREATE (t:test {prop: 483753}); +---- ok +-STATEMENT CREATE (t:test {prop: 156403}); +---- ok +-STATEMENT CREATE (t:test {prop: 763453}); +---- ok +-STATEMENT CREATE (t:test {prop: 763329}); +---- ok +-STATEMENT CREATE (t:test {prop: 485135}); +---- ok +-STATEMENT CREATE (t:test {prop: 63394}); +---- ok +-STATEMENT CREATE (t:test {prop: 537496}); +---- ok +-STATEMENT CREATE (t:test {prop: 270467}); +---- ok +-STATEMENT CREATE (t:test {prop: 573123}); +---- ok +-STATEMENT CREATE (t:test {prop: 802663}); +---- ok +-STATEMENT CREATE (t:test {prop: 927457}); +---- ok +-STATEMENT CREATE (t:test {prop: 867590}); +---- ok +-STATEMENT CREATE (t:test {prop: 481473}); +---- ok +-STATEMENT CREATE (t:test {prop: 903179}); +---- ok +-STATEMENT CREATE (t:test {prop: 646095}); +---- ok +-STATEMENT CREATE (t:test {prop: 309230}); +---- ok +-STATEMENT CREATE (t:test {prop: 329137}); +---- ok +-STATEMENT CREATE (t:test {prop: 720698}); +---- ok +-STATEMENT CREATE (t:test {prop: 236575}); +---- ok +-STATEMENT CREATE (t:test {prop: 930558}); +---- ok +-STATEMENT CREATE (t:test {prop: 330726}); +---- ok +-STATEMENT CREATE (t:test {prop: 690949}); +---- ok +-STATEMENT CREATE (t:test {prop: 620065}); +---- ok +-STATEMENT CREATE (t:test {prop: 201960}); +---- ok +-STATEMENT CREATE (t:test {prop: 200023}); +---- ok +-STATEMENT CREATE (t:test {prop: 434381}); +---- ok +-STATEMENT CREATE (t:test {prop: 399633}); +---- ok +-STATEMENT CREATE (t:test {prop: 134244}); +---- ok +-STATEMENT CREATE (t:test {prop: 331167}); +---- ok +-STATEMENT CREATE (t:test {prop: 171184}); +---- ok +-STATEMENT CREATE (t:test {prop: 665564}); +---- ok +-STATEMENT CREATE (t:test {prop: 226659}); +---- ok +-STATEMENT CREATE (t:test {prop: 683460}); +---- ok +-STATEMENT CREATE (t:test {prop: 126896}); +---- ok +-STATEMENT CREATE (t:test {prop: 734916}); +---- ok +-STATEMENT CREATE (t:test {prop: 368338}); +---- ok +-STATEMENT CREATE (t:test {prop: 596390}); +---- ok +-STATEMENT CREATE (t:test {prop: 623492}); +---- ok +-STATEMENT CREATE (t:test {prop: 113510}); +---- ok +-STATEMENT CREATE (t:test {prop: 642098}); +---- ok +-STATEMENT CREATE (t:test {prop: 386777}); +---- ok +-STATEMENT CREATE (t:test {prop: 294101}); +---- ok +-STATEMENT CREATE (t:test {prop: 927431}); +---- ok +-STATEMENT CREATE (t:test {prop: 480005}); +---- ok +-STATEMENT CREATE (t:test {prop: 229656}); +---- ok +-STATEMENT CREATE (t:test {prop: 223336}); +---- ok +-STATEMENT CREATE (t:test {prop: 151595}); +---- ok +-STATEMENT CREATE (t:test {prop: 802029}); +---- ok +-STATEMENT CREATE (t:test {prop: 923054}); +---- ok +-STATEMENT CREATE (t:test {prop: 90088}); +---- ok +-STATEMENT CREATE (t:test {prop: 117948}); +---- ok +-STATEMENT CREATE (t:test {prop: 131381}); +---- ok +-STATEMENT CREATE (t:test {prop: 703288}); +---- ok +-STATEMENT CREATE (t:test {prop: 340244}); +---- ok +-STATEMENT CREATE (t:test {prop: 507995}); +---- ok +-STATEMENT CREATE (t:test {prop: 427400}); +---- ok +-STATEMENT CREATE (t:test {prop: 241992}); +---- ok +-STATEMENT CREATE (t:test {prop: 934140}); +---- ok +-STATEMENT CREATE (t:test {prop: 557738}); +---- ok +-STATEMENT CREATE (t:test {prop: 888936}); +---- ok +-STATEMENT CREATE (t:test {prop: 674434}); +---- ok +-STATEMENT CREATE (t:test {prop: 291032}); +---- ok +-STATEMENT CREATE (t:test {prop: 839747}); +---- ok +-STATEMENT CREATE (t:test {prop: 403388}); +---- ok +-STATEMENT CREATE (t:test {prop: 835414}); +---- ok +-STATEMENT CREATE (t:test {prop: 509706}); +---- ok +-STATEMENT CREATE (t:test {prop: 519534}); +---- ok +-STATEMENT CREATE (t:test {prop: 821916}); +---- ok +-STATEMENT CREATE (t:test {prop: 640258}); +---- ok +-STATEMENT CREATE (t:test {prop: 978640}); +---- ok +-STATEMENT CREATE (t:test {prop: 844546}); +---- ok +-STATEMENT CREATE (t:test {prop: 997220}); +---- ok +-STATEMENT CREATE (t:test {prop: 680285}); +---- ok +-STATEMENT CREATE (t:test {prop: 368433}); +---- ok +-STATEMENT CREATE (t:test {prop: 299933}); +---- ok +-STATEMENT CREATE (t:test {prop: 405884}); +---- ok +-STATEMENT CREATE (t:test {prop: 668366}); +---- ok +-STATEMENT CREATE (t:test {prop: 247824}); +---- ok +-STATEMENT CREATE (t:test {prop: 492922}); +---- ok +-STATEMENT CREATE (t:test {prop: 843915}); +---- ok +-STATEMENT CREATE (t:test {prop: 524669}); +---- ok +-STATEMENT CREATE (t:test {prop: 999765}); +---- ok +-STATEMENT CREATE (t:test {prop: 689237}); +---- ok +-STATEMENT CREATE (t:test {prop: 133746}); +---- ok +-STATEMENT CREATE (t:test {prop: 656240}); +---- ok +-STATEMENT CREATE (t:test {prop: 222414}); +---- ok +-STATEMENT CREATE (t:test {prop: 341390}); +---- ok +-STATEMENT CREATE (t:test {prop: 453644}); +---- ok +-STATEMENT CREATE (t:test {prop: 288518}); +---- ok +-STATEMENT CREATE (t:test {prop: 709258}); +---- ok +-STATEMENT CREATE (t:test {prop: 54960}); +---- ok +-STATEMENT CREATE (t:test {prop: 961755}); +---- ok +-STATEMENT CREATE (t:test {prop: 712942}); +---- ok +-STATEMENT CREATE (t:test {prop: 806465}); +---- ok +-STATEMENT CREATE (t:test {prop: 297974}); +---- ok +-STATEMENT CREATE (t:test {prop: 79040}); +---- ok +-STATEMENT CREATE (t:test {prop: 827426}); +---- ok +-STATEMENT CREATE (t:test {prop: 446898}); +---- ok +-STATEMENT CREATE (t:test {prop: 694176}); +---- ok +-STATEMENT CREATE (t:test {prop: 587857}); +---- ok +-STATEMENT CREATE (t:test {prop: 633546}); +---- ok +-STATEMENT CREATE (t:test {prop: 118749}); +---- ok +-STATEMENT CREATE (t:test {prop: 962647}); +---- ok +-STATEMENT CREATE (t:test {prop: 199409}); +---- ok +-STATEMENT CREATE (t:test {prop: 40113}); +---- ok +-STATEMENT CREATE (t:test {prop: 149233}); +---- ok +-STATEMENT CREATE (t:test {prop: 969580}); +---- ok +-STATEMENT CREATE (t:test {prop: 944275}); +---- ok +-STATEMENT CREATE (t:test {prop: 341325}); +---- ok +-STATEMENT CREATE (t:test {prop: 684730}); +---- ok +-STATEMENT CREATE (t:test {prop: 992927}); +---- ok +-STATEMENT CREATE (t:test {prop: 79009}); +---- ok +-STATEMENT CREATE (t:test {prop: 45664}); +---- ok +-STATEMENT CREATE (t:test {prop: 130077}); +---- ok +-STATEMENT CREATE (t:test {prop: 355045}); +---- ok +-STATEMENT CREATE (t:test {prop: 794437}); +---- ok +-STATEMENT CREATE (t:test {prop: 437596}); +---- ok +-STATEMENT CREATE (t:test {prop: 257261}); +---- ok +-STATEMENT CREATE (t:test {prop: 732013}); +---- ok +-STATEMENT CREATE (t:test {prop: 162854}); +---- ok +-STATEMENT CREATE (t:test {prop: 641731}); +---- ok +-STATEMENT CREATE (t:test {prop: 851097}); +---- ok +-STATEMENT CREATE (t:test {prop: 272082}); +---- ok +-STATEMENT CREATE (t:test {prop: 338786}); +---- ok +-STATEMENT CREATE (t:test {prop: 413508}); +---- ok +-STATEMENT CREATE (t:test {prop: 355958}); +---- ok +-STATEMENT CREATE (t:test {prop: 197648}); +---- ok +-STATEMENT CREATE (t:test {prop: 530011}); +---- ok +-STATEMENT CREATE (t:test {prop: 13327}); +---- ok +-STATEMENT CREATE (t:test {prop: 30321}); +---- ok +-STATEMENT CREATE (t:test {prop: 227045}); +---- ok +-STATEMENT CREATE (t:test {prop: 906913}); +---- ok +-STATEMENT CREATE (t:test {prop: 309002}); +---- ok +-STATEMENT CREATE (t:test {prop: 771040}); +---- ok +-STATEMENT CREATE (t:test {prop: 890462}); +---- ok +-STATEMENT CREATE (t:test {prop: 296472}); +---- ok +-STATEMENT CREATE (t:test {prop: 445692}); +---- ok +-STATEMENT CREATE (t:test {prop: 405288}); +---- ok +-STATEMENT CREATE (t:test {prop: 383125}); +---- ok +-STATEMENT CREATE (t:test {prop: 869396}); +---- ok +-STATEMENT CREATE (t:test {prop: 747098}); +---- ok +-STATEMENT CREATE (t:test {prop: 823017}); +---- ok +-STATEMENT CREATE (t:test {prop: 848844}); +---- ok +-STATEMENT CREATE (t:test {prop: 694750}); +---- ok +-STATEMENT CREATE (t:test {prop: 16053}); +---- ok +-STATEMENT CREATE (t:test {prop: 383077}); +---- ok +-STATEMENT CREATE (t:test {prop: 924730}); +---- ok +-STATEMENT CREATE (t:test {prop: 948421}); +---- ok +-STATEMENT CREATE (t:test {prop: 716845}); +---- ok +-STATEMENT CREATE (t:test {prop: 403054}); +---- ok +-STATEMENT CREATE (t:test {prop: 794788}); +---- ok +-STATEMENT CREATE (t:test {prop: 656155}); +---- ok +-STATEMENT CREATE (t:test {prop: 911738}); +---- ok +-STATEMENT CREATE (t:test {prop: 763639}); +---- ok +-STATEMENT CREATE (t:test {prop: 94528}); +---- ok +-STATEMENT CREATE (t:test {prop: 844306}); +---- ok +-STATEMENT CREATE (t:test {prop: 676993}); +---- ok +-STATEMENT CREATE (t:test {prop: 480795}); +---- ok +-STATEMENT CREATE (t:test {prop: 955216}); +---- ok +-STATEMENT CREATE (t:test {prop: 298807}); +---- ok +-STATEMENT CREATE (t:test {prop: 379283}); +---- ok +-STATEMENT CREATE (t:test {prop: 807643}); +---- ok +-STATEMENT CREATE (t:test {prop: 360614}); +---- ok +-STATEMENT CREATE (t:test {prop: 406617}); +---- ok +-STATEMENT CREATE (t:test {prop: 965665}); +---- ok +-STATEMENT CREATE (t:test {prop: 66322}); +---- ok +-STATEMENT CREATE (t:test {prop: 413794}); +---- ok +-STATEMENT CREATE (t:test {prop: 921396}); +---- ok +-STATEMENT CREATE (t:test {prop: 652423}); +---- ok +-STATEMENT CREATE (t:test {prop: 734060}); +---- ok +-STATEMENT CREATE (t:test {prop: 809078}); +---- ok +-STATEMENT CREATE (t:test {prop: 178408}); +---- ok +-STATEMENT CREATE (t:test {prop: 221777}); +---- ok +-STATEMENT CREATE (t:test {prop: 44190}); +---- ok +-STATEMENT CREATE (t:test {prop: 492583}); +---- ok +-STATEMENT CREATE (t:test {prop: 278543}); +---- ok +-STATEMENT CREATE (t:test {prop: 779103}); +---- ok +-STATEMENT CREATE (t:test {prop: 883889}); +---- ok +-STATEMENT CREATE (t:test {prop: 855262}); +---- ok +-STATEMENT CREATE (t:test {prop: 718846}); +---- ok +-STATEMENT CREATE (t:test {prop: 227347}); +---- ok +-STATEMENT CREATE (t:test {prop: 407706}); +---- ok +-STATEMENT CREATE (t:test {prop: 223388}); +---- ok +-STATEMENT CREATE (t:test {prop: 598146}); +---- ok +-STATEMENT CREATE (t:test {prop: 695753}); +---- ok +-STATEMENT CREATE (t:test {prop: 500385}); +---- ok +-STATEMENT CREATE (t:test {prop: 834117}); +---- ok +-STATEMENT CREATE (t:test {prop: 651757}); +---- ok +-STATEMENT CREATE (t:test {prop: 503413}); +---- ok +-STATEMENT CREATE (t:test {prop: 130746}); +---- ok +-STATEMENT CREATE (t:test {prop: 748460}); +---- ok +-STATEMENT CREATE (t:test {prop: 270047}); +---- ok +-STATEMENT CREATE (t:test {prop: 485148}); +---- ok +-STATEMENT CREATE (t:test {prop: 985655}); +---- ok +-STATEMENT CREATE (t:test {prop: 700794}); +---- ok +-STATEMENT CREATE (t:test {prop: 429787}); +---- ok +-STATEMENT CREATE (t:test {prop: 246981}); +---- ok +-STATEMENT CREATE (t:test {prop: 599027}); +---- ok +-STATEMENT CREATE (t:test {prop: 268317}); +---- ok +-STATEMENT CREATE (t:test {prop: 777325}); +---- ok +-STATEMENT CREATE (t:test {prop: 653737}); +---- ok +-STATEMENT CREATE (t:test {prop: 973515}); +---- ok +-STATEMENT CREATE (t:test {prop: 74436}); +---- ok +-STATEMENT CREATE (t:test {prop: 282177}); +---- ok +-STATEMENT CREATE (t:test {prop: 645108}); +---- ok +-STATEMENT CREATE (t:test {prop: 808164}); +---- ok +-STATEMENT CREATE (t:test {prop: 303322}); +---- ok +-STATEMENT CREATE (t:test {prop: 910839}); +---- ok +-STATEMENT CREATE (t:test {prop: 269770}); +---- ok +-STATEMENT CREATE (t:test {prop: 270285}); +---- ok +-STATEMENT CREATE (t:test {prop: 515274}); +---- ok +-STATEMENT CREATE (t:test {prop: 402835}); +---- ok +-STATEMENT CREATE (t:test {prop: 78701}); +---- ok +-STATEMENT CREATE (t:test {prop: 48723}); +---- ok +-STATEMENT CREATE (t:test {prop: 557896}); +---- ok +-STATEMENT CREATE (t:test {prop: 370746}); +---- ok +-STATEMENT CREATE (t:test {prop: 556497}); +---- ok +-STATEMENT CREATE (t:test {prop: 931991}); +---- ok +-STATEMENT CREATE (t:test {prop: 465148}); +---- ok +-STATEMENT CREATE (t:test {prop: 163928}); +---- ok +-STATEMENT CREATE (t:test {prop: 527426}); +---- ok +-STATEMENT CREATE (t:test {prop: 993146}); +---- ok +-STATEMENT CREATE (t:test {prop: 664782}); +---- ok +-STATEMENT CREATE (t:test {prop: 312287}); +---- ok +-STATEMENT CREATE (t:test {prop: 300143}); +---- ok +-STATEMENT CREATE (t:test {prop: 614411}); +---- ok +-STATEMENT CREATE (t:test {prop: 729016}); +---- ok +-STATEMENT CREATE (t:test {prop: 590414}); +---- ok +-STATEMENT CREATE (t:test {prop: 276285}); +---- ok +-STATEMENT CREATE (t:test {prop: 569164}); +---- ok +-STATEMENT CREATE (t:test {prop: 460467}); +---- ok +-STATEMENT CREATE (t:test {prop: 905480}); +---- ok +-STATEMENT CREATE (t:test {prop: 644540}); +---- ok +-STATEMENT CREATE (t:test {prop: 782157}); +---- ok +-STATEMENT CREATE (t:test {prop: 615006}); +---- ok +-STATEMENT CREATE (t:test {prop: 862503}); +---- ok +-STATEMENT CREATE (t:test {prop: 587280}); +---- ok +-STATEMENT CREATE (t:test {prop: 284826}); +---- ok +-STATEMENT CREATE (t:test {prop: 907171}); +---- ok +-STATEMENT CREATE (t:test {prop: 85366}); +---- ok +-STATEMENT CREATE (t:test {prop: 748935}); +---- ok +-STATEMENT CREATE (t:test {prop: 931163}); +---- ok +-STATEMENT CREATE (t:test {prop: 484848}); +---- ok +-STATEMENT CREATE (t:test {prop: 679741}); +---- ok +-STATEMENT CREATE (t:test {prop: 641246}); +---- ok +-STATEMENT CREATE (t:test {prop: 896936}); +---- ok +-STATEMENT CREATE (t:test {prop: 279149}); +---- ok +-STATEMENT CREATE (t:test {prop: 548945}); +---- ok +-STATEMENT CREATE (t:test {prop: 730193}); +---- ok +-STATEMENT CREATE (t:test {prop: 812891}); +---- ok +-STATEMENT CREATE (t:test {prop: 995366}); +---- ok +-STATEMENT CREATE (t:test {prop: 894777}); +---- ok +-STATEMENT CREATE (t:test {prop: 949839}); +---- ok +-STATEMENT CREATE (t:test {prop: 508948}); +---- ok +-STATEMENT CREATE (t:test {prop: 218269}); +---- ok +-STATEMENT CREATE (t:test {prop: 43838}); +---- ok +-STATEMENT CREATE (t:test {prop: 685098}); +---- ok +-STATEMENT CREATE (t:test {prop: 645858}); +---- ok +-STATEMENT CREATE (t:test {prop: 111081}); +---- ok +-STATEMENT CREATE (t:test {prop: 555637}); +---- ok +-STATEMENT CREATE (t:test {prop: 818603}); +---- ok +-STATEMENT CREATE (t:test {prop: 952990}); +---- ok +-STATEMENT CREATE (t:test {prop: 52748}); +---- ok +-STATEMENT CREATE (t:test {prop: 244754}); +---- ok +-STATEMENT CREATE (t:test {prop: 468927}); +---- ok +-STATEMENT CREATE (t:test {prop: 311356}); +---- ok +-STATEMENT CREATE (t:test {prop: 840054}); +---- ok +-STATEMENT CREATE (t:test {prop: 528081}); +---- ok +-STATEMENT CREATE (t:test {prop: 806835}); +---- ok +-STATEMENT CREATE (t:test {prop: 991633}); +---- ok +-STATEMENT CREATE (t:test {prop: 722259}); +---- ok +-STATEMENT CREATE (t:test {prop: 103184}); +---- ok +-STATEMENT CREATE (t:test {prop: 379164}); +---- ok +-STATEMENT CREATE (t:test {prop: 906309}); +---- ok +-STATEMENT CREATE (t:test {prop: 731419}); +---- ok +-STATEMENT CREATE (t:test {prop: 437281}); +---- ok +-STATEMENT CREATE (t:test {prop: 718916}); +---- ok +-STATEMENT CREATE (t:test {prop: 42214}); +---- ok +-STATEMENT CREATE (t:test {prop: 736711}); +---- ok +-STATEMENT CREATE (t:test {prop: 233901}); +---- ok +-STATEMENT CREATE (t:test {prop: 127059}); +---- ok +-STATEMENT CREATE (t:test {prop: 525828}); +---- ok +-STATEMENT CREATE (t:test {prop: 378222}); +---- ok +-STATEMENT CREATE (t:test {prop: 679843}); +---- ok +-STATEMENT CREATE (t:test {prop: 999060}); +---- ok +-STATEMENT CREATE (t:test {prop: 220150}); +---- ok +-STATEMENT CREATE (t:test {prop: 965517}); +---- ok +-STATEMENT CREATE (t:test {prop: 104453}); +---- ok +-STATEMENT CREATE (t:test {prop: 160735}); +---- ok +-STATEMENT CREATE (t:test {prop: 556902}); +---- ok +-STATEMENT CREATE (t:test {prop: 304154}); +---- ok +-STATEMENT CREATE (t:test {prop: 46682}); +---- ok +-STATEMENT CREATE (t:test {prop: 205979}); +---- ok +-STATEMENT CREATE (t:test {prop: 869336}); +---- ok +-STATEMENT CREATE (t:test {prop: 732927}); +---- ok +-STATEMENT CREATE (t:test {prop: 716753}); +---- ok +-STATEMENT CREATE (t:test {prop: 704889}); +---- ok +-STATEMENT CREATE (t:test {prop: 834056}); +---- ok +-STATEMENT CREATE (t:test {prop: 702031}); +---- ok +-STATEMENT CREATE (t:test {prop: 586760}); +---- ok +-STATEMENT CREATE (t:test {prop: 259709}); +---- ok +-STATEMENT CREATE (t:test {prop: 898654}); +---- ok +-STATEMENT CREATE (t:test {prop: 303912}); +---- ok +-STATEMENT CREATE (t:test {prop: 450521}); +---- ok +-STATEMENT CREATE (t:test {prop: 481379}); +---- ok +-STATEMENT CREATE (t:test {prop: 434530}); +---- ok +-STATEMENT CREATE (t:test {prop: 79697}); +---- ok +-STATEMENT CREATE (t:test {prop: 419917}); +---- ok +-STATEMENT CREATE (t:test {prop: 562329}); +---- ok +-STATEMENT CREATE (t:test {prop: 941615}); +---- ok +-STATEMENT CREATE (t:test {prop: 896423}); +---- ok +-STATEMENT CREATE (t:test {prop: 322924}); +---- ok +-STATEMENT CREATE (t:test {prop: 529291}); +---- ok +-STATEMENT CREATE (t:test {prop: 217587}); +---- ok +-STATEMENT CREATE (t:test {prop: 251456}); +---- ok +-STATEMENT CREATE (t:test {prop: 711008}); +---- ok +-STATEMENT CREATE (t:test {prop: 593857}); +---- ok +-STATEMENT CREATE (t:test {prop: 107943}); +---- ok +-STATEMENT CREATE (t:test {prop: 658907}); +---- ok +-STATEMENT CREATE (t:test {prop: 310413}); +---- ok +-STATEMENT CREATE (t:test {prop: 367406}); +---- ok +-STATEMENT CREATE (t:test {prop: 614204}); +---- ok +-STATEMENT CREATE (t:test {prop: 531727}); +---- ok +-STATEMENT CREATE (t:test {prop: 278832}); +---- ok +-STATEMENT CREATE (t:test {prop: 802426}); +---- ok +-STATEMENT CREATE (t:test {prop: 845681}); +---- ok +-STATEMENT CREATE (t:test {prop: 571743}); +---- ok +-STATEMENT CREATE (t:test {prop: 658166}); +---- ok +-STATEMENT CREATE (t:test {prop: 258100}); +---- ok +-STATEMENT CREATE (t:test {prop: 302202}); +---- ok +-STATEMENT CREATE (t:test {prop: 980585}); +---- ok +-STATEMENT CREATE (t:test {prop: 484537}); +---- ok +-STATEMENT CREATE (t:test {prop: 519399}); +---- ok +-STATEMENT CREATE (t:test {prop: 199908}); +---- ok +-STATEMENT CREATE (t:test {prop: 797823}); +---- ok +-STATEMENT CREATE (t:test {prop: 94283}); +---- ok +-STATEMENT CREATE (t:test {prop: 10249}); +---- ok +-STATEMENT CREATE (t:test {prop: 300542}); +---- ok +-STATEMENT CREATE (t:test {prop: 654196}); +---- ok +-STATEMENT CREATE (t:test {prop: 171127}); +---- ok +-STATEMENT CREATE (t:test {prop: 183243}); +---- ok +-STATEMENT CREATE (t:test {prop: 976080}); +---- ok +-STATEMENT CREATE (t:test {prop: 1137}); +---- ok +-STATEMENT CREATE (t:test {prop: 196600}); +---- ok +-STATEMENT CREATE (t:test {prop: 492071}); +---- ok +-STATEMENT CREATE (t:test {prop: 466564}); +---- ok +-STATEMENT CREATE (t:test {prop: 455187}); +---- ok +-STATEMENT CREATE (t:test {prop: 933706}); +---- ok +-STATEMENT CREATE (t:test {prop: 502029}); +---- ok +-STATEMENT CREATE (t:test {prop: 850228}); +---- ok +-STATEMENT CREATE (t:test {prop: 28043}); +---- ok +-STATEMENT CREATE (t:test {prop: 472066}); +---- ok +-STATEMENT CREATE (t:test {prop: 272499}); +---- ok +-STATEMENT CREATE (t:test {prop: 261414}); +---- ok +-STATEMENT CREATE (t:test {prop: 229384}); +---- ok +-STATEMENT CREATE (t:test {prop: 794331}); +---- ok +-STATEMENT CREATE (t:test {prop: 796396}); +---- ok +-STATEMENT CREATE (t:test {prop: 411551}); +---- ok +-STATEMENT CREATE (t:test {prop: 416785}); +---- ok +-STATEMENT CREATE (t:test {prop: 763713}); +---- ok +-STATEMENT CREATE (t:test {prop: 906542}); +---- ok +-STATEMENT CREATE (t:test {prop: 908013}); +---- ok +-STATEMENT CREATE (t:test {prop: 228753}); +---- ok +-STATEMENT CREATE (t:test {prop: 194325}); +---- ok +-STATEMENT CREATE (t:test {prop: 243644}); +---- ok +-STATEMENT CREATE (t:test {prop: 104894}); +---- ok +-STATEMENT CREATE (t:test {prop: 930687}); +---- ok +-STATEMENT CREATE (t:test {prop: 887224}); +---- ok +-STATEMENT CREATE (t:test {prop: 237511}); +---- ok +-STATEMENT CREATE (t:test {prop: 665101}); +---- ok +-STATEMENT CREATE (t:test {prop: 335409}); +---- ok +-STATEMENT CREATE (t:test {prop: 877542}); +---- ok +-STATEMENT CREATE (t:test {prop: 979439}); +---- ok +-STATEMENT CREATE (t:test {prop: 851125}); +---- ok +-STATEMENT CREATE (t:test {prop: 34629}); +---- ok +-STATEMENT CREATE (t:test {prop: 575704}); +---- ok +-STATEMENT CREATE (t:test {prop: 245503}); +---- ok +-STATEMENT CREATE (t:test {prop: 613599}); +---- ok +-STATEMENT CREATE (t:test {prop: 892191}); +---- ok +-STATEMENT CREATE (t:test {prop: 364929}); +---- ok +-STATEMENT CREATE (t:test {prop: 529979}); +---- ok +-STATEMENT CREATE (t:test {prop: 351868}); +---- ok +-STATEMENT CREATE (t:test {prop: 182398}); +---- ok +-STATEMENT CREATE (t:test {prop: 290169}); +---- ok +-STATEMENT CREATE (t:test {prop: 884269}); +---- ok +-STATEMENT CREATE (t:test {prop: 931715}); +---- ok +-STATEMENT CREATE (t:test {prop: 389661}); +---- ok +-STATEMENT CREATE (t:test {prop: 969038}); +---- ok +-STATEMENT CREATE (t:test {prop: 716692}); +---- ok +-STATEMENT CREATE (t:test {prop: 253572}); +---- ok +-STATEMENT CREATE (t:test {prop: 151441}); +---- ok +-STATEMENT CREATE (t:test {prop: 905500}); +---- ok +-STATEMENT CREATE (t:test {prop: 940201}); +---- ok +-STATEMENT CREATE (t:test {prop: 735211}); +---- ok +-STATEMENT CREATE (t:test {prop: 316484}); +---- ok +-STATEMENT CREATE (t:test {prop: 462899}); +---- ok +-STATEMENT CREATE (t:test {prop: 658875}); +---- ok +-STATEMENT CREATE (t:test {prop: 454514}); +---- ok +-STATEMENT CREATE (t:test {prop: 24601}); +---- ok +-STATEMENT CREATE (t:test {prop: 315524}); +---- ok +-STATEMENT CREATE (t:test {prop: 936371}); +---- ok +-STATEMENT CREATE (t:test {prop: 486647}); +---- ok +-STATEMENT CREATE (t:test {prop: 7034}); +---- ok +-STATEMENT CREATE (t:test {prop: 666847}); +---- ok +-STATEMENT CREATE (t:test {prop: 278954}); +---- ok +-STATEMENT CREATE (t:test {prop: 912881}); +---- ok +-STATEMENT CREATE (t:test {prop: 742410}); +---- ok +-STATEMENT CREATE (t:test {prop: 766313}); +---- ok +-STATEMENT CREATE (t:test {prop: 131171}); +---- ok +-STATEMENT CREATE (t:test {prop: 434834}); +---- ok +-STATEMENT CREATE (t:test {prop: 690786}); +---- ok +-STATEMENT CREATE (t:test {prop: 559181}); +---- ok +-STATEMENT CREATE (t:test {prop: 290512}); +---- ok +-STATEMENT CREATE (t:test {prop: 154897}); +---- ok +-STATEMENT CREATE (t:test {prop: 435565}); +---- ok +-STATEMENT CREATE (t:test {prop: 692775}); +---- ok +-STATEMENT CREATE (t:test {prop: 353730}); +---- ok +-STATEMENT CREATE (t:test {prop: 83193}); +---- ok +-STATEMENT CREATE (t:test {prop: 600170}); +---- ok +-STATEMENT CREATE (t:test {prop: 488772}); +---- ok +-STATEMENT CREATE (t:test {prop: 368318}); +---- ok +-STATEMENT CREATE (t:test {prop: 37490}); +---- ok +-STATEMENT CREATE (t:test {prop: 721387}); +---- ok +-STATEMENT CREATE (t:test {prop: 822049}); +---- ok +-STATEMENT CREATE (t:test {prop: 235905}); +---- ok +-STATEMENT CREATE (t:test {prop: 26681}); +---- ok +-STATEMENT CREATE (t:test {prop: 394256}); +---- ok +-STATEMENT CREATE (t:test {prop: 855983}); +---- ok +-STATEMENT CREATE (t:test {prop: 428294}); +---- ok +-STATEMENT CREATE (t:test {prop: 438943}); +---- ok +-STATEMENT CREATE (t:test {prop: 803942}); +---- ok +-STATEMENT CREATE (t:test {prop: 716594}); +---- ok +-STATEMENT CREATE (t:test {prop: 178702}); +---- ok +-STATEMENT CREATE (t:test {prop: 958197}); +---- ok +-STATEMENT CREATE (t:test {prop: 631226}); +---- ok +-STATEMENT CREATE (t:test {prop: 147619}); +---- ok +-STATEMENT CREATE (t:test {prop: 706681}); +---- ok +-STATEMENT CREATE (t:test {prop: 688111}); +---- ok +-STATEMENT CREATE (t:test {prop: 993403}); +---- ok +-STATEMENT CREATE (t:test {prop: 369240}); +---- ok +-STATEMENT CREATE (t:test {prop: 723901}); +---- ok +-STATEMENT CREATE (t:test {prop: 982477}); +---- ok +-STATEMENT CREATE (t:test {prop: 993843}); +---- ok +-STATEMENT CREATE (t:test {prop: 992903}); +---- ok +-STATEMENT CREATE (t:test {prop: 61096}); +---- ok +-STATEMENT CREATE (t:test {prop: 800681}); +---- ok +-STATEMENT CREATE (t:test {prop: 182219}); +---- ok +-STATEMENT CREATE (t:test {prop: 524687}); +---- ok +-STATEMENT CREATE (t:test {prop: 370830}); +---- ok +-STATEMENT CREATE (t:test {prop: 266442}); +---- ok +-STATEMENT CREATE (t:test {prop: 286302}); +---- ok +-STATEMENT CREATE (t:test {prop: 605010}); +---- ok +-STATEMENT CREATE (t:test {prop: 876564}); +---- ok +-STATEMENT CREATE (t:test {prop: 444555}); +---- ok +-STATEMENT CREATE (t:test {prop: 273905}); +---- ok +-STATEMENT CREATE (t:test {prop: 65051}); +---- ok +-STATEMENT CREATE (t:test {prop: 202782}); +---- ok +-STATEMENT CREATE (t:test {prop: 183470}); +---- ok +-STATEMENT CREATE (t:test {prop: 1004}); +---- ok +-STATEMENT CREATE (t:test {prop: 377000}); +---- ok +-STATEMENT CREATE (t:test {prop: 277062}); +---- ok +-STATEMENT CREATE (t:test {prop: 568541}); +---- ok +-STATEMENT CREATE (t:test {prop: 848698}); +---- ok +-STATEMENT CREATE (t:test {prop: 375432}); +---- ok +-STATEMENT CREATE (t:test {prop: 320096}); +---- ok +-STATEMENT CREATE (t:test {prop: 11364}); +---- ok +-STATEMENT CREATE (t:test {prop: 520285}); +---- ok +-STATEMENT CREATE (t:test {prop: 726047}); +---- ok +-STATEMENT CREATE (t:test {prop: 729686}); +---- ok +-STATEMENT CREATE (t:test {prop: 507585}); +---- ok +-STATEMENT CREATE (t:test {prop: 261763}); +---- ok +-STATEMENT CREATE (t:test {prop: 626518}); +---- ok +-STATEMENT CREATE (t:test {prop: 98900}); +---- ok +-STATEMENT CREATE (t:test {prop: 23800}); +---- ok +-STATEMENT CREATE (t:test {prop: 675352}); +---- ok +-STATEMENT CREATE (t:test {prop: 42506}); +---- ok +-STATEMENT CREATE (t:test {prop: 612689}); +---- ok +-STATEMENT CREATE (t:test {prop: 65782}); +---- ok +-STATEMENT CREATE (t:test {prop: 89549}); +---- ok +-STATEMENT CREATE (t:test {prop: 510044}); +---- ok +-STATEMENT CREATE (t:test {prop: 815076}); +---- ok +-STATEMENT CREATE (t:test {prop: 655960}); +---- ok +-STATEMENT CREATE (t:test {prop: 900678}); +---- ok +-STATEMENT CREATE (t:test {prop: 797257}); +---- ok +-STATEMENT CREATE (t:test {prop: 844660}); +---- ok +-STATEMENT CREATE (t:test {prop: 554300}); +---- ok +-STATEMENT CREATE (t:test {prop: 364014}); +---- ok +-STATEMENT CREATE (t:test {prop: 249365}); +---- ok +-STATEMENT CREATE (t:test {prop: 757619}); +---- ok +-STATEMENT CREATE (t:test {prop: 926194}); +---- ok +-STATEMENT CREATE (t:test {prop: 622557}); +---- ok +-STATEMENT CREATE (t:test {prop: 962230}); +---- ok +-STATEMENT CREATE (t:test {prop: 222319}); +---- ok +-STATEMENT CREATE (t:test {prop: 153757}); +---- ok +-STATEMENT CREATE (t:test {prop: 7976}); +---- ok +-STATEMENT CREATE (t:test {prop: 210663}); +---- ok +-STATEMENT CREATE (t:test {prop: 972912}); +---- ok +-STATEMENT CREATE (t:test {prop: 818607}); +---- ok +-STATEMENT CREATE (t:test {prop: 446243}); +---- ok +-STATEMENT CREATE (t:test {prop: 118491}); +---- ok +-STATEMENT CREATE (t:test {prop: 879085}); +---- ok +-STATEMENT CREATE (t:test {prop: 883642}); +---- ok +-STATEMENT CREATE (t:test {prop: 443085}); +---- ok +-STATEMENT CREATE (t:test {prop: 612533}); +---- ok +-STATEMENT CREATE (t:test {prop: 849319}); +---- ok +-STATEMENT CREATE (t:test {prop: 305545}); +---- ok +-STATEMENT CREATE (t:test {prop: 4953}); +---- ok +-STATEMENT CREATE (t:test {prop: 444815}); +---- ok +-STATEMENT CREATE (t:test {prop: 712537}); +---- ok +-STATEMENT CREATE (t:test {prop: 235133}); +---- ok +-STATEMENT CREATE (t:test {prop: 927909}); +---- ok +-STATEMENT CREATE (t:test {prop: 783819}); +---- ok +-STATEMENT CREATE (t:test {prop: 766468}); +---- ok +-STATEMENT CREATE (t:test {prop: 742359}); +---- ok +-STATEMENT CREATE (t:test {prop: 145967}); +---- ok +-STATEMENT CREATE (t:test {prop: 936738}); +---- ok +-STATEMENT CREATE (t:test {prop: 407925}); +---- ok +-STATEMENT CREATE (t:test {prop: 2802}); +---- ok +-STATEMENT CREATE (t:test {prop: 521486}); +---- ok +-STATEMENT CREATE (t:test {prop: 328909}); +---- ok +-STATEMENT CREATE (t:test {prop: 958277}); +---- ok +-STATEMENT CREATE (t:test {prop: 923034}); +---- ok +-STATEMENT CREATE (t:test {prop: 566563}); +---- ok +-STATEMENT CREATE (t:test {prop: 223003}); +---- ok +-STATEMENT CREATE (t:test {prop: 123456}); +---- ok +-STATEMENT CREATE (t:test {prop: 106869}); +---- ok +-STATEMENT CREATE (t:test {prop: 12358}); +---- ok +-STATEMENT CREATE (t:test {prop: 61100}); +---- ok +-STATEMENT CREATE (t:test {prop: 285634}); +---- ok +-STATEMENT CREATE (t:test {prop: 288751}); +---- ok +-STATEMENT CREATE (t:test {prop: 422579}); +---- ok +-STATEMENT CREATE (t:test {prop: 442491}); +---- ok +-STATEMENT CREATE (t:test {prop: 980503}); +---- ok +-STATEMENT CREATE (t:test {prop: 24166}); +---- ok +-STATEMENT CREATE (t:test {prop: 40793}); +---- ok +-STATEMENT CREATE (t:test {prop: 48019}); +---- ok +-STATEMENT CREATE (t:test {prop: 577511}); +---- ok +-STATEMENT CREATE (t:test {prop: 675101}); +---- ok +-STATEMENT CREATE (t:test {prop: 328317}); +---- ok +-STATEMENT CREATE (t:test {prop: 636578}); +---- ok +-STATEMENT CREATE (t:test {prop: 441068}); +---- ok +-STATEMENT CREATE (t:test {prop: 80624}); +---- ok +-STATEMENT CREATE (t:test {prop: 510727}); +---- ok +-STATEMENT CREATE (t:test {prop: 5303}); +---- ok +-STATEMENT CREATE (t:test {prop: 307947}); +---- ok +-STATEMENT CREATE (t:test {prop: 790271}); +---- ok +-STATEMENT CREATE (t:test {prop: 180550}); +---- ok +-STATEMENT CREATE (t:test {prop: 163072}); +---- ok +-STATEMENT CREATE (t:test {prop: 536795}); +---- ok +-STATEMENT CREATE (t:test {prop: 650288}); +---- ok +-STATEMENT CREATE (t:test {prop: 524475}); +---- ok +-STATEMENT CREATE (t:test {prop: 717488}); +---- ok +-STATEMENT CREATE (t:test {prop: 151086}); +---- ok +-STATEMENT CREATE (t:test {prop: 996850}); +---- ok +-STATEMENT CREATE (t:test {prop: 835781}); +---- ok +-STATEMENT CREATE (t:test {prop: 284519}); +---- ok +-STATEMENT CREATE (t:test {prop: 155000}); +---- ok +-STATEMENT CREATE (t:test {prop: 182989}); +---- ok +-STATEMENT CREATE (t:test {prop: 477640}); +---- ok +-STATEMENT CREATE (t:test {prop: 110265}); +---- ok +-STATEMENT CREATE (t:test {prop: 129593}); +---- ok +-STATEMENT CREATE (t:test {prop: 377401}); +---- ok +-STATEMENT CREATE (t:test {prop: 87465}); +---- ok +-STATEMENT CREATE (t:test {prop: 233803}); +---- ok +-STATEMENT CREATE (t:test {prop: 150374}); +---- ok +-STATEMENT CREATE (t:test {prop: 851602}); +---- ok +-STATEMENT CREATE (t:test {prop: 269131}); +---- ok +-STATEMENT CREATE (t:test {prop: 773572}); +---- ok +-STATEMENT CREATE (t:test {prop: 473887}); +---- ok +-STATEMENT CREATE (t:test {prop: 189190}); +---- ok +-STATEMENT CREATE (t:test {prop: 747668}); +---- ok +-STATEMENT CREATE (t:test {prop: 722811}); +---- ok +-STATEMENT CREATE (t:test {prop: 509996}); +---- ok +-STATEMENT CREATE (t:test {prop: 781738}); +---- ok +-STATEMENT CREATE (t:test {prop: 524368}); +---- ok +-STATEMENT CREATE (t:test {prop: 909836}); +---- ok +-STATEMENT CREATE (t:test {prop: 174371}); +---- ok +-STATEMENT CREATE (t:test {prop: 946953}); +---- ok +-STATEMENT CREATE (t:test {prop: 505352}); +---- ok +-STATEMENT CREATE (t:test {prop: 60771}); +---- ok +-STATEMENT CREATE (t:test {prop: 296237}); +---- ok +-STATEMENT CREATE (t:test {prop: 860772}); +---- ok +-STATEMENT CREATE (t:test {prop: 81368}); +---- ok +-STATEMENT CREATE (t:test {prop: 300869}); +---- ok +-STATEMENT CREATE (t:test {prop: 531159}); +---- ok +-STATEMENT CREATE (t:test {prop: 87196}); +---- ok +-STATEMENT CREATE (t:test {prop: 23579}); +---- ok +-STATEMENT CREATE (t:test {prop: 764321}); +---- ok +-STATEMENT CREATE (t:test {prop: 996002}); +---- ok +-STATEMENT CREATE (t:test {prop: 225832}); +---- ok +-STATEMENT CREATE (t:test {prop: 545434}); +---- ok +-STATEMENT CREATE (t:test {prop: 678405}); +---- ok +-STATEMENT CREATE (t:test {prop: 529163}); +---- ok +-STATEMENT CREATE (t:test {prop: 499039}); +---- ok +-STATEMENT CREATE (t:test {prop: 9073}); +---- ok +-STATEMENT CREATE (t:test {prop: 259705}); +---- ok +-STATEMENT CREATE (t:test {prop: 950560}); +---- ok +-STATEMENT CREATE (t:test {prop: 375828}); +---- ok +-STATEMENT CREATE (t:test {prop: 57163}); +---- ok +-STATEMENT CREATE (t:test {prop: 820917}); +---- ok +-STATEMENT CREATE (t:test {prop: 321582}); +---- ok +-STATEMENT CREATE (t:test {prop: 86851}); +---- ok +-STATEMENT CREATE (t:test {prop: 152755}); +---- ok +-STATEMENT CREATE (t:test {prop: 63447}); +---- ok +-STATEMENT CREATE (t:test {prop: 100282}); +---- ok +-STATEMENT CREATE (t:test {prop: 186001}); +---- ok +-STATEMENT CREATE (t:test {prop: 111438}); +---- ok +-STATEMENT CREATE (t:test {prop: 552731}); +---- ok +-STATEMENT CREATE (t:test {prop: 261966}); +---- ok +-STATEMENT CREATE (t:test {prop: 679043}); +---- ok +-STATEMENT CREATE (t:test {prop: 936621}); +---- ok +-STATEMENT CREATE (t:test {prop: 981323}); +---- ok +-STATEMENT CREATE (t:test {prop: 244820}); +---- ok +-STATEMENT CREATE (t:test {prop: 890135}); +---- ok +-STATEMENT CREATE (t:test {prop: 263928}); +---- ok +-STATEMENT CREATE (t:test {prop: 982793}); +---- ok +-STATEMENT CREATE (t:test {prop: 686687}); +---- ok +-STATEMENT CREATE (t:test {prop: 271797}); +---- ok +-STATEMENT CREATE (t:test {prop: 142153}); +---- ok +-STATEMENT CREATE (t:test {prop: 478431}); +---- ok +-STATEMENT CREATE (t:test {prop: 803793}); +---- ok +-STATEMENT CREATE (t:test {prop: 132104}); +---- ok +-STATEMENT CREATE (t:test {prop: 848912}); +---- ok +-STATEMENT CREATE (t:test {prop: 108106}); +---- ok +-STATEMENT CREATE (t:test {prop: 836554}); +---- ok +-STATEMENT CREATE (t:test {prop: 409419}); +---- ok +-STATEMENT CREATE (t:test {prop: 128623}); +---- ok +-STATEMENT CREATE (t:test {prop: 509498}); +---- ok +-STATEMENT CREATE (t:test {prop: 802074}); +---- ok +-STATEMENT CREATE (t:test {prop: 930192}); +---- ok +-STATEMENT CREATE (t:test {prop: 962701}); +---- ok +-STATEMENT CREATE (t:test {prop: 662407}); +---- ok +-STATEMENT CREATE (t:test {prop: 188217}); +---- ok +-STATEMENT CREATE (t:test {prop: 505128}); +---- ok +-STATEMENT CREATE (t:test {prop: 787510}); +---- ok +-STATEMENT CREATE (t:test {prop: 736606}); +---- ok +-STATEMENT CREATE (t:test {prop: 966436}); +---- ok +-STATEMENT CREATE (t:test {prop: 931852}); +---- ok +-STATEMENT CREATE (t:test {prop: 870601}); +---- ok +-STATEMENT CREATE (t:test {prop: 974889}); +---- ok +-STATEMENT CREATE (t:test {prop: 661803}); +---- ok +-STATEMENT CREATE (t:test {prop: 605729}); +---- ok +-STATEMENT CREATE (t:test {prop: 927313}); +---- ok +-STATEMENT CREATE (t:test {prop: 28283}); +---- ok +-STATEMENT CREATE (t:test {prop: 373550}); +---- ok +-STATEMENT CREATE (t:test {prop: 445119}); +---- ok +-STATEMENT CREATE (t:test {prop: 145816}); +---- ok +-STATEMENT CREATE (t:test {prop: 586825}); +---- ok +-STATEMENT CREATE (t:test {prop: 730794}); +---- ok +-STATEMENT CREATE (t:test {prop: 761407}); +---- ok +-STATEMENT CREATE (t:test {prop: 518631}); +---- ok +-STATEMENT CREATE (t:test {prop: 352978}); +---- ok +-STATEMENT CREATE (t:test {prop: 938209}); +---- ok +-STATEMENT CREATE (t:test {prop: 532104}); +---- ok +-STATEMENT CREATE (t:test {prop: 960463}); +---- ok +-STATEMENT CREATE (t:test {prop: 833288}); +---- ok +-STATEMENT CREATE (t:test {prop: 661514}); +---- ok +-STATEMENT CREATE (t:test {prop: 557267}); +---- ok +-STATEMENT CREATE (t:test {prop: 605504}); +---- ok +-STATEMENT CREATE (t:test {prop: 666709}); +---- ok +-STATEMENT CREATE (t:test {prop: 776180}); +---- ok +-STATEMENT CREATE (t:test {prop: 257868}); +---- ok +-STATEMENT CREATE (t:test {prop: 744556}); +---- ok +-STATEMENT CREATE (t:test {prop: 187293}); +---- ok +-STATEMENT CREATE (t:test {prop: 368063}); +---- ok +-STATEMENT CREATE (t:test {prop: 678277}); +---- ok +-STATEMENT CREATE (t:test {prop: 597821}); +---- ok +-STATEMENT CREATE (t:test {prop: 74647}); +---- ok +-STATEMENT CREATE (t:test {prop: 362909}); +---- ok +-STATEMENT CREATE (t:test {prop: 31839}); +---- ok +-STATEMENT CREATE (t:test {prop: 316611}); +---- ok +-STATEMENT CREATE (t:test {prop: 579518}); +---- ok +-STATEMENT CREATE (t:test {prop: 884048}); +---- ok +-STATEMENT CREATE (t:test {prop: 540016}); +---- ok +-STATEMENT CREATE (t:test {prop: 388338}); +---- ok +-STATEMENT CREATE (t:test {prop: 702128}); +---- ok +-STATEMENT CREATE (t:test {prop: 314434}); +---- ok +-STATEMENT CREATE (t:test {prop: 204689}); +---- ok +-STATEMENT CREATE (t:test {prop: 136387}); +---- ok +-STATEMENT CREATE (t:test {prop: 290528}); +---- ok +-STATEMENT CREATE (t:test {prop: 938776}); +---- ok +-STATEMENT CREATE (t:test {prop: 358585}); +---- ok +-STATEMENT CREATE (t:test {prop: 459184}); +---- ok +-STATEMENT CREATE (t:test {prop: 927309}); +---- ok +-STATEMENT CREATE (t:test {prop: 749116}); +---- ok +-STATEMENT CREATE (t:test {prop: 780}); +---- ok +-STATEMENT CREATE (t:test {prop: 124541}); +---- ok +-STATEMENT CREATE (t:test {prop: 300274}); +---- ok +-STATEMENT CREATE (t:test {prop: 55403}); +---- ok +-STATEMENT CREATE (t:test {prop: 769252}); +---- ok +-STATEMENT CREATE (t:test {prop: 130345}); +---- ok +-STATEMENT CREATE (t:test {prop: 763250}); +---- ok +-STATEMENT CREATE (t:test {prop: 158323}); +---- ok +-STATEMENT CREATE (t:test {prop: 899732}); +---- ok +-STATEMENT CREATE (t:test {prop: 836127}); +---- ok +-STATEMENT CREATE (t:test {prop: 293865}); +---- ok +-STATEMENT CREATE (t:test {prop: 56297}); +---- ok +-STATEMENT CREATE (t:test {prop: 23037}); +---- ok +-STATEMENT CREATE (t:test {prop: 381912}); +---- ok +-STATEMENT CREATE (t:test {prop: 287318}); +---- ok +-STATEMENT CREATE (t:test {prop: 18744}); +---- ok +-STATEMENT CREATE (t:test {prop: 771263}); +---- ok +-STATEMENT CREATE (t:test {prop: 948148}); +---- ok +-STATEMENT CREATE (t:test {prop: 928583}); +---- ok +-STATEMENT CREATE (t:test {prop: 851739}); +---- ok +-STATEMENT CREATE (t:test {prop: 719619}); +---- ok +-STATEMENT CREATE (t:test {prop: 71516}); +---- ok +-STATEMENT CREATE (t:test {prop: 946238}); +---- ok +-STATEMENT CREATE (t:test {prop: 420563}); +---- ok +-STATEMENT CREATE (t:test {prop: 514359}); +---- ok +-STATEMENT CREATE (t:test {prop: 560498}); +---- ok +-STATEMENT CREATE (t:test {prop: 423410}); +---- ok +-STATEMENT CREATE (t:test {prop: 250923}); +---- ok +-STATEMENT CREATE (t:test {prop: 600534}); +---- ok +-STATEMENT CREATE (t:test {prop: 427837}); +---- ok +-STATEMENT CREATE (t:test {prop: 677999}); +---- ok +-STATEMENT CREATE (t:test {prop: 257686}); +---- ok +-STATEMENT CREATE (t:test {prop: 618827}); +---- ok +-STATEMENT CREATE (t:test {prop: 536638}); +---- ok +-STATEMENT CREATE (t:test {prop: 77512}); +---- ok +-STATEMENT CREATE (t:test {prop: 12488}); +---- ok +-STATEMENT CREATE (t:test {prop: 601316}); +---- ok +-STATEMENT CREATE (t:test {prop: 894109}); +---- ok +-STATEMENT CREATE (t:test {prop: 460999}); +---- ok +-STATEMENT CREATE (t:test {prop: 347996}); +---- ok +-STATEMENT CREATE (t:test {prop: 700848}); +---- ok +-STATEMENT CREATE (t:test {prop: 16937}); +---- ok +-STATEMENT CREATE (t:test {prop: 361215}); +---- ok +-STATEMENT CREATE (t:test {prop: 103699}); +---- ok +-STATEMENT CREATE (t:test {prop: 295861}); +---- ok +-STATEMENT CREATE (t:test {prop: 741718}); +---- ok +-STATEMENT CREATE (t:test {prop: 420333}); +---- ok +-STATEMENT CREATE (t:test {prop: 902523}); +---- ok +-STATEMENT CREATE (t:test {prop: 690818}); +---- ok +-STATEMENT CREATE (t:test {prop: 229071}); +---- ok +-STATEMENT CREATE (t:test {prop: 248610}); +---- ok +-STATEMENT CREATE (t:test {prop: 435857}); +---- ok +-STATEMENT CREATE (t:test {prop: 181040}); +---- ok +-STATEMENT CREATE (t:test {prop: 81924}); +---- ok +-STATEMENT CREATE (t:test {prop: 110538}); +---- ok +-STATEMENT CREATE (t:test {prop: 201614}); +---- ok +-STATEMENT CREATE (t:test {prop: 775779}); +---- ok +-STATEMENT CREATE (t:test {prop: 628070}); +---- ok +-STATEMENT CREATE (t:test {prop: 80510}); +---- ok +-STATEMENT CREATE (t:test {prop: 112393}); +---- ok +-STATEMENT CREATE (t:test {prop: 794113}); +---- ok +-STATEMENT CREATE (t:test {prop: 116049}); +---- ok +-STATEMENT CREATE (t:test {prop: 278590}); +---- ok +-STATEMENT CREATE (t:test {prop: 143843}); +---- ok +-STATEMENT CREATE (t:test {prop: 651313}); +---- ok +-STATEMENT CREATE (t:test {prop: 368741}); +---- ok +-STATEMENT CREATE (t:test {prop: 426920}); +---- ok +-STATEMENT CREATE (t:test {prop: 159284}); +---- ok +-STATEMENT CREATE (t:test {prop: 507100}); +---- ok +-STATEMENT CREATE (t:test {prop: 975150}); +---- ok +-STATEMENT CREATE (t:test {prop: 337066}); +---- ok +-STATEMENT CREATE (t:test {prop: 404087}); +---- ok +-STATEMENT CREATE (t:test {prop: 678169}); +---- ok +-STATEMENT CREATE (t:test {prop: 372089}); +---- ok +-STATEMENT CREATE (t:test {prop: 238502}); +---- ok +-STATEMENT CREATE (t:test {prop: 993128}); +---- ok +-STATEMENT CREATE (t:test {prop: 684006}); +---- ok +-STATEMENT CREATE (t:test {prop: 346116}); +---- ok +-STATEMENT CREATE (t:test {prop: 206360}); +---- ok +-STATEMENT CREATE (t:test {prop: 402808}); +---- ok +-STATEMENT CREATE (t:test {prop: 591218}); +---- ok +-STATEMENT CREATE (t:test {prop: 54347}); +---- ok +-STATEMENT CREATE (t:test {prop: 842657}); +---- ok +-STATEMENT CREATE (t:test {prop: 939824}); +---- ok +-STATEMENT CREATE (t:test {prop: 574638}); +---- ok +-STATEMENT CREATE (t:test {prop: 976484}); +---- ok +-STATEMENT CREATE (t:test {prop: 251134}); +---- ok +-STATEMENT CREATE (t:test {prop: 534303}); +---- ok +-STATEMENT CREATE (t:test {prop: 778352}); +---- ok +-STATEMENT CREATE (t:test {prop: 782021}); +---- ok +-STATEMENT CREATE (t:test {prop: 408868}); +---- ok +-STATEMENT CREATE (t:test {prop: 571636}); +---- ok +-STATEMENT CREATE (t:test {prop: 745642}); +---- ok +-STATEMENT CREATE (t:test {prop: 975920}); +---- ok +-STATEMENT CREATE (t:test {prop: 863739}); +---- ok +-STATEMENT CREATE (t:test {prop: 762762}); +---- ok +-STATEMENT CREATE (t:test {prop: 986599}); +---- ok +-STATEMENT CREATE (t:test {prop: 137739}); +---- ok +-STATEMENT CREATE (t:test {prop: 884730}); +---- ok +-STATEMENT CREATE (t:test {prop: 970536}); +---- ok +-STATEMENT CREATE (t:test {prop: 844175}); +---- ok +-STATEMENT CREATE (t:test {prop: 440193}); +---- ok +-STATEMENT CREATE (t:test {prop: 53781}); +---- ok +-STATEMENT CREATE (t:test {prop: 633828}); +---- ok +-STATEMENT CREATE (t:test {prop: 64328}); +---- ok +-STATEMENT CREATE (t:test {prop: 498447}); +---- ok +-STATEMENT CREATE (t:test {prop: 222722}); +---- ok +-STATEMENT CREATE (t:test {prop: 285610}); +---- ok +-STATEMENT CREATE (t:test {prop: 372000}); +---- ok +-STATEMENT CREATE (t:test {prop: 624701}); +---- ok +-STATEMENT CREATE (t:test {prop: 964487}); +---- ok +-STATEMENT CREATE (t:test {prop: 456976}); +---- ok +-STATEMENT CREATE (t:test {prop: 5433}); +---- ok +-STATEMENT CREATE (t:test {prop: 35808}); +---- ok +-STATEMENT CREATE (t:test {prop: 927395}); +---- ok +-STATEMENT CREATE (t:test {prop: 262634}); +---- ok +-STATEMENT CREATE (t:test {prop: 42024}); +---- ok +-STATEMENT CREATE (t:test {prop: 560551}); +---- ok +-STATEMENT CREATE (t:test {prop: 190491}); +---- ok +-STATEMENT CREATE (t:test {prop: 20575}); +---- ok +-STATEMENT CREATE (t:test {prop: 291781}); +---- ok +-STATEMENT CREATE (t:test {prop: 767868}); +---- ok +-STATEMENT CREATE (t:test {prop: 331972}); +---- ok +-STATEMENT CREATE (t:test {prop: 599195}); +---- ok +-STATEMENT CREATE (t:test {prop: 545147}); +---- ok +-STATEMENT CREATE (t:test {prop: 522753}); +---- ok +-STATEMENT CREATE (t:test {prop: 947935}); +---- ok +-STATEMENT CREATE (t:test {prop: 332976}); +---- ok +-STATEMENT CREATE (t:test {prop: 706032}); +---- ok +-STATEMENT CREATE (t:test {prop: 880220}); +---- ok +-STATEMENT CREATE (t:test {prop: 434428}); +---- ok +-STATEMENT CREATE (t:test {prop: 705947}); +---- ok +-STATEMENT CREATE (t:test {prop: 326987}); +---- ok +-STATEMENT CREATE (t:test {prop: 931126}); +---- ok +-STATEMENT CREATE (t:test {prop: 70044}); +---- ok +-STATEMENT CREATE (t:test {prop: 859482}); +---- ok +-STATEMENT CREATE (t:test {prop: 422853}); +---- ok +-STATEMENT CREATE (t:test {prop: 331618}); +---- ok +-STATEMENT CREATE (t:test {prop: 115661}); +---- ok +-STATEMENT CREATE (t:test {prop: 468219}); +---- ok +-STATEMENT CREATE (t:test {prop: 910328}); +---- ok +-STATEMENT CREATE (t:test {prop: 500478}); +---- ok +-STATEMENT CREATE (t:test {prop: 168475}); +---- ok +-STATEMENT CREATE (t:test {prop: 235607}); +---- ok +-STATEMENT CREATE (t:test {prop: 567646}); +---- ok +-STATEMENT CREATE (t:test {prop: 376874}); +---- ok +-STATEMENT CREATE (t:test {prop: 783987}); +---- ok +-STATEMENT CREATE (t:test {prop: 465000}); +---- ok +-STATEMENT CREATE (t:test {prop: 488670}); +---- ok +-STATEMENT CREATE (t:test {prop: 85034}); +---- ok +-STATEMENT CREATE (t:test {prop: 790785}); +---- ok +-STATEMENT CREATE (t:test {prop: 106110}); +---- ok +-STATEMENT CREATE (t:test {prop: 668802}); +---- ok +-STATEMENT CREATE (t:test {prop: 745436}); +---- ok +-STATEMENT CREATE (t:test {prop: 597743}); +---- ok +-STATEMENT CREATE (t:test {prop: 197076}); +---- ok +-STATEMENT CREATE (t:test {prop: 49246}); +---- ok +-STATEMENT CREATE (t:test {prop: 344819}); +---- ok +-STATEMENT CREATE (t:test {prop: 257229}); +---- ok +-STATEMENT CREATE (t:test {prop: 473379}); +---- ok +-STATEMENT CREATE (t:test {prop: 47470}); +---- ok +-STATEMENT CREATE (t:test {prop: 195244}); +---- ok +-STATEMENT CREATE (t:test {prop: 922860}); +---- ok +-STATEMENT CREATE (t:test {prop: 341505}); +---- ok +-STATEMENT CREATE (t:test {prop: 611146}); +---- ok +-STATEMENT CREATE (t:test {prop: 704694}); +---- ok +-STATEMENT CREATE (t:test {prop: 522725}); +---- ok +-STATEMENT CREATE (t:test {prop: 662622}); +---- ok +-STATEMENT CREATE (t:test {prop: 775948}); +---- ok +-STATEMENT CREATE (t:test {prop: 925057}); +---- ok +-STATEMENT CREATE (t:test {prop: 753419}); +---- ok +-STATEMENT CREATE (t:test {prop: 572200}); +---- ok +-STATEMENT CREATE (t:test {prop: 748292}); +---- ok +-STATEMENT CREATE (t:test {prop: 284092}); +---- ok +-STATEMENT CREATE (t:test {prop: 998404}); +---- ok +-STATEMENT CREATE (t:test {prop: 779979}); +---- ok +-STATEMENT CREATE (t:test {prop: 38134}); +---- ok +-STATEMENT CREATE (t:test {prop: 646420}); +---- ok +-STATEMENT CREATE (t:test {prop: 886274}); +---- ok +-STATEMENT CREATE (t:test {prop: 703163}); +---- ok +-STATEMENT CREATE (t:test {prop: 468179}); +---- ok +-STATEMENT CREATE (t:test {prop: 283061}); +---- ok +-STATEMENT CREATE (t:test {prop: 474313}); +---- ok +-STATEMENT CREATE (t:test {prop: 11174}); +---- ok +-STATEMENT CREATE (t:test {prop: 725306}); +---- ok +-STATEMENT CREATE (t:test {prop: 262846}); +---- ok +-STATEMENT CREATE (t:test {prop: 343883}); +---- ok +-STATEMENT CREATE (t:test {prop: 991016}); +---- ok +-STATEMENT CREATE (t:test {prop: 587986}); +---- ok +-STATEMENT CREATE (t:test {prop: 614924}); +---- ok +-STATEMENT CREATE (t:test {prop: 701381}); +---- ok +-STATEMENT CREATE (t:test {prop: 302507}); +---- ok +-STATEMENT CREATE (t:test {prop: 76320}); +---- ok +-STATEMENT CREATE (t:test {prop: 840964}); +---- ok +-STATEMENT CREATE (t:test {prop: 945342}); +---- ok +-STATEMENT CREATE (t:test {prop: 508314}); +---- ok +-STATEMENT CREATE (t:test {prop: 284010}); +---- ok +-STATEMENT CREATE (t:test {prop: 848130}); +---- ok +-STATEMENT CREATE (t:test {prop: 473475}); +---- ok +-STATEMENT CREATE (t:test {prop: 289430}); +---- ok +-STATEMENT CREATE (t:test {prop: 853165}); +---- ok +-STATEMENT CREATE (t:test {prop: 303541}); +---- ok +-STATEMENT CREATE (t:test {prop: 862662}); +---- ok +-STATEMENT CREATE (t:test {prop: 428237}); +---- ok +-STATEMENT CREATE (t:test {prop: 729208}); +---- ok +-STATEMENT CREATE (t:test {prop: 893671}); +---- ok +-STATEMENT CREATE (t:test {prop: 519314}); +---- ok +-STATEMENT CREATE (t:test {prop: 456555}); +---- ok +-STATEMENT CREATE (t:test {prop: 485248}); +---- ok +-STATEMENT CREATE (t:test {prop: 963509}); +---- ok +-STATEMENT CREATE (t:test {prop: 842633}); +---- ok +-STATEMENT CREATE (t:test {prop: 571026}); +---- ok +-STATEMENT CREATE (t:test {prop: 962514}); +---- ok +-STATEMENT CREATE (t:test {prop: 176221}); +---- ok +-STATEMENT CREATE (t:test {prop: 358882}); +---- ok +-STATEMENT CREATE (t:test {prop: 746940}); +---- ok +-STATEMENT CREATE (t:test {prop: 376310}); +---- ok +-STATEMENT CREATE (t:test {prop: 528747}); +---- ok +-STATEMENT CREATE (t:test {prop: 773080}); +---- ok +-STATEMENT CREATE (t:test {prop: 174305}); +---- ok +-STATEMENT CREATE (t:test {prop: 158758}); +---- ok +-STATEMENT CREATE (t:test {prop: 646955}); +---- ok +-STATEMENT CREATE (t:test {prop: 961807}); +---- ok +-STATEMENT CREATE (t:test {prop: 214075}); +---- ok +-STATEMENT CREATE (t:test {prop: 379675}); +---- ok +-STATEMENT CREATE (t:test {prop: 573166}); +---- ok +-STATEMENT CREATE (t:test {prop: 722696}); +---- ok +-STATEMENT CREATE (t:test {prop: 589138}); +---- ok +-STATEMENT CREATE (t:test {prop: 102525}); +---- ok +-STATEMENT CREATE (t:test {prop: 657326}); +---- ok +-STATEMENT CREATE (t:test {prop: 30662}); +---- ok +-STATEMENT CREATE (t:test {prop: 591001}); +---- ok +-STATEMENT CREATE (t:test {prop: 923117}); +---- ok +-STATEMENT CREATE (t:test {prop: 272521}); +---- ok +-STATEMENT CREATE (t:test {prop: 962174}); +---- ok +-STATEMENT CREATE (t:test {prop: 451365}); +---- ok +-STATEMENT CREATE (t:test {prop: 336209}); +---- ok +-STATEMENT CREATE (t:test {prop: 989959}); +---- ok +-STATEMENT CREATE (t:test {prop: 379860}); +---- ok +-STATEMENT CREATE (t:test {prop: 412014}); +---- ok +-STATEMENT CREATE (t:test {prop: 678161}); +---- ok +-STATEMENT CREATE (t:test {prop: 146736}); +---- ok +-STATEMENT CREATE (t:test {prop: 543704}); +---- ok +-STATEMENT CREATE (t:test {prop: 307667}); +---- ok +-STATEMENT CREATE (t:test {prop: 449097}); +---- ok +-STATEMENT CREATE (t:test {prop: 521035}); +---- ok +-STATEMENT CREATE (t:test {prop: 836161}); +---- ok +-STATEMENT CREATE (t:test {prop: 308514}); +---- ok +-STATEMENT CREATE (t:test {prop: 929532}); +---- ok +-STATEMENT CREATE (t:test {prop: 684802}); +---- ok +-STATEMENT CREATE (t:test {prop: 892341}); +---- ok +-STATEMENT CREATE (t:test {prop: 945030}); +---- ok +-STATEMENT CREATE (t:test {prop: 300064}); +---- ok +-STATEMENT CREATE (t:test {prop: 476141}); +---- ok +-STATEMENT CREATE (t:test {prop: 132311}); +---- ok +-STATEMENT CREATE (t:test {prop: 741252}); +---- ok +-STATEMENT CREATE (t:test {prop: 956604}); +---- ok +-STATEMENT CREATE (t:test {prop: 954636}); +---- ok +-STATEMENT CREATE (t:test {prop: 259277}); +---- ok +-STATEMENT CREATE (t:test {prop: 513307}); +---- ok +-STATEMENT CREATE (t:test {prop: 949634}); +---- ok +-STATEMENT CREATE (t:test {prop: 29500}); +---- ok +-STATEMENT CREATE (t:test {prop: 70590}); +---- ok +-STATEMENT CREATE (t:test {prop: 513813}); +---- ok +-STATEMENT CREATE (t:test {prop: 306311}); +---- ok +-STATEMENT CREATE (t:test {prop: 312566}); +---- ok +-STATEMENT CREATE (t:test {prop: 224948}); +---- ok +-STATEMENT CREATE (t:test {prop: 542170}); +---- ok +-STATEMENT CREATE (t:test {prop: 570240}); +---- ok +-STATEMENT CREATE (t:test {prop: 548527}); +---- ok +-STATEMENT CREATE (t:test {prop: 741254}); +---- ok +-STATEMENT CREATE (t:test {prop: 266476}); +---- ok +-STATEMENT CREATE (t:test {prop: 190509}); +---- ok +-STATEMENT CREATE (t:test {prop: 858185}); +---- ok +-STATEMENT CREATE (t:test {prop: 342368}); +---- ok +-STATEMENT CREATE (t:test {prop: 566774}); +---- ok +-STATEMENT CREATE (t:test {prop: 849964}); +---- ok +-STATEMENT CREATE (t:test {prop: 231411}); +---- ok +-STATEMENT CREATE (t:test {prop: 913359}); +---- ok +-STATEMENT CREATE (t:test {prop: 416712}); +---- ok +-STATEMENT CREATE (t:test {prop: 756183}); +---- ok +-STATEMENT CREATE (t:test {prop: 556660}); +---- ok +-STATEMENT CREATE (t:test {prop: 728994}); +---- ok +-STATEMENT CREATE (t:test {prop: 474585}); +---- ok +-STATEMENT CREATE (t:test {prop: 203551}); +---- ok +-STATEMENT CREATE (t:test {prop: 326978}); +---- ok +-STATEMENT CREATE (t:test {prop: 853181}); +---- ok +-STATEMENT CREATE (t:test {prop: 157630}); +---- ok +-STATEMENT CREATE (t:test {prop: 308247}); +---- ok +-STATEMENT CREATE (t:test {prop: 301455}); +---- ok +-STATEMENT CREATE (t:test {prop: 363992}); +---- ok +-STATEMENT CREATE (t:test {prop: 661494}); +---- ok +-STATEMENT CREATE (t:test {prop: 148560}); +---- ok +-STATEMENT CREATE (t:test {prop: 824146}); +---- ok +-STATEMENT CREATE (t:test {prop: 194321}); +---- ok +-STATEMENT CREATE (t:test {prop: 470505}); +---- ok +-STATEMENT CREATE (t:test {prop: 875587}); +---- ok +-STATEMENT CREATE (t:test {prop: 399874}); +---- ok +-STATEMENT CREATE (t:test {prop: 343928}); +---- ok +-STATEMENT CREATE (t:test {prop: 581685}); +---- ok +-STATEMENT CREATE (t:test {prop: 506838}); +---- ok +-STATEMENT CREATE (t:test {prop: 576172}); +---- ok +-STATEMENT CREATE (t:test {prop: 803988}); +---- ok +-STATEMENT CREATE (t:test {prop: 586186}); +---- ok +-STATEMENT CREATE (t:test {prop: 982959}); +---- ok +-STATEMENT CREATE (t:test {prop: 536622}); +---- ok +-STATEMENT CREATE (t:test {prop: 603591}); +---- ok +-STATEMENT CREATE (t:test {prop: 451433}); +---- ok +-STATEMENT CREATE (t:test {prop: 356582}); +---- ok +-STATEMENT CREATE (t:test {prop: 645515}); +---- ok +-STATEMENT CREATE (t:test {prop: 417285}); +---- ok +-STATEMENT CREATE (t:test {prop: 303504}); +---- ok +-STATEMENT CREATE (t:test {prop: 352229}); +---- ok +-STATEMENT CREATE (t:test {prop: 379931}); +---- ok +-STATEMENT CREATE (t:test {prop: 689161}); +---- ok +-STATEMENT CREATE (t:test {prop: 828242}); +---- ok +-STATEMENT CREATE (t:test {prop: 747403}); +---- ok +-STATEMENT CREATE (t:test {prop: 875345}); +---- ok +-STATEMENT CREATE (t:test {prop: 921888}); +---- ok +-STATEMENT CREATE (t:test {prop: 345059}); +---- ok +-STATEMENT CREATE (t:test {prop: 698720}); +---- ok +-STATEMENT CREATE (t:test {prop: 223326}); +---- ok +-STATEMENT CREATE (t:test {prop: 266485}); +---- ok +-STATEMENT CREATE (t:test {prop: 541609}); +---- ok +-STATEMENT CREATE (t:test {prop: 578107}); +---- ok +-STATEMENT CREATE (t:test {prop: 365433}); +---- ok +-STATEMENT CREATE (t:test {prop: 348717}); +---- ok +-STATEMENT CREATE (t:test {prop: 310848}); +---- ok +-STATEMENT CREATE (t:test {prop: 312566}); +---- ok +-STATEMENT CREATE (t:test {prop: 121445}); +---- ok +-STATEMENT CREATE (t:test {prop: 405798}); +---- ok +-STATEMENT CREATE (t:test {prop: 486902}); +---- ok +-STATEMENT CREATE (t:test {prop: 350938}); +---- ok +-STATEMENT CREATE (t:test {prop: 412225}); +---- ok +-STATEMENT CREATE (t:test {prop: 723018}); +---- ok +-STATEMENT CREATE (t:test {prop: 350424}); +---- ok +-STATEMENT CREATE (t:test {prop: 768960}); +---- ok +-STATEMENT CREATE (t:test {prop: 743281}); +---- ok +-STATEMENT CREATE (t:test {prop: 678185}); +---- ok +-STATEMENT CREATE (t:test {prop: 282595}); +---- ok +-STATEMENT CREATE (t:test {prop: 88280}); +---- ok +-STATEMENT CREATE (t:test {prop: 357696}); +---- ok +-STATEMENT CREATE (t:test {prop: 367823}); +---- ok +-STATEMENT CREATE (t:test {prop: 737718}); +---- ok +-STATEMENT CREATE (t:test {prop: 103199}); +---- ok +-STATEMENT CREATE (t:test {prop: 117284}); +---- ok +-STATEMENT CREATE (t:test {prop: 115173}); +---- ok +-STATEMENT CREATE (t:test {prop: 384420}); +---- ok +-STATEMENT CREATE (t:test {prop: 100574}); +---- ok +-STATEMENT CREATE (t:test {prop: 64768}); +---- ok +-STATEMENT CREATE (t:test {prop: 477588}); +---- ok +-STATEMENT CREATE (t:test {prop: 298131}); +---- ok +-STATEMENT CREATE (t:test {prop: 558884}); +---- ok +-STATEMENT CREATE (t:test {prop: 835570}); +---- ok +-STATEMENT CREATE (t:test {prop: 943975}); +---- ok +-STATEMENT CREATE (t:test {prop: 922862}); +---- ok +-STATEMENT CREATE (t:test {prop: 345453}); +---- ok +-STATEMENT CREATE (t:test {prop: 218736}); +---- ok +-STATEMENT CREATE (t:test {prop: 260740}); +---- ok +-STATEMENT CREATE (t:test {prop: 394181}); +---- ok +-STATEMENT CREATE (t:test {prop: 508448}); +---- ok +-STATEMENT CREATE (t:test {prop: 305098}); +---- ok +-STATEMENT CREATE (t:test {prop: 310704}); +---- ok +-STATEMENT CREATE (t:test {prop: 380164}); +---- ok +-STATEMENT CREATE (t:test {prop: 432082}); +---- ok +-STATEMENT CREATE (t:test {prop: 221638}); +---- ok +-STATEMENT CREATE (t:test {prop: 331503}); +---- ok +-STATEMENT CREATE (t:test {prop: 643399}); +---- ok +-STATEMENT CREATE (t:test {prop: 787873}); +---- ok +-STATEMENT CREATE (t:test {prop: 263973}); +---- ok +-STATEMENT CREATE (t:test {prop: 388089}); +---- ok +-STATEMENT CREATE (t:test {prop: 28555}); +---- ok +-STATEMENT CREATE (t:test {prop: 611518}); +---- ok +-STATEMENT CREATE (t:test {prop: 485228}); +---- ok +-STATEMENT CREATE (t:test {prop: 525113}); +---- ok +-STATEMENT CREATE (t:test {prop: 57226}); +---- ok +-STATEMENT CREATE (t:test {prop: 172187}); +---- ok +-STATEMENT CREATE (t:test {prop: 765605}); +---- ok +-STATEMENT CREATE (t:test {prop: 370453}); +---- ok +-STATEMENT CREATE (t:test {prop: 155791}); +---- ok +-STATEMENT CREATE (t:test {prop: 715734}); +---- ok +-STATEMENT CREATE (t:test {prop: 957156}); +---- ok +-STATEMENT CREATE (t:test {prop: 553351}); +---- ok +-STATEMENT CREATE (t:test {prop: 708558}); +---- ok +-STATEMENT CREATE (t:test {prop: 387428}); +---- ok +-STATEMENT CREATE (t:test {prop: 659342}); +---- ok +-STATEMENT CREATE (t:test {prop: 498046}); +---- ok +-STATEMENT CREATE (t:test {prop: 641410}); +---- ok +-STATEMENT CREATE (t:test {prop: 898453}); +---- ok +-STATEMENT CREATE (t:test {prop: 681953}); +---- ok +-STATEMENT CREATE (t:test {prop: 51176}); +---- ok +-STATEMENT CREATE (t:test {prop: 150731}); +---- ok +-STATEMENT CREATE (t:test {prop: 397153}); +---- ok +-STATEMENT CREATE (t:test {prop: 615652}); +---- ok +-STATEMENT CREATE (t:test {prop: 251072}); +---- ok +-STATEMENT CREATE (t:test {prop: 817698}); +---- ok +-STATEMENT CREATE (t:test {prop: 89525}); +---- ok +-STATEMENT CREATE (t:test {prop: 520384}); +---- ok +-STATEMENT CREATE (t:test {prop: 367336}); +---- ok +-STATEMENT CREATE (t:test {prop: 600464}); +---- ok +-STATEMENT CREATE (t:test {prop: 599325}); +---- ok +-STATEMENT CREATE (t:test {prop: 230178}); +---- ok +-STATEMENT CREATE (t:test {prop: 629366}); +---- ok +-STATEMENT CREATE (t:test {prop: 32161}); +---- ok +-STATEMENT CREATE (t:test {prop: 620246}); +---- ok +-STATEMENT CREATE (t:test {prop: 644967}); +---- ok +-STATEMENT CREATE (t:test {prop: 860617}); +---- ok +-STATEMENT CREATE (t:test {prop: 103555}); +---- ok +-STATEMENT CREATE (t:test {prop: 193629}); +---- ok +-STATEMENT CREATE (t:test {prop: 42151}); +---- ok +-STATEMENT CREATE (t:test {prop: 73656}); +---- ok +-STATEMENT CREATE (t:test {prop: 378908}); +---- ok +-STATEMENT CREATE (t:test {prop: 413609}); +---- ok +-STATEMENT CREATE (t:test {prop: 454032}); +---- ok +-STATEMENT CREATE (t:test {prop: 10236}); +---- ok +-STATEMENT CREATE (t:test {prop: 492533}); +---- ok +-STATEMENT CREATE (t:test {prop: 297386}); +---- ok +-STATEMENT CREATE (t:test {prop: 968685}); +---- ok +-STATEMENT CREATE (t:test {prop: 543078}); +---- ok +-STATEMENT CREATE (t:test {prop: 638815}); +---- ok +-STATEMENT CREATE (t:test {prop: 287177}); +---- ok +-STATEMENT CREATE (t:test {prop: 948330}); +---- ok +-STATEMENT CREATE (t:test {prop: 134949}); +---- ok +-STATEMENT CREATE (t:test {prop: 459398}); +---- ok +-STATEMENT CREATE (t:test {prop: 232823}); +---- ok +-STATEMENT CREATE (t:test {prop: 6642}); +---- ok +-STATEMENT CREATE (t:test {prop: 356219}); +---- ok +-STATEMENT CREATE (t:test {prop: 171887}); +---- ok +-STATEMENT CREATE (t:test {prop: 359319}); +---- ok +-STATEMENT CREATE (t:test {prop: 954044}); +---- ok +-STATEMENT CREATE (t:test {prop: 892703}); +---- ok +-STATEMENT CREATE (t:test {prop: 724657}); +---- ok +-STATEMENT CREATE (t:test {prop: 196372}); +---- ok +-STATEMENT CREATE (t:test {prop: 620182}); +---- ok +-STATEMENT CREATE (t:test {prop: 422542}); +---- ok +-STATEMENT CREATE (t:test {prop: 11353}); +---- ok +-STATEMENT CREATE (t:test {prop: 831919}); +---- ok +-STATEMENT CREATE (t:test {prop: 157585}); +---- ok +-STATEMENT CREATE (t:test {prop: 52910}); +---- ok +-STATEMENT CREATE (t:test {prop: 835654}); +---- ok +-STATEMENT CREATE (t:test {prop: 538751}); +---- ok +-STATEMENT CREATE (t:test {prop: 887721}); +---- ok +-STATEMENT CREATE (t:test {prop: 181477}); +---- ok +-STATEMENT CREATE (t:test {prop: 385406}); +---- ok +-STATEMENT CREATE (t:test {prop: 769830}); +---- ok +-STATEMENT CREATE (t:test {prop: 702868}); +---- ok +-STATEMENT CREATE (t:test {prop: 697047}); +---- ok +-STATEMENT CREATE (t:test {prop: 831291}); +---- ok +-STATEMENT CREATE (t:test {prop: 196157}); +---- ok +-STATEMENT CREATE (t:test {prop: 47731}); +---- ok +-STATEMENT CREATE (t:test {prop: 154206}); +---- ok +-STATEMENT CREATE (t:test {prop: 387123}); +---- ok +-STATEMENT CREATE (t:test {prop: 265641}); +---- ok +-STATEMENT CREATE (t:test {prop: 204326}); +---- ok +-STATEMENT CREATE (t:test {prop: 309472}); +---- ok +-STATEMENT CREATE (t:test {prop: 84870}); +---- ok +-STATEMENT CREATE (t:test {prop: 726596}); +---- ok +-STATEMENT CREATE (t:test {prop: 206087}); +---- ok +-STATEMENT CREATE (t:test {prop: 467010}); +---- ok +-STATEMENT CREATE (t:test {prop: 669832}); +---- ok +-STATEMENT CREATE (t:test {prop: 758562}); +---- ok +-STATEMENT CREATE (t:test {prop: 850788}); +---- ok +-STATEMENT CREATE (t:test {prop: 530936}); +---- ok +-STATEMENT CREATE (t:test {prop: 484182}); +---- ok +-STATEMENT CREATE (t:test {prop: 896005}); +---- ok +-STATEMENT CREATE (t:test {prop: 323242}); +---- ok +-STATEMENT CREATE (t:test {prop: 286301}); +---- ok +-STATEMENT CREATE (t:test {prop: 26441}); +---- ok +-STATEMENT CREATE (t:test {prop: 867233}); +---- ok +-STATEMENT CREATE (t:test {prop: 685796}); +---- ok +-STATEMENT CREATE (t:test {prop: 403711}); +---- ok +-STATEMENT CREATE (t:test {prop: 836301}); +---- ok +-STATEMENT CREATE (t:test {prop: 865967}); +---- ok +-STATEMENT CREATE (t:test {prop: 821380}); +---- ok +-STATEMENT CREATE (t:test {prop: 939237}); +---- ok +-STATEMENT CREATE (t:test {prop: 14823}); +---- ok +-STATEMENT CREATE (t:test {prop: 278590}); +---- ok +-STATEMENT CREATE (t:test {prop: 977605}); +---- ok +-STATEMENT CREATE (t:test {prop: 231242}); +---- ok +-STATEMENT CREATE (t:test {prop: 127523}); +---- ok +-STATEMENT CREATE (t:test {prop: 292150}); +---- ok +-STATEMENT CREATE (t:test {prop: 870073}); +---- ok +-STATEMENT CREATE (t:test {prop: 392474}); +---- ok +-STATEMENT CREATE (t:test {prop: 889886}); +---- ok +-STATEMENT CREATE (t:test {prop: 409633}); +---- ok +-STATEMENT CREATE (t:test {prop: 224909}); +---- ok +-STATEMENT CREATE (t:test {prop: 377857}); +---- ok +-STATEMENT CREATE (t:test {prop: 799991}); +---- ok +-STATEMENT CREATE (t:test {prop: 111133}); +---- ok +-STATEMENT CREATE (t:test {prop: 422018}); +---- ok +-STATEMENT CREATE (t:test {prop: 818126}); +---- ok +-STATEMENT CREATE (t:test {prop: 644400}); +---- ok +-STATEMENT CREATE (t:test {prop: 536400}); +---- ok +-STATEMENT CREATE (t:test {prop: 819827}); +---- ok +-STATEMENT CREATE (t:test {prop: 662610}); +---- ok +-STATEMENT CREATE (t:test {prop: 870837}); +---- ok +-STATEMENT CREATE (t:test {prop: 823980}); +---- ok +-STATEMENT CREATE (t:test {prop: 285121}); +---- ok +-STATEMENT CREATE (t:test {prop: 169207}); +---- ok +-STATEMENT CREATE (t:test {prop: 772395}); +---- ok +-STATEMENT CREATE (t:test {prop: 635773}); +---- ok +-STATEMENT CREATE (t:test {prop: 973367}); +---- ok +-STATEMENT CREATE (t:test {prop: 425597}); +---- ok +-STATEMENT CREATE (t:test {prop: 765628}); +---- ok +-STATEMENT CREATE (t:test {prop: 57325}); +---- ok +-STATEMENT CREATE (t:test {prop: 216929}); +---- ok +-STATEMENT CREATE (t:test {prop: 242735}); +---- ok +-STATEMENT CREATE (t:test {prop: 451684}); +---- ok +-STATEMENT CREATE (t:test {prop: 74601}); +---- ok +-STATEMENT CREATE (t:test {prop: 651151}); +---- ok +-STATEMENT CREATE (t:test {prop: 968596}); +---- ok +-STATEMENT CREATE (t:test {prop: 650772}); +---- ok +-STATEMENT CREATE (t:test {prop: 301858}); +---- ok +-STATEMENT CREATE (t:test {prop: 181154}); +---- ok +-STATEMENT CREATE (t:test {prop: 63907}); +---- ok +-STATEMENT CREATE (t:test {prop: 260751}); +---- ok +-STATEMENT CREATE (t:test {prop: 356549}); +---- ok +-STATEMENT CREATE (t:test {prop: 717116}); +---- ok +-STATEMENT CREATE (t:test {prop: 405259}); +---- ok +-STATEMENT CREATE (t:test {prop: 404496}); +---- ok +-STATEMENT CREATE (t:test {prop: 12759}); +---- ok +-STATEMENT CREATE (t:test {prop: 86996}); +---- ok +-STATEMENT CREATE (t:test {prop: 424315}); +---- ok +-STATEMENT CREATE (t:test {prop: 568740}); +---- ok +-STATEMENT CREATE (t:test {prop: 884122}); +---- ok +-STATEMENT CREATE (t:test {prop: 268028}); +---- ok +-STATEMENT CREATE (t:test {prop: 206667}); +---- ok +-STATEMENT CREATE (t:test {prop: 403444}); +---- ok +-STATEMENT CREATE (t:test {prop: 46398}); +---- ok +-STATEMENT CREATE (t:test {prop: 409583}); +---- ok +-STATEMENT CREATE (t:test {prop: 417403}); +---- ok +-STATEMENT CREATE (t:test {prop: 505947}); +---- ok +-STATEMENT CREATE (t:test {prop: 793153}); +---- ok +-STATEMENT CREATE (t:test {prop: 714513}); +---- ok +-STATEMENT CREATE (t:test {prop: 622318}); +---- ok +-STATEMENT CREATE (t:test {prop: 940265}); +---- ok +-STATEMENT CREATE (t:test {prop: 196174}); +---- ok +-STATEMENT CREATE (t:test {prop: 782011}); +---- ok +-STATEMENT CREATE (t:test {prop: 771053}); +---- ok +-STATEMENT CREATE (t:test {prop: 693989}); +---- ok +-STATEMENT CREATE (t:test {prop: 547254}); +---- ok +-STATEMENT CREATE (t:test {prop: 959354}); +---- ok +-STATEMENT CREATE (t:test {prop: 580128}); +---- ok +-STATEMENT CREATE (t:test {prop: 704262}); +---- ok +-STATEMENT CREATE (t:test {prop: 722814}); +---- ok +-STATEMENT CREATE (t:test {prop: 177543}); +---- ok +-STATEMENT CREATE (t:test {prop: 215792}); +---- ok +-STATEMENT CREATE (t:test {prop: 107537}); +---- ok +-STATEMENT CREATE (t:test {prop: 747254}); +---- ok +-STATEMENT CREATE (t:test {prop: 187216}); +---- ok +-STATEMENT CREATE (t:test {prop: 194321}); +---- ok +-STATEMENT CREATE (t:test {prop: 731132}); +---- ok +-STATEMENT CREATE (t:test {prop: 847982}); +---- ok +-STATEMENT CREATE (t:test {prop: 718839}); +---- ok +-STATEMENT CREATE (t:test {prop: 159673}); +---- ok +-STATEMENT CREATE (t:test {prop: 164326}); +---- ok +-STATEMENT CREATE (t:test {prop: 48429}); +---- ok +-STATEMENT CREATE (t:test {prop: 908174}); +---- ok +-STATEMENT CREATE (t:test {prop: 272339}); +---- ok +-STATEMENT CREATE (t:test {prop: 129262}); +---- ok +-STATEMENT CREATE (t:test {prop: 607124}); +---- ok +-STATEMENT CREATE (t:test {prop: 67138}); +---- ok +-STATEMENT CREATE (t:test {prop: 350587}); +---- ok +-STATEMENT CREATE (t:test {prop: 975261}); +---- ok +-STATEMENT CREATE (t:test {prop: 796578}); +---- ok +-STATEMENT CREATE (t:test {prop: 603018}); +---- ok +-STATEMENT CREATE (t:test {prop: 277142}); +---- ok +-STATEMENT CREATE (t:test {prop: 561105}); +---- ok +-STATEMENT CREATE (t:test {prop: 280978}); +---- ok +-STATEMENT CREATE (t:test {prop: 53760}); +---- ok +-STATEMENT CREATE (t:test {prop: 772516}); +---- ok +-STATEMENT CREATE (t:test {prop: 933437}); +---- ok +-STATEMENT CREATE (t:test {prop: 322131}); +---- ok +-STATEMENT CREATE (t:test {prop: 327275}); +---- ok +-STATEMENT CREATE (t:test {prop: 277566}); +---- ok +-STATEMENT CREATE (t:test {prop: 364347}); +---- ok +-STATEMENT CREATE (t:test {prop: 599628}); +---- ok +-STATEMENT CREATE (t:test {prop: 114711}); +---- ok +-STATEMENT CREATE (t:test {prop: 747585}); +---- ok +-STATEMENT CREATE (t:test {prop: 889810}); +---- ok +-STATEMENT CREATE (t:test {prop: 775602}); +---- ok +-STATEMENT CREATE (t:test {prop: 519929}); +---- ok +-STATEMENT CREATE (t:test {prop: 326997}); +---- ok +-STATEMENT CREATE (t:test {prop: 206498}); +---- ok +-STATEMENT CREATE (t:test {prop: 8472}); +---- ok +-STATEMENT CREATE (t:test {prop: 714319}); +---- ok +-STATEMENT CREATE (t:test {prop: 964183}); +---- ok +-STATEMENT CREATE (t:test {prop: 963884}); +---- ok +-STATEMENT CREATE (t:test {prop: 749039}); +---- ok +-STATEMENT CREATE (t:test {prop: 275498}); +---- ok +-STATEMENT CREATE (t:test {prop: 544525}); +---- ok +-STATEMENT CREATE (t:test {prop: 511809}); +---- ok +-STATEMENT CREATE (t:test {prop: 181348}); +---- ok +-STATEMENT CREATE (t:test {prop: 561588}); +---- ok +-STATEMENT CREATE (t:test {prop: 564330}); +---- ok +-STATEMENT CREATE (t:test {prop: 127348}); +---- ok +-STATEMENT CREATE (t:test {prop: 956187}); +---- ok +-STATEMENT CREATE (t:test {prop: 141339}); +---- ok +-STATEMENT CREATE (t:test {prop: 878710}); +---- ok +-STATEMENT CREATE (t:test {prop: 753651}); +---- ok +-STATEMENT CREATE (t:test {prop: 750141}); +---- ok +-STATEMENT CREATE (t:test {prop: 632212}); +---- ok +-STATEMENT CREATE (t:test {prop: 949122}); +---- ok +-STATEMENT CREATE (t:test {prop: 284502}); +---- ok +-STATEMENT CREATE (t:test {prop: 827355}); +---- ok +-STATEMENT CREATE (t:test {prop: 756932}); +---- ok +-STATEMENT CREATE (t:test {prop: 995279}); +---- ok +-STATEMENT CREATE (t:test {prop: 955097}); +---- ok +-STATEMENT CREATE (t:test {prop: 119512}); +---- ok +-STATEMENT CREATE (t:test {prop: 743093}); +---- ok +-STATEMENT CREATE (t:test {prop: 501883}); +---- ok +-STATEMENT CREATE (t:test {prop: 544783}); +---- ok +-STATEMENT CREATE (t:test {prop: 157102}); +---- ok +-STATEMENT CREATE (t:test {prop: 205141}); +---- ok +-STATEMENT CREATE (t:test {prop: 350629}); +---- ok +-STATEMENT CREATE (t:test {prop: 871494}); +---- ok +-STATEMENT CREATE (t:test {prop: 704878}); +---- ok +-STATEMENT CREATE (t:test {prop: 538294}); +---- ok +-STATEMENT CREATE (t:test {prop: 545365}); +---- ok +-STATEMENT CREATE (t:test {prop: 62945}); +---- ok +-STATEMENT CREATE (t:test {prop: 649265}); +---- ok +-STATEMENT CREATE (t:test {prop: 602276}); +---- ok +-STATEMENT CREATE (t:test {prop: 585257}); +---- ok +-STATEMENT CREATE (t:test {prop: 335192}); +---- ok +-STATEMENT CREATE (t:test {prop: 680668}); +---- ok +-STATEMENT CREATE (t:test {prop: 516655}); +---- ok +-STATEMENT CREATE (t:test {prop: 212422}); +---- ok +-STATEMENT CREATE (t:test {prop: 469331}); +---- ok +-STATEMENT CREATE (t:test {prop: 247754}); +---- ok +-STATEMENT CREATE (t:test {prop: 279086}); +---- ok +-STATEMENT CREATE (t:test {prop: 207740}); +---- ok +-STATEMENT CREATE (t:test {prop: 107635}); +---- ok +-STATEMENT CREATE (t:test {prop: 251936}); +---- ok +-STATEMENT CREATE (t:test {prop: 40040}); +---- ok +-STATEMENT CREATE (t:test {prop: 796401}); +---- ok +-STATEMENT CREATE (t:test {prop: 232297}); +---- ok +-STATEMENT CREATE (t:test {prop: 306246}); +---- ok +-STATEMENT CREATE (t:test {prop: 124257}); +---- ok +-STATEMENT CREATE (t:test {prop: 876172}); +---- ok +-STATEMENT CREATE (t:test {prop: 618089}); +---- ok +-STATEMENT CREATE (t:test {prop: 188458}); +---- ok +-STATEMENT CREATE (t:test {prop: 72438}); +---- ok +-STATEMENT CREATE (t:test {prop: 384539}); +---- ok +-STATEMENT CREATE (t:test {prop: 546223}); +---- ok +-STATEMENT CREATE (t:test {prop: 999704}); +---- ok +-STATEMENT CREATE (t:test {prop: 708310}); +---- ok +-STATEMENT CREATE (t:test {prop: 208253}); +---- ok +-STATEMENT CREATE (t:test {prop: 854493}); +---- ok +-STATEMENT CREATE (t:test {prop: 48774}); +---- ok +-STATEMENT CREATE (t:test {prop: 60097}); +---- ok +-STATEMENT CREATE (t:test {prop: 674970}); +---- ok +-STATEMENT CREATE (t:test {prop: 384359}); +---- ok +-STATEMENT CREATE (t:test {prop: 219074}); +---- ok +-STATEMENT CREATE (t:test {prop: 2965}); +---- ok +-STATEMENT CREATE (t:test {prop: 602997}); +---- ok +-STATEMENT CREATE (t:test {prop: 989902}); +---- ok +-STATEMENT CREATE (t:test {prop: 242969}); +---- ok +-STATEMENT CREATE (t:test {prop: 498814}); +---- ok +-STATEMENT CREATE (t:test {prop: 481103}); +---- ok +-STATEMENT CREATE (t:test {prop: 233274}); +---- ok +-STATEMENT CREATE (t:test {prop: 869941}); +---- ok +-STATEMENT CREATE (t:test {prop: 372548}); +---- ok +-STATEMENT CREATE (t:test {prop: 497907}); +---- ok +-STATEMENT CREATE (t:test {prop: 507022}); +---- ok +-STATEMENT CREATE (t:test {prop: 482093}); +---- ok +-STATEMENT CREATE (t:test {prop: 561512}); +---- ok +-STATEMENT CREATE (t:test {prop: 472903}); +---- ok +-STATEMENT CREATE (t:test {prop: 384071}); +---- ok +-STATEMENT CREATE (t:test {prop: 444828}); +---- ok +-STATEMENT CREATE (t:test {prop: 764509}); +---- ok +-STATEMENT CREATE (t:test {prop: 310018}); +---- ok +-STATEMENT CREATE (t:test {prop: 289896}); +---- ok +-STATEMENT CREATE (t:test {prop: 191089}); +---- ok +-STATEMENT CREATE (t:test {prop: 42105}); +---- ok +-STATEMENT CREATE (t:test {prop: 139445}); +---- ok +-STATEMENT CREATE (t:test {prop: 585265}); +---- ok +-STATEMENT CREATE (t:test {prop: 614803}); +---- ok +-STATEMENT CREATE (t:test {prop: 338358}); +---- ok +-STATEMENT CREATE (t:test {prop: 683773}); +---- ok +-STATEMENT CREATE (t:test {prop: 129187}); +---- ok +-STATEMENT CREATE (t:test {prop: 484425}); +---- ok +-STATEMENT CREATE (t:test {prop: 311587}); +---- ok +-STATEMENT CREATE (t:test {prop: 210587}); +---- ok +-STATEMENT CREATE (t:test {prop: 908545}); +---- ok +-STATEMENT CREATE (t:test {prop: 491018}); +---- ok +-STATEMENT CREATE (t:test {prop: 268309}); +---- ok +-STATEMENT CREATE (t:test {prop: 547072}); +---- ok +-STATEMENT CREATE (t:test {prop: 239537}); +---- ok +-STATEMENT CREATE (t:test {prop: 13844}); +---- ok +-STATEMENT CREATE (t:test {prop: 765950}); +---- ok +-STATEMENT CREATE (t:test {prop: 403516}); +---- ok +-STATEMENT CREATE (t:test {prop: 284472}); +---- ok +-STATEMENT CREATE (t:test {prop: 591300}); +---- ok +-STATEMENT CREATE (t:test {prop: 537681}); +---- ok +-STATEMENT CREATE (t:test {prop: 117775}); +---- ok +-STATEMENT CREATE (t:test {prop: 166273}); +---- ok +-STATEMENT CREATE (t:test {prop: 827138}); +---- ok +-STATEMENT CREATE (t:test {prop: 655357}); +---- ok +-STATEMENT CREATE (t:test {prop: 813128}); +---- ok +-STATEMENT CREATE (t:test {prop: 174246}); +---- ok +-STATEMENT CREATE (t:test {prop: 778298}); +---- ok +-STATEMENT CREATE (t:test {prop: 146310}); +---- ok +-STATEMENT CREATE (t:test {prop: 674484}); +---- ok +-STATEMENT CREATE (t:test {prop: 257519}); +---- ok +-STATEMENT CREATE (t:test {prop: 77957}); +---- ok +-STATEMENT CREATE (t:test {prop: 958686}); +---- ok +-STATEMENT CREATE (t:test {prop: 97090}); +---- ok +-STATEMENT CREATE (t:test {prop: 555578}); +---- ok +-STATEMENT CREATE (t:test {prop: 17380}); +---- ok +-STATEMENT CREATE (t:test {prop: 487374}); +---- ok +-STATEMENT CREATE (t:test {prop: 305544}); +---- ok +-STATEMENT CREATE (t:test {prop: 64848}); +---- ok +-STATEMENT CREATE (t:test {prop: 630964}); +---- ok +-STATEMENT CREATE (t:test {prop: 73988}); +---- ok +-STATEMENT CREATE (t:test {prop: 126130}); +---- ok +-STATEMENT CREATE (t:test {prop: 780297}); +---- ok +-STATEMENT CREATE (t:test {prop: 605832}); +---- ok +-STATEMENT CREATE (t:test {prop: 817243}); +---- ok +-STATEMENT CREATE (t:test {prop: 962050}); +---- ok +-STATEMENT CREATE (t:test {prop: 327050}); +---- ok +-STATEMENT CREATE (t:test {prop: 608289}); +---- ok +-STATEMENT CREATE (t:test {prop: 540509}); +---- ok +-STATEMENT CREATE (t:test {prop: 676857}); +---- ok +-STATEMENT CREATE (t:test {prop: 107981}); +---- ok +-STATEMENT CREATE (t:test {prop: 623976}); +---- ok +-STATEMENT CREATE (t:test {prop: 878274}); +---- ok +-STATEMENT CREATE (t:test {prop: 948844}); +---- ok +-STATEMENT CREATE (t:test {prop: 659363}); +---- ok +-STATEMENT CREATE (t:test {prop: 387137}); +---- ok +-STATEMENT CREATE (t:test {prop: 347714}); +---- ok +-STATEMENT CREATE (t:test {prop: 956670}); +---- ok +-STATEMENT CREATE (t:test {prop: 918065}); +---- ok +-STATEMENT CREATE (t:test {prop: 603064}); +---- ok +-STATEMENT CREATE (t:test {prop: 367473}); +---- ok +-STATEMENT CREATE (t:test {prop: 808753}); +---- ok +-STATEMENT CREATE (t:test {prop: 784201}); +---- ok +-STATEMENT CREATE (t:test {prop: 815348}); +---- ok +-STATEMENT CREATE (t:test {prop: 800926}); +---- ok +-STATEMENT CREATE (t:test {prop: 406498}); +---- ok +-STATEMENT CREATE (t:test {prop: 145637}); +---- ok +-STATEMENT CREATE (t:test {prop: 796315}); +---- ok +-STATEMENT CREATE (t:test {prop: 792439}); +---- ok +-STATEMENT CREATE (t:test {prop: 326481}); +---- ok +-STATEMENT CREATE (t:test {prop: 838911}); +---- ok +-STATEMENT CREATE (t:test {prop: 514930}); +---- ok +-STATEMENT CREATE (t:test {prop: 435059}); +---- ok +-STATEMENT CREATE (t:test {prop: 957312}); +---- ok +-STATEMENT CREATE (t:test {prop: 948174}); +---- ok +-STATEMENT CREATE (t:test {prop: 192945}); +---- ok +-STATEMENT CREATE (t:test {prop: 104801}); +---- ok +-STATEMENT CREATE (t:test {prop: 603838}); +---- ok +-STATEMENT CREATE (t:test {prop: 320979}); +---- ok +-STATEMENT CREATE (t:test {prop: 56048}); +---- ok +-STATEMENT CREATE (t:test {prop: 748373}); +---- ok +-STATEMENT CREATE (t:test {prop: 78108}); +---- ok +-STATEMENT CREATE (t:test {prop: 680549}); +---- ok +-STATEMENT CREATE (t:test {prop: 661125}); +---- ok +-STATEMENT CREATE (t:test {prop: 891378}); +---- ok +-STATEMENT CREATE (t:test {prop: 187888}); +---- ok +-STATEMENT CREATE (t:test {prop: 708898}); +---- ok +-STATEMENT CREATE (t:test {prop: 733951}); +---- ok +-STATEMENT CREATE (t:test {prop: 436630}); +---- ok +-STATEMENT CREATE (t:test {prop: 456681}); +---- ok +-STATEMENT CREATE (t:test {prop: 103690}); +---- ok +-STATEMENT CREATE (t:test {prop: 244424}); +---- ok +-STATEMENT CREATE (t:test {prop: 267421}); +---- ok +-STATEMENT CREATE (t:test {prop: 546391}); +---- ok +-STATEMENT CREATE (t:test {prop: 793174}); +---- ok +-STATEMENT CREATE (t:test {prop: 685069}); +---- ok +-STATEMENT CREATE (t:test {prop: 891587}); +---- ok +-STATEMENT CREATE (t:test {prop: 60319}); +---- ok +-STATEMENT CREATE (t:test {prop: 318651}); +---- ok +-STATEMENT CREATE (t:test {prop: 738866}); +---- ok +-STATEMENT CREATE (t:test {prop: 649095}); +---- ok +-STATEMENT CREATE (t:test {prop: 502887}); +---- ok +-STATEMENT CREATE (t:test {prop: 581282}); +---- ok +-STATEMENT CREATE (t:test {prop: 495893}); +---- ok +-STATEMENT CREATE (t:test {prop: 156186}); +---- ok +-STATEMENT CREATE (t:test {prop: 793786}); +---- ok +-STATEMENT CREATE (t:test {prop: 412269}); +---- ok +-STATEMENT CREATE (t:test {prop: 96642}); +---- ok +-STATEMENT CREATE (t:test {prop: 860316}); +---- ok +-STATEMENT CREATE (t:test {prop: 720099}); +---- ok +-STATEMENT CREATE (t:test {prop: 360057}); +---- ok +-STATEMENT CREATE (t:test {prop: 756438}); +---- ok +-STATEMENT CREATE (t:test {prop: 322367}); +---- ok +-STATEMENT CREATE (t:test {prop: 884767}); +---- ok +-STATEMENT CREATE (t:test {prop: 268804}); +---- ok +-STATEMENT CREATE (t:test {prop: 31114}); +---- ok +-STATEMENT CREATE (t:test {prop: 782357}); +---- ok +-STATEMENT CREATE (t:test {prop: 530787}); +---- ok +-STATEMENT CREATE (t:test {prop: 375721}); +---- ok +-STATEMENT CREATE (t:test {prop: 388548}); +---- ok +-STATEMENT CREATE (t:test {prop: 489761}); +---- ok +-STATEMENT CREATE (t:test {prop: 132049}); +---- ok +-STATEMENT CREATE (t:test {prop: 873237}); +---- ok +-STATEMENT CREATE (t:test {prop: 990077}); +---- ok +-STATEMENT CREATE (t:test {prop: 528371}); +---- ok +-STATEMENT CREATE (t:test {prop: 583403}); +---- ok +-STATEMENT CREATE (t:test {prop: 721847}); +---- ok +-STATEMENT CREATE (t:test {prop: 152443}); +---- ok +-STATEMENT CREATE (t:test {prop: 753010}); +---- ok +-STATEMENT CREATE (t:test {prop: 602655}); +---- ok +-STATEMENT CREATE (t:test {prop: 469340}); +---- ok +-STATEMENT CREATE (t:test {prop: 321573}); +---- ok +-STATEMENT CREATE (t:test {prop: 882709}); +---- ok +-STATEMENT CREATE (t:test {prop: 232411}); +---- ok +-STATEMENT CREATE (t:test {prop: 392621}); +---- ok +-STATEMENT CREATE (t:test {prop: 497764}); +---- ok +-STATEMENT CREATE (t:test {prop: 518643}); +---- ok +-STATEMENT CREATE (t:test {prop: 505417}); +---- ok +-STATEMENT CREATE (t:test {prop: 20881}); +---- ok +-STATEMENT CREATE (t:test {prop: 362025}); +---- ok +-STATEMENT CREATE (t:test {prop: 221341}); +---- ok +-STATEMENT CREATE (t:test {prop: 534760}); +---- ok +-STATEMENT CREATE (t:test {prop: 428901}); +---- ok +-STATEMENT CREATE (t:test {prop: 233527}); +---- ok +-STATEMENT CREATE (t:test {prop: 489526}); +---- ok +-STATEMENT CREATE (t:test {prop: 222944}); +---- ok +-STATEMENT CREATE (t:test {prop: 110148}); +---- ok +-STATEMENT CREATE (t:test {prop: 867918}); +---- ok +-STATEMENT CREATE (t:test {prop: 603744}); +---- ok +-STATEMENT CREATE (t:test {prop: 498445}); +---- ok +-STATEMENT CREATE (t:test {prop: 369710}); +---- ok +-STATEMENT CREATE (t:test {prop: 634144}); +---- ok +-STATEMENT CREATE (t:test {prop: 478036}); +---- ok +-STATEMENT CREATE (t:test {prop: 548956}); +---- ok +-STATEMENT CREATE (t:test {prop: 757436}); +---- ok +-STATEMENT CREATE (t:test {prop: 581443}); +---- ok +-STATEMENT CREATE (t:test {prop: 53080}); +---- ok +-STATEMENT CREATE (t:test {prop: 766725}); +---- ok +-STATEMENT CREATE (t:test {prop: 271789}); +---- ok +-STATEMENT CREATE (t:test {prop: 251402}); +---- ok +-STATEMENT CREATE (t:test {prop: 801172}); +---- ok +-STATEMENT CREATE (t:test {prop: 430799}); +---- ok +-STATEMENT CREATE (t:test {prop: 380590}); +---- ok +-STATEMENT CREATE (t:test {prop: 512639}); +---- ok +-STATEMENT CREATE (t:test {prop: 676107}); +---- ok +-STATEMENT CREATE (t:test {prop: 780808}); +---- ok +-STATEMENT CREATE (t:test {prop: 36736}); +---- ok +-STATEMENT CREATE (t:test {prop: 858600}); +---- ok +-STATEMENT CREATE (t:test {prop: 227156}); +---- ok +-STATEMENT CREATE (t:test {prop: 72701}); +---- ok +-STATEMENT CREATE (t:test {prop: 208848}); +---- ok +-STATEMENT CREATE (t:test {prop: 208584}); +---- ok +-STATEMENT CREATE (t:test {prop: 230883}); +---- ok +-STATEMENT CREATE (t:test {prop: 796672}); +---- ok +-STATEMENT CREATE (t:test {prop: 410321}); +---- ok +-STATEMENT CREATE (t:test {prop: 618456}); +---- ok +-STATEMENT CREATE (t:test {prop: 890437}); +---- ok +-STATEMENT CREATE (t:test {prop: 957376}); +---- ok +-STATEMENT CREATE (t:test {prop: 18771}); +---- ok +-STATEMENT CREATE (t:test {prop: 640451}); +---- ok +-STATEMENT CREATE (t:test {prop: 695541}); +---- ok +-STATEMENT CREATE (t:test {prop: 395068}); +---- ok +-STATEMENT CREATE (t:test {prop: 660107}); +---- ok +-STATEMENT CREATE (t:test {prop: 666702}); +---- ok +-STATEMENT CREATE (t:test {prop: 869572}); +---- ok +-STATEMENT CREATE (t:test {prop: 738738}); +---- ok +-STATEMENT CREATE (t:test {prop: 208576}); +---- ok +-STATEMENT CREATE (t:test {prop: 995833}); +---- ok +-STATEMENT CREATE (t:test {prop: 694286}); +---- ok +-STATEMENT CREATE (t:test {prop: 743792}); +---- ok +-STATEMENT CREATE (t:test {prop: 956279}); +---- ok +-STATEMENT CREATE (t:test {prop: 854720}); +---- ok +-STATEMENT CREATE (t:test {prop: 182979}); +---- ok +-STATEMENT CREATE (t:test {prop: 432665}); +---- ok +-STATEMENT CREATE (t:test {prop: 872722}); +---- ok +-STATEMENT CREATE (t:test {prop: 997969}); +---- ok +-STATEMENT CREATE (t:test {prop: 476798}); +---- ok +-STATEMENT CREATE (t:test {prop: 823540}); +---- ok +-STATEMENT CREATE (t:test {prop: 971429}); +---- ok +-STATEMENT CREATE (t:test {prop: 929199}); +---- ok +-STATEMENT CREATE (t:test {prop: 159349}); +---- ok +-STATEMENT CREATE (t:test {prop: 289668}); +---- ok +-STATEMENT CREATE (t:test {prop: 642159}); +---- ok +-STATEMENT CREATE (t:test {prop: 399146}); +---- ok +-STATEMENT CREATE (t:test {prop: 877069}); +---- ok +-STATEMENT CREATE (t:test {prop: 905090}); +---- ok +-STATEMENT CREATE (t:test {prop: 487838}); +---- ok +-STATEMENT CREATE (t:test {prop: 979815}); +---- ok +-STATEMENT CREATE (t:test {prop: 412748}); +---- ok +-STATEMENT CREATE (t:test {prop: 531841}); +---- ok +-STATEMENT CREATE (t:test {prop: 690759}); +---- ok +-STATEMENT CREATE (t:test {prop: 564252}); +---- ok +-STATEMENT CREATE (t:test {prop: 445040}); +---- ok +-STATEMENT CREATE (t:test {prop: 750877}); +---- ok +-STATEMENT CREATE (t:test {prop: 205272}); +---- ok +-STATEMENT CREATE (t:test {prop: 660067}); +---- ok +-STATEMENT CREATE (t:test {prop: 455474}); +---- ok +-STATEMENT CREATE (t:test {prop: 234660}); +---- ok +-STATEMENT CREATE (t:test {prop: 127880}); +---- ok +-STATEMENT CREATE (t:test {prop: 698293}); +---- ok +-STATEMENT CREATE (t:test {prop: 6773}); +---- ok +-STATEMENT CREATE (t:test {prop: 898506}); +---- ok +-STATEMENT CREATE (t:test {prop: 949624}); +---- ok +-STATEMENT CREATE (t:test {prop: 472149}); +---- ok +-STATEMENT CREATE (t:test {prop: 977942}); +---- ok +-STATEMENT CREATE (t:test {prop: 295279}); +---- ok +-STATEMENT CREATE (t:test {prop: 126517}); +---- ok +-STATEMENT CREATE (t:test {prop: 896323}); +---- ok +-STATEMENT CREATE (t:test {prop: 35755}); +---- ok +-STATEMENT CREATE (t:test {prop: 184961}); +---- ok +-STATEMENT CREATE (t:test {prop: 391980}); +---- ok +-STATEMENT CREATE (t:test {prop: 164469}); +---- ok +-STATEMENT CREATE (t:test {prop: 95576}); +---- ok +-STATEMENT CREATE (t:test {prop: 769030}); +---- ok +-STATEMENT CREATE (t:test {prop: 413459}); +---- ok +-STATEMENT CREATE (t:test {prop: 804858}); +---- ok +-STATEMENT CREATE (t:test {prop: 801014}); +---- ok +-STATEMENT CREATE (t:test {prop: 494598}); +---- ok +-STATEMENT CREATE (t:test {prop: 616235}); +---- ok +-STATEMENT CREATE (t:test {prop: 919628}); +---- ok +-STATEMENT CREATE (t:test {prop: 571865}); +---- ok +-STATEMENT CREATE (t:test {prop: 586364}); +---- ok +-STATEMENT CREATE (t:test {prop: 328173}); +---- ok +-STATEMENT CREATE (t:test {prop: 580547}); +---- ok +-STATEMENT CREATE (t:test {prop: 829374}); +---- ok +-STATEMENT CREATE (t:test {prop: 135857}); +---- ok +-STATEMENT CREATE (t:test {prop: 586923}); +---- ok +-STATEMENT CREATE (t:test {prop: 151078}); +---- ok +-STATEMENT CREATE (t:test {prop: 614836}); +---- ok +-STATEMENT CREATE (t:test {prop: 197984}); +---- ok +-STATEMENT CREATE (t:test {prop: 668330}); +---- ok +-STATEMENT CREATE (t:test {prop: 289540}); +---- ok +-STATEMENT CREATE (t:test {prop: 579641}); +---- ok +-STATEMENT CREATE (t:test {prop: 20214}); +---- ok +-STATEMENT CREATE (t:test {prop: 308013}); +---- ok +-STATEMENT CREATE (t:test {prop: 48815}); +---- ok +-STATEMENT CREATE (t:test {prop: 92856}); +---- ok +-STATEMENT CREATE (t:test {prop: 526374}); +---- ok +-STATEMENT CREATE (t:test {prop: 403532}); +---- ok +-STATEMENT CREATE (t:test {prop: 82256}); +---- ok +-STATEMENT CREATE (t:test {prop: 347036}); +---- ok +-STATEMENT CREATE (t:test {prop: 637882}); +---- ok +-STATEMENT CREATE (t:test {prop: 720554}); +---- ok +-STATEMENT CREATE (t:test {prop: 533675}); +---- ok +-STATEMENT CREATE (t:test {prop: 404240}); +---- ok +-STATEMENT CREATE (t:test {prop: 799546}); +---- ok +-STATEMENT CREATE (t:test {prop: 248421}); +---- ok +-STATEMENT CREATE (t:test {prop: 382657}); +---- ok +-STATEMENT CREATE (t:test {prop: 453244}); +---- ok +-STATEMENT CREATE (t:test {prop: 3354}); +---- ok +-STATEMENT CREATE (t:test {prop: 575429}); +---- ok +-STATEMENT CREATE (t:test {prop: 31470}); +---- ok +-STATEMENT CREATE (t:test {prop: 925663}); +---- ok +-STATEMENT CREATE (t:test {prop: 674738}); +---- ok +-STATEMENT CREATE (t:test {prop: 242714}); +---- ok +-STATEMENT CREATE (t:test {prop: 785843}); +---- ok +-STATEMENT CREATE (t:test {prop: 147747}); +---- ok +-STATEMENT CREATE (t:test {prop: 981450}); +---- ok +-STATEMENT CREATE (t:test {prop: 576661}); +---- ok +-STATEMENT CREATE (t:test {prop: 705809}); +---- ok +-STATEMENT CREATE (t:test {prop: 394380}); +---- ok +-STATEMENT CREATE (t:test {prop: 204119}); +---- ok +-STATEMENT CREATE (t:test {prop: 291060}); +---- ok +-STATEMENT CREATE (t:test {prop: 958414}); +---- ok +-STATEMENT CREATE (t:test {prop: 552745}); +---- ok +-STATEMENT CREATE (t:test {prop: 970721}); +---- ok +-STATEMENT CREATE (t:test {prop: 591895}); +---- ok +-STATEMENT CREATE (t:test {prop: 183541}); +---- ok +-STATEMENT CREATE (t:test {prop: 916934}); +---- ok +-STATEMENT CREATE (t:test {prop: 964365}); +---- ok +-STATEMENT CREATE (t:test {prop: 200735}); +---- ok +-STATEMENT CREATE (t:test {prop: 830207}); +---- ok +-STATEMENT CREATE (t:test {prop: 900841}); +---- ok +-STATEMENT CREATE (t:test {prop: 340694}); +---- ok +-STATEMENT CREATE (t:test {prop: 966376}); +---- ok +-STATEMENT CREATE (t:test {prop: 999242}); +---- ok +-STATEMENT CREATE (t:test {prop: 740297}); +---- ok +-STATEMENT CREATE (t:test {prop: 806447}); +---- ok +-STATEMENT CREATE (t:test {prop: 573691}); +---- ok +-STATEMENT CREATE (t:test {prop: 844634}); +---- ok +-STATEMENT CREATE (t:test {prop: 755323}); +---- ok +-STATEMENT CREATE (t:test {prop: 499336}); +---- ok +-STATEMENT CREATE (t:test {prop: 344288}); +---- ok +-STATEMENT CREATE (t:test {prop: 815983}); +---- ok +-STATEMENT CREATE (t:test {prop: 49671}); +---- ok +-STATEMENT CREATE (t:test {prop: 492504}); +---- ok +-STATEMENT CREATE (t:test {prop: 599301}); +---- ok +-STATEMENT CREATE (t:test {prop: 189066}); +---- ok +-STATEMENT CREATE (t:test {prop: 403474}); +---- ok +-STATEMENT CREATE (t:test {prop: 933332}); +---- ok +-STATEMENT CREATE (t:test {prop: 780430}); +---- ok +-STATEMENT CREATE (t:test {prop: 103296}); +---- ok +-STATEMENT CREATE (t:test {prop: 204424}); +---- ok +-STATEMENT CREATE (t:test {prop: 151220}); +---- ok +-STATEMENT CREATE (t:test {prop: 138274}); +---- ok +-STATEMENT CREATE (t:test {prop: 582079}); +---- ok +-STATEMENT CREATE (t:test {prop: 963561}); +---- ok +-STATEMENT CREATE (t:test {prop: 443798}); +---- ok +-STATEMENT CREATE (t:test {prop: 352180}); +---- ok +-STATEMENT CREATE (t:test {prop: 331006}); +---- ok +-STATEMENT CREATE (t:test {prop: 303458}); +---- ok +-STATEMENT CREATE (t:test {prop: 706725}); +---- ok +-STATEMENT CREATE (t:test {prop: 25144}); +---- ok +-STATEMENT CREATE (t:test {prop: 651288}); +---- ok +-STATEMENT CREATE (t:test {prop: 794462}); +---- ok +-STATEMENT CREATE (t:test {prop: 489587}); +---- ok +-STATEMENT CREATE (t:test {prop: 503401}); +---- ok +-STATEMENT CREATE (t:test {prop: 51004}); +---- ok +-STATEMENT CREATE (t:test {prop: 539722}); +---- ok +-STATEMENT CREATE (t:test {prop: 991371}); +---- ok +-STATEMENT CREATE (t:test {prop: 388807}); +---- ok +-STATEMENT CREATE (t:test {prop: 89188}); +---- ok +-STATEMENT CREATE (t:test {prop: 111522}); +---- ok +-STATEMENT CREATE (t:test {prop: 899385}); +---- ok +-STATEMENT CREATE (t:test {prop: 24832}); +---- ok +-STATEMENT CREATE (t:test {prop: 42064}); +---- ok +-STATEMENT CREATE (t:test {prop: 292728}); +---- ok +-STATEMENT CREATE (t:test {prop: 716721}); +---- ok +-STATEMENT CREATE (t:test {prop: 437771}); +---- ok +-STATEMENT CREATE (t:test {prop: 540791}); +---- ok +-STATEMENT CREATE (t:test {prop: 976956}); +---- ok +-STATEMENT CREATE (t:test {prop: 197335}); +---- ok +-STATEMENT CREATE (t:test {prop: 610467}); +---- ok +-STATEMENT CREATE (t:test {prop: 469687}); +---- ok +-STATEMENT CREATE (t:test {prop: 565616}); +---- ok +-STATEMENT CREATE (t:test {prop: 669204}); +---- ok +-STATEMENT CREATE (t:test {prop: 2076}); +---- ok +-STATEMENT CREATE (t:test {prop: 315791}); +---- ok +-STATEMENT CREATE (t:test {prop: 739192}); +---- ok +-STATEMENT CREATE (t:test {prop: 891517}); +---- ok +-STATEMENT CREATE (t:test {prop: 315294}); +---- ok +-STATEMENT CREATE (t:test {prop: 346389}); +---- ok +-STATEMENT CREATE (t:test {prop: 552508}); +---- ok +-STATEMENT CREATE (t:test {prop: 972497}); +---- ok +-STATEMENT CREATE (t:test {prop: 26061}); +---- ok +-STATEMENT CREATE (t:test {prop: 736082}); +---- ok +-STATEMENT CREATE (t:test {prop: 143036}); +---- ok +-STATEMENT CREATE (t:test {prop: 909355}); +---- ok +-STATEMENT CREATE (t:test {prop: 434700}); +---- ok +-STATEMENT CREATE (t:test {prop: 189407}); +---- ok +-STATEMENT CREATE (t:test {prop: 510825}); +---- ok +-STATEMENT CREATE (t:test {prop: 935509}); +---- ok +-STATEMENT CREATE (t:test {prop: 6560}); +---- ok +-STATEMENT CREATE (t:test {prop: 323427}); +---- ok +-STATEMENT CREATE (t:test {prop: 153199}); +---- ok +-STATEMENT CREATE (t:test {prop: 929780}); +---- ok +-STATEMENT CREATE (t:test {prop: 366235}); +---- ok +-STATEMENT CREATE (t:test {prop: 574539}); +---- ok +-STATEMENT CREATE (t:test {prop: 847603}); +---- ok +-STATEMENT CREATE (t:test {prop: 920571}); +---- ok +-STATEMENT CREATE (t:test {prop: 167420}); +---- ok +-STATEMENT CREATE (t:test {prop: 114495}); +---- ok +-STATEMENT CREATE (t:test {prop: 688021}); +---- ok +-STATEMENT CREATE (t:test {prop: 671240}); +---- ok +-STATEMENT CREATE (t:test {prop: 300793}); +---- ok +-STATEMENT CREATE (t:test {prop: 847613}); +---- ok +-STATEMENT CREATE (t:test {prop: 991339}); +---- ok +-STATEMENT CREATE (t:test {prop: 54156}); +---- ok +-STATEMENT CREATE (t:test {prop: 978945}); +---- ok +-STATEMENT CREATE (t:test {prop: 164853}); +---- ok +-STATEMENT CREATE (t:test {prop: 278213}); +---- ok +-STATEMENT CREATE (t:test {prop: 598262}); +---- ok +-STATEMENT CREATE (t:test {prop: 697225}); +---- ok +-STATEMENT CREATE (t:test {prop: 994873}); +---- ok +-STATEMENT CREATE (t:test {prop: 181765}); +---- ok +-STATEMENT CREATE (t:test {prop: 541318}); +---- ok +-STATEMENT CREATE (t:test {prop: 596435}); +---- ok +-STATEMENT CREATE (t:test {prop: 271986}); +---- ok +-STATEMENT CREATE (t:test {prop: 650616}); +---- ok +-STATEMENT CREATE (t:test {prop: 188784}); +---- ok +-STATEMENT CREATE (t:test {prop: 76475}); +---- ok +-STATEMENT CREATE (t:test {prop: 402707}); +---- ok +-STATEMENT CREATE (t:test {prop: 835840}); +---- ok +-STATEMENT CREATE (t:test {prop: 851718}); +---- ok +-STATEMENT CREATE (t:test {prop: 3075}); +---- ok +-STATEMENT CREATE (t:test {prop: 263873}); +---- ok +-STATEMENT CREATE (t:test {prop: 22657}); +---- ok +-STATEMENT CREATE (t:test {prop: 963817}); +---- ok +-STATEMENT CREATE (t:test {prop: 724126}); +---- ok +-STATEMENT CREATE (t:test {prop: 286556}); +---- ok +-STATEMENT CREATE (t:test {prop: 799459}); +---- ok +-STATEMENT CREATE (t:test {prop: 832011}); +---- ok +-STATEMENT CREATE (t:test {prop: 538349}); +---- ok +-STATEMENT CREATE (t:test {prop: 581703}); +---- ok +-STATEMENT CREATE (t:test {prop: 294666}); +---- ok +-STATEMENT CREATE (t:test {prop: 893232}); +---- ok +-STATEMENT CREATE (t:test {prop: 578987}); +---- ok +-STATEMENT CREATE (t:test {prop: 470077}); +---- ok +-STATEMENT CREATE (t:test {prop: 534938}); +---- ok +-STATEMENT CREATE (t:test {prop: 919459}); +---- ok +-STATEMENT CREATE (t:test {prop: 895322}); +---- ok +-STATEMENT CREATE (t:test {prop: 13854}); +---- ok +-STATEMENT CREATE (t:test {prop: 266249}); +---- ok +-STATEMENT CREATE (t:test {prop: 604355}); +---- ok +-STATEMENT CREATE (t:test {prop: 368955}); +---- ok +-STATEMENT CREATE (t:test {prop: 889793}); +---- ok +-STATEMENT CREATE (t:test {prop: 66617}); +---- ok +-STATEMENT CREATE (t:test {prop: 787366}); +---- ok +-STATEMENT CREATE (t:test {prop: 596009}); +---- ok +-STATEMENT CREATE (t:test {prop: 291470}); +---- ok +-STATEMENT CREATE (t:test {prop: 552298}); +---- ok +-STATEMENT CREATE (t:test {prop: 541110}); +---- ok +-STATEMENT CREATE (t:test {prop: 142418}); +---- ok +-STATEMENT CREATE (t:test {prop: 783482}); +---- ok +-STATEMENT CREATE (t:test {prop: 191458}); +---- ok +-STATEMENT CREATE (t:test {prop: 475588}); +---- ok +-STATEMENT CREATE (t:test {prop: 300453}); +---- ok +-STATEMENT CREATE (t:test {prop: 318388}); +---- ok +-STATEMENT CREATE (t:test {prop: 509492}); +---- ok +-STATEMENT CREATE (t:test {prop: 924773}); +---- ok +-STATEMENT CREATE (t:test {prop: 183790}); +---- ok +-STATEMENT CREATE (t:test {prop: 873838}); +---- ok +-STATEMENT CREATE (t:test {prop: 83298}); +---- ok +-STATEMENT CREATE (t:test {prop: 129967}); +---- ok +-STATEMENT CREATE (t:test {prop: 260272}); +---- ok +-STATEMENT CREATE (t:test {prop: 776354}); +---- ok +-STATEMENT CREATE (t:test {prop: 558924}); +---- ok +-STATEMENT CREATE (t:test {prop: 760551}); +---- ok +-STATEMENT CREATE (t:test {prop: 688906}); +---- ok +-STATEMENT CREATE (t:test {prop: 431186}); +---- ok +-STATEMENT CREATE (t:test {prop: 382848}); +---- ok +-STATEMENT CREATE (t:test {prop: 189550}); +---- ok +-STATEMENT CREATE (t:test {prop: 905953}); +---- ok +-STATEMENT CREATE (t:test {prop: 171283}); +---- ok +-STATEMENT CREATE (t:test {prop: 798120}); +---- ok +-STATEMENT CREATE (t:test {prop: 500900}); +---- ok +-STATEMENT CREATE (t:test {prop: 378898}); +---- ok +-STATEMENT CREATE (t:test {prop: 311563}); +---- ok +-STATEMENT CREATE (t:test {prop: 734825}); +---- ok +-STATEMENT CREATE (t:test {prop: 5699}); +---- ok +-STATEMENT CREATE (t:test {prop: 209751}); +---- ok +-STATEMENT CREATE (t:test {prop: 997741}); +---- ok +-STATEMENT CREATE (t:test {prop: 791613}); +---- ok +-STATEMENT CREATE (t:test {prop: 569510}); +---- ok +-STATEMENT CREATE (t:test {prop: 571778}); +---- ok +-STATEMENT CREATE (t:test {prop: 894570}); +---- ok +-STATEMENT CREATE (t:test {prop: 346825}); +---- ok +-STATEMENT CREATE (t:test {prop: 92202}); +---- ok +-STATEMENT CREATE (t:test {prop: 271412}); +---- ok +-STATEMENT CREATE (t:test {prop: 751244}); +---- ok +-STATEMENT CREATE (t:test {prop: 38287}); +---- ok +-STATEMENT CREATE (t:test {prop: 383132}); +---- ok +-STATEMENT CREATE (t:test {prop: 872341}); +---- ok +-STATEMENT CREATE (t:test {prop: 529381}); +---- ok +-STATEMENT CREATE (t:test {prop: 230866}); +---- ok +-STATEMENT CREATE (t:test {prop: 517218}); +---- ok +-STATEMENT CREATE (t:test {prop: 706707}); +---- ok +-STATEMENT CREATE (t:test {prop: 925754}); +---- ok +-STATEMENT CREATE (t:test {prop: 479926}); +---- ok +-STATEMENT CREATE (t:test {prop: 361646}); +---- ok +-STATEMENT CREATE (t:test {prop: 718630}); +---- ok +-STATEMENT CREATE (t:test {prop: 575900}); +---- ok +-STATEMENT CREATE (t:test {prop: 118868}); +---- ok +-STATEMENT CREATE (t:test {prop: 236342}); +---- ok +-STATEMENT CREATE (t:test {prop: 821689}); +---- ok +-STATEMENT CREATE (t:test {prop: 130664}); +---- ok +-STATEMENT CREATE (t:test {prop: 435695}); +---- ok +-STATEMENT CREATE (t:test {prop: 984805}); +---- ok +-STATEMENT CREATE (t:test {prop: 335156}); +---- ok +-STATEMENT CREATE (t:test {prop: 607805}); +---- ok +-STATEMENT CREATE (t:test {prop: 61180}); +---- ok +-STATEMENT CREATE (t:test {prop: 946492}); +---- ok +-STATEMENT CREATE (t:test {prop: 211689}); +---- ok +-STATEMENT CREATE (t:test {prop: 354950}); +---- ok +-STATEMENT CREATE (t:test {prop: 80466}); +---- ok +-STATEMENT CREATE (t:test {prop: 110139}); +---- ok +-STATEMENT CREATE (t:test {prop: 591202}); +---- ok +-STATEMENT CREATE (t:test {prop: 256231}); +---- ok +-STATEMENT CREATE (t:test {prop: 66397}); +---- ok +-STATEMENT CREATE (t:test {prop: 887520}); +---- ok +-STATEMENT CREATE (t:test {prop: 728506}); +---- ok +-STATEMENT CREATE (t:test {prop: 553743}); +---- ok +-STATEMENT CREATE (t:test {prop: 348338}); +---- ok +-STATEMENT CREATE (t:test {prop: 4229}); +---- ok +-STATEMENT CREATE (t:test {prop: 880772}); +---- ok +-STATEMENT CREATE (t:test {prop: 396245}); +---- ok +-STATEMENT CREATE (t:test {prop: 378578}); +---- ok +-STATEMENT CREATE (t:test {prop: 154262}); +---- ok +-STATEMENT CREATE (t:test {prop: 638997}); +---- ok +-STATEMENT CREATE (t:test {prop: 420662}); +---- ok +-STATEMENT CREATE (t:test {prop: 39106}); +---- ok +-STATEMENT CREATE (t:test {prop: 541762}); +---- ok +-STATEMENT CREATE (t:test {prop: 696261}); +---- ok +-STATEMENT CREATE (t:test {prop: 118402}); +---- ok +-STATEMENT CREATE (t:test {prop: 529452}); +---- ok +-STATEMENT CREATE (t:test {prop: 314261}); +---- ok +-STATEMENT CREATE (t:test {prop: 80427}); +---- ok +-STATEMENT CREATE (t:test {prop: 443270}); +---- ok +-STATEMENT CREATE (t:test {prop: 324693}); +---- ok +-STATEMENT CREATE (t:test {prop: 930685}); +---- ok +-STATEMENT CREATE (t:test {prop: 563343}); +---- ok +-STATEMENT CREATE (t:test {prop: 780515}); +---- ok +-STATEMENT CREATE (t:test {prop: 786872}); +---- ok +-STATEMENT CREATE (t:test {prop: 830152}); +---- ok +-STATEMENT CREATE (t:test {prop: 610438}); +---- ok +-STATEMENT CREATE (t:test {prop: 458750}); +---- ok +-STATEMENT CREATE (t:test {prop: 870417}); +---- ok +-STATEMENT CREATE (t:test {prop: 795999}); +---- ok +-STATEMENT CREATE (t:test {prop: 334595}); +---- ok +-STATEMENT CREATE (t:test {prop: 357587}); +---- ok +-STATEMENT CREATE (t:test {prop: 35773}); +---- ok +-STATEMENT CREATE (t:test {prop: 655686}); +---- ok +-STATEMENT CREATE (t:test {prop: 117945}); +---- ok +-STATEMENT CREATE (t:test {prop: 160025}); +---- ok +-STATEMENT CREATE (t:test {prop: 751121}); +---- ok +-STATEMENT CREATE (t:test {prop: 5012}); +---- ok +-STATEMENT CREATE (t:test {prop: 521839}); +---- ok +-STATEMENT CREATE (t:test {prop: 39604}); +---- ok +-STATEMENT CREATE (t:test {prop: 365608}); +---- ok +-STATEMENT CREATE (t:test {prop: 283866}); +---- ok +-STATEMENT CREATE (t:test {prop: 750120}); +---- ok +-STATEMENT CREATE (t:test {prop: 283496}); +---- ok +-STATEMENT CREATE (t:test {prop: 236625}); +---- ok +-STATEMENT CREATE (t:test {prop: 311437}); +---- ok +-STATEMENT CREATE (t:test {prop: 805830}); +---- ok +-STATEMENT CREATE (t:test {prop: 128244}); +---- ok +-STATEMENT CREATE (t:test {prop: 317653}); +---- ok +-STATEMENT CREATE (t:test {prop: 838372}); +---- ok +-STATEMENT CREATE (t:test {prop: 169840}); +---- ok +-STATEMENT CREATE (t:test {prop: 751744}); +---- ok +-STATEMENT CREATE (t:test {prop: 83587}); +---- ok +-STATEMENT CREATE (t:test {prop: 761373}); +---- ok +-STATEMENT CREATE (t:test {prop: 559429}); +---- ok +-STATEMENT CREATE (t:test {prop: 447204}); +---- ok +-STATEMENT CREATE (t:test {prop: 587225}); +---- ok +-STATEMENT CREATE (t:test {prop: 653825}); +---- ok +-STATEMENT CREATE (t:test {prop: 975675}); +---- ok +-STATEMENT CREATE (t:test {prop: 957304}); +---- ok +-STATEMENT CREATE (t:test {prop: 412316}); +---- ok +-STATEMENT CREATE (t:test {prop: 747893}); +---- ok +-STATEMENT CREATE (t:test {prop: 172627}); +---- ok +-STATEMENT CREATE (t:test {prop: 137290}); +---- ok +-STATEMENT CREATE (t:test {prop: 170619}); +---- ok +-STATEMENT CREATE (t:test {prop: 902213}); +---- ok +-STATEMENT CREATE (t:test {prop: 165081}); +---- ok +-STATEMENT CREATE (t:test {prop: 278501}); +---- ok +-STATEMENT CREATE (t:test {prop: 908882}); +---- ok +-STATEMENT CREATE (t:test {prop: 552721}); +---- ok +-STATEMENT CREATE (t:test {prop: 229077}); +---- ok +-STATEMENT CREATE (t:test {prop: 634824}); +---- ok +-STATEMENT CREATE (t:test {prop: 674169}); +---- ok +-STATEMENT CREATE (t:test {prop: 68460}); +---- ok +-STATEMENT CREATE (t:test {prop: 774789}); +---- ok +-STATEMENT CREATE (t:test {prop: 305949}); +---- ok +-STATEMENT CREATE (t:test {prop: 516968}); +---- ok +-STATEMENT CREATE (t:test {prop: 698229}); +---- ok +-STATEMENT CREATE (t:test {prop: 50073}); +---- ok +-STATEMENT CREATE (t:test {prop: 797342}); +---- ok +-STATEMENT CREATE (t:test {prop: 497209}); +---- ok +-STATEMENT CREATE (t:test {prop: 869777}); +---- ok +-STATEMENT CREATE (t:test {prop: 539791}); +---- ok +-STATEMENT CREATE (t:test {prop: 294027}); +---- ok +-STATEMENT CREATE (t:test {prop: 988023}); +---- ok +-STATEMENT CREATE (t:test {prop: 28427}); +---- ok +-STATEMENT CREATE (t:test {prop: 38573}); +---- ok +-STATEMENT CREATE (t:test {prop: 485346}); +---- ok +-STATEMENT CREATE (t:test {prop: 817859}); +---- ok +-STATEMENT CREATE (t:test {prop: 459254}); +---- ok +-STATEMENT CREATE (t:test {prop: 477841}); +---- ok +-STATEMENT CREATE (t:test {prop: 655978}); +---- ok +-STATEMENT CREATE (t:test {prop: 900028}); +---- ok +-STATEMENT CREATE (t:test {prop: 652981}); +---- ok +-STATEMENT CREATE (t:test {prop: 267802}); +---- ok +-STATEMENT CREATE (t:test {prop: 421218}); +---- ok +-STATEMENT CREATE (t:test {prop: 94507}); +---- ok +-STATEMENT CREATE (t:test {prop: 374450}); +---- ok +-STATEMENT CREATE (t:test {prop: 156397}); +---- ok +-STATEMENT CREATE (t:test {prop: 987004}); +---- ok +-STATEMENT CREATE (t:test {prop: 355090}); +---- ok +-STATEMENT CREATE (t:test {prop: 32271}); +---- ok +-STATEMENT CREATE (t:test {prop: 550534}); +---- ok +-STATEMENT CREATE (t:test {prop: 340453}); +---- ok +-STATEMENT CREATE (t:test {prop: 892821}); +---- ok +-STATEMENT CREATE (t:test {prop: 33793}); +---- ok +-STATEMENT CREATE (t:test {prop: 976746}); +---- ok +-STATEMENT CREATE (t:test {prop: 375797}); +---- ok +-STATEMENT CREATE (t:test {prop: 498309}); +---- ok +-STATEMENT CREATE (t:test {prop: 168693}); +---- ok +-STATEMENT CREATE (t:test {prop: 973135}); +---- ok +-STATEMENT CREATE (t:test {prop: 556269}); +---- ok +-STATEMENT CREATE (t:test {prop: 167064}); +---- ok +-STATEMENT CREATE (t:test {prop: 404363}); +---- ok +-STATEMENT CREATE (t:test {prop: 248737}); +---- ok +-STATEMENT CREATE (t:test {prop: 364654}); +---- ok +-STATEMENT CREATE (t:test {prop: 107956}); +---- ok +-STATEMENT CREATE (t:test {prop: 878015}); +---- ok +-STATEMENT CREATE (t:test {prop: 458569}); +---- ok +-STATEMENT CREATE (t:test {prop: 315568}); +---- ok +-STATEMENT CREATE (t:test {prop: 756820}); +---- ok +-STATEMENT CREATE (t:test {prop: 261094}); +---- ok +-STATEMENT CREATE (t:test {prop: 236789}); +---- ok +-STATEMENT CREATE (t:test {prop: 227798}); +---- ok +-STATEMENT CREATE (t:test {prop: 612917}); +---- ok +-STATEMENT CREATE (t:test {prop: 782507}); +---- ok +-STATEMENT CREATE (t:test {prop: 52603}); +---- ok +-STATEMENT CREATE (t:test {prop: 145829}); +---- ok +-STATEMENT CREATE (t:test {prop: 465472}); +---- ok +-STATEMENT CREATE (t:test {prop: 82843}); +---- ok +-STATEMENT CREATE (t:test {prop: 177264}); +---- ok +-STATEMENT CREATE (t:test {prop: 426798}); +---- ok +-STATEMENT CREATE (t:test {prop: 623885}); +---- ok +-STATEMENT CREATE (t:test {prop: 105322}); +---- ok +-STATEMENT CREATE (t:test {prop: 876198}); +---- ok +-STATEMENT CREATE (t:test {prop: 452788}); +---- ok +-STATEMENT CREATE (t:test {prop: 181534}); +---- ok +-STATEMENT CREATE (t:test {prop: 126321}); +---- ok +-STATEMENT CREATE (t:test {prop: 463373}); +---- ok +-STATEMENT CREATE (t:test {prop: 596021}); +---- ok +-STATEMENT CREATE (t:test {prop: 578267}); +---- ok +-STATEMENT CREATE (t:test {prop: 770412}); +---- ok +-STATEMENT CREATE (t:test {prop: 62265}); +---- ok +-STATEMENT CREATE (t:test {prop: 531688}); +---- ok +-STATEMENT CREATE (t:test {prop: 803227}); +---- ok +-STATEMENT CREATE (t:test {prop: 340187}); +---- ok +-STATEMENT CREATE (t:test {prop: 252011}); +---- ok +-STATEMENT CREATE (t:test {prop: 655067}); +---- ok +-STATEMENT CREATE (t:test {prop: 433422}); +---- ok +-STATEMENT CREATE (t:test {prop: 754209}); +---- ok +-STATEMENT CREATE (t:test {prop: 58397}); +---- ok +-STATEMENT CREATE (t:test {prop: 969387}); +---- ok +-STATEMENT CREATE (t:test {prop: 143373}); +---- ok +-STATEMENT CREATE (t:test {prop: 285348}); +---- ok +-STATEMENT CREATE (t:test {prop: 453300}); +---- ok +-STATEMENT CREATE (t:test {prop: 50701}); +---- ok +-STATEMENT CREATE (t:test {prop: 450206}); +---- ok +-STATEMENT CREATE (t:test {prop: 906606}); +---- ok +-STATEMENT CREATE (t:test {prop: 918735}); +---- ok +-STATEMENT CREATE (t:test {prop: 761488}); +---- ok +-STATEMENT CREATE (t:test {prop: 220778}); +---- ok +-STATEMENT CREATE (t:test {prop: 274156}); +---- ok +-STATEMENT CREATE (t:test {prop: 951088}); +---- ok +-STATEMENT CREATE (t:test {prop: 774734}); +---- ok +-STATEMENT CREATE (t:test {prop: 527017}); +---- ok +-STATEMENT CREATE (t:test {prop: 985599}); +---- ok +-STATEMENT CREATE (t:test {prop: 136496}); +---- ok +-STATEMENT CREATE (t:test {prop: 116574}); +---- ok +-STATEMENT CREATE (t:test {prop: 407173}); +---- ok +-STATEMENT CREATE (t:test {prop: 322626}); +---- ok +-STATEMENT CREATE (t:test {prop: 826525}); +---- ok +-STATEMENT CREATE (t:test {prop: 652372}); +---- ok +-STATEMENT CREATE (t:test {prop: 438378}); +---- ok +-STATEMENT CREATE (t:test {prop: 654440}); +---- ok +-STATEMENT CREATE (t:test {prop: 253786}); +---- ok +-STATEMENT CREATE (t:test {prop: 140840}); +---- ok +-STATEMENT CREATE (t:test {prop: 669028}); +---- ok +-STATEMENT CREATE (t:test {prop: 797114}); +---- ok +-STATEMENT CREATE (t:test {prop: 818919}); +---- ok +-STATEMENT CREATE (t:test {prop: 873741}); +---- ok +-STATEMENT CREATE (t:test {prop: 321364}); +---- ok +-STATEMENT CREATE (t:test {prop: 270178}); +---- ok +-STATEMENT CREATE (t:test {prop: 806576}); +---- ok +-STATEMENT CREATE (t:test {prop: 893851}); +---- ok +-STATEMENT CREATE (t:test {prop: 306666}); +---- ok +-STATEMENT CREATE (t:test {prop: 362403}); +---- ok +-STATEMENT CREATE (t:test {prop: 759125}); +---- ok +-STATEMENT CREATE (t:test {prop: 160617}); +---- ok +-STATEMENT CREATE (t:test {prop: 125382}); +---- ok +-STATEMENT CREATE (t:test {prop: 757802}); +---- ok +-STATEMENT CREATE (t:test {prop: 22163}); +---- ok +-STATEMENT CREATE (t:test {prop: 783005}); +---- ok +-STATEMENT CREATE (t:test {prop: 241363}); +---- ok +-STATEMENT CREATE (t:test {prop: 399055}); +---- ok +-STATEMENT CREATE (t:test {prop: 471919}); +---- ok +-STATEMENT CREATE (t:test {prop: 283256}); +---- ok +-STATEMENT CREATE (t:test {prop: 360988}); +---- ok +-STATEMENT CREATE (t:test {prop: 254954}); +---- ok +-STATEMENT CREATE (t:test {prop: 179736}); +---- ok +-STATEMENT CREATE (t:test {prop: 995829}); +---- ok +-STATEMENT CREATE (t:test {prop: 634642}); +---- ok +-STATEMENT CREATE (t:test {prop: 600133}); +---- ok +-STATEMENT CREATE (t:test {prop: 615512}); +---- ok +-STATEMENT CREATE (t:test {prop: 868931}); +---- ok +-STATEMENT CREATE (t:test {prop: 835900}); +---- ok +-STATEMENT CREATE (t:test {prop: 159477}); +---- ok +-STATEMENT CREATE (t:test {prop: 365911}); +---- ok +-STATEMENT CREATE (t:test {prop: 129256}); +---- ok +-STATEMENT CREATE (t:test {prop: 768746}); +---- ok +-STATEMENT CREATE (t:test {prop: 584438}); +---- ok +-STATEMENT CREATE (t:test {prop: 548058}); +---- ok +-STATEMENT CREATE (t:test {prop: 33343}); +---- ok +-STATEMENT CREATE (t:test {prop: 700888}); +---- ok +-STATEMENT CREATE (t:test {prop: 272136}); +---- ok +-STATEMENT CREATE (t:test {prop: 382800}); +---- ok +-STATEMENT CREATE (t:test {prop: 320963}); +---- ok +-STATEMENT CREATE (t:test {prop: 437087}); +---- ok +-STATEMENT CREATE (t:test {prop: 610356}); +---- ok +-STATEMENT CREATE (t:test {prop: 837575}); +---- ok +-STATEMENT CREATE (t:test {prop: 922136}); +---- ok +-STATEMENT CREATE (t:test {prop: 204938}); +---- ok +-STATEMENT CREATE (t:test {prop: 255827}); +---- ok +-STATEMENT CREATE (t:test {prop: 335916}); +---- ok +-STATEMENT CREATE (t:test {prop: 124594}); +---- ok +-STATEMENT CREATE (t:test {prop: 571134}); +---- ok +-STATEMENT CREATE (t:test {prop: 287167}); +---- ok +-STATEMENT CREATE (t:test {prop: 850692}); +---- ok +-STATEMENT CREATE (t:test {prop: 371018}); +---- ok +-STATEMENT CREATE (t:test {prop: 97002}); +---- ok +-STATEMENT CREATE (t:test {prop: 369158}); +---- ok +-STATEMENT CREATE (t:test {prop: 929871}); +---- ok +-STATEMENT CREATE (t:test {prop: 812305}); +---- ok +-STATEMENT CREATE (t:test {prop: 64559}); +---- ok +-STATEMENT CREATE (t:test {prop: 613596}); +---- ok +-STATEMENT CREATE (t:test {prop: 460524}); +---- ok +-STATEMENT CREATE (t:test {prop: 95947}); +---- ok +-STATEMENT CREATE (t:test {prop: 864084}); +---- ok +-STATEMENT CREATE (t:test {prop: 867314}); +---- ok +-STATEMENT CREATE (t:test {prop: 573380}); +---- ok +-STATEMENT CREATE (t:test {prop: 189803}); +---- ok +-STATEMENT CREATE (t:test {prop: 973451}); +---- ok +-STATEMENT CREATE (t:test {prop: 629860}); +---- ok +-STATEMENT CREATE (t:test {prop: 390288}); +---- ok +-STATEMENT CREATE (t:test {prop: 20233}); +---- ok +-STATEMENT CREATE (t:test {prop: 843033}); +---- ok +-STATEMENT CREATE (t:test {prop: 702649}); +---- ok +-STATEMENT CREATE (t:test {prop: 699556}); +---- ok +-STATEMENT CREATE (t:test {prop: 534897}); +---- ok +-STATEMENT CREATE (t:test {prop: 366153}); +---- ok +-STATEMENT CREATE (t:test {prop: 908435}); +---- ok +-STATEMENT CREATE (t:test {prop: 324595}); +---- ok +-STATEMENT CREATE (t:test {prop: 534766}); +---- ok +-STATEMENT CREATE (t:test {prop: 67790}); +---- ok +-STATEMENT CREATE (t:test {prop: 264598}); +---- ok +-STATEMENT CREATE (t:test {prop: 542704}); +---- ok +-STATEMENT CREATE (t:test {prop: 70852}); +---- ok +-STATEMENT CREATE (t:test {prop: 613993}); +---- ok +-STATEMENT CREATE (t:test {prop: 307876}); +---- ok +-STATEMENT CREATE (t:test {prop: 143498}); +---- ok +-STATEMENT CREATE (t:test {prop: 972528}); +---- ok +-STATEMENT CREATE (t:test {prop: 696354}); +---- ok +-STATEMENT CREATE (t:test {prop: 869588}); +---- ok +-STATEMENT CREATE (t:test {prop: 360706}); +---- ok +-STATEMENT CREATE (t:test {prop: 608705}); +---- ok +-STATEMENT CREATE (t:test {prop: 264484}); +---- ok +-STATEMENT CREATE (t:test {prop: 536820}); +---- ok +-STATEMENT CREATE (t:test {prop: 526829}); +---- ok +-STATEMENT CREATE (t:test {prop: 359904}); +---- ok +-STATEMENT CREATE (t:test {prop: 442125}); +---- ok +-STATEMENT CREATE (t:test {prop: 660253}); +---- ok +-STATEMENT CREATE (t:test {prop: 726713}); +---- ok +-STATEMENT CREATE (t:test {prop: 743903}); +---- ok +-STATEMENT CREATE (t:test {prop: 871470}); +---- ok +-STATEMENT CREATE (t:test {prop: 117210}); +---- ok +-STATEMENT CREATE (t:test {prop: 424007}); +---- ok +-STATEMENT CREATE (t:test {prop: 948784}); +---- ok +-STATEMENT CREATE (t:test {prop: 402704}); +---- ok +-STATEMENT CREATE (t:test {prop: 385367}); +---- ok +-STATEMENT CREATE (t:test {prop: 908643}); +---- ok +-STATEMENT CREATE (t:test {prop: 225221}); +---- ok +-STATEMENT CREATE (t:test {prop: 105475}); +---- ok +-STATEMENT CREATE (t:test {prop: 568534}); +---- ok +-STATEMENT CREATE (t:test {prop: 408512}); +---- ok +-STATEMENT CREATE (t:test {prop: 238387}); +---- ok +-STATEMENT CREATE (t:test {prop: 179413}); +---- ok +-STATEMENT CREATE (t:test {prop: 829125}); +---- ok +-STATEMENT CREATE (t:test {prop: 418168}); +---- ok +-STATEMENT CREATE (t:test {prop: 546262}); +---- ok +-STATEMENT CREATE (t:test {prop: 760683}); +---- ok +-STATEMENT CREATE (t:test {prop: 581926}); +---- ok +-STATEMENT CREATE (t:test {prop: 494661}); +---- ok +-STATEMENT CREATE (t:test {prop: 958911}); +---- ok +-STATEMENT CREATE (t:test {prop: 572894}); +---- ok +-STATEMENT CREATE (t:test {prop: 485668}); +---- ok +-STATEMENT CREATE (t:test {prop: 793967}); +---- ok +-STATEMENT CREATE (t:test {prop: 724462}); +---- ok +-STATEMENT CREATE (t:test {prop: 500121}); +---- ok +-STATEMENT CREATE (t:test {prop: 471653}); +---- ok +-STATEMENT CREATE (t:test {prop: 866425}); +---- ok +-STATEMENT CREATE (t:test {prop: 520209}); +---- ok +-STATEMENT CREATE (t:test {prop: 933820}); +---- ok +-STATEMENT CREATE (t:test {prop: 376991}); +---- ok +-STATEMENT CREATE (t:test {prop: 476287}); +---- ok +-STATEMENT CREATE (t:test {prop: 645318}); +---- ok +-STATEMENT CREATE (t:test {prop: 297346}); +---- ok +-STATEMENT CREATE (t:test {prop: 183912}); +---- ok +-STATEMENT CREATE (t:test {prop: 767360}); +---- ok +-STATEMENT CREATE (t:test {prop: 827387}); +---- ok +-STATEMENT CREATE (t:test {prop: 395003}); +---- ok +-STATEMENT CREATE (t:test {prop: 272764}); +---- ok +-STATEMENT CREATE (t:test {prop: 750183}); +---- ok +-STATEMENT CREATE (t:test {prop: 340169}); +---- ok +-STATEMENT CREATE (t:test {prop: 630114}); +---- ok +-STATEMENT CREATE (t:test {prop: 579585}); +---- ok +-STATEMENT CREATE (t:test {prop: 757980}); +---- ok +-STATEMENT CREATE (t:test {prop: 151569}); +---- ok +-STATEMENT CREATE (t:test {prop: 248754}); +---- ok +-STATEMENT CREATE (t:test {prop: 76042}); +---- ok +-STATEMENT CREATE (t:test {prop: 563570}); +---- ok +-STATEMENT CREATE (t:test {prop: 167817}); +---- ok +-STATEMENT CREATE (t:test {prop: 663261}); +---- ok +-STATEMENT CREATE (t:test {prop: 212284}); +---- ok +-STATEMENT CREATE (t:test {prop: 547607}); +---- ok +-STATEMENT CREATE (t:test {prop: 962290}); +---- ok +-STATEMENT CREATE (t:test {prop: 913394}); +---- ok +-STATEMENT CREATE (t:test {prop: 132519}); +---- ok +-STATEMENT CREATE (t:test {prop: 432309}); +---- ok +-STATEMENT CREATE (t:test {prop: 683271}); +---- ok +-STATEMENT CREATE (t:test {prop: 992183}); +---- ok +-STATEMENT CREATE (t:test {prop: 766204}); +---- ok +-STATEMENT CREATE (t:test {prop: 223954}); +---- ok +-STATEMENT CREATE (t:test {prop: 769600}); +---- ok +-STATEMENT CREATE (t:test {prop: 208943}); +---- ok +-STATEMENT CREATE (t:test {prop: 765764}); +---- ok +-STATEMENT CREATE (t:test {prop: 926499}); +---- ok +-STATEMENT CREATE (t:test {prop: 83812}); +---- ok +-STATEMENT CREATE (t:test {prop: 136868}); +---- ok +-STATEMENT CREATE (t:test {prop: 713083}); +---- ok +-STATEMENT CREATE (t:test {prop: 782983}); +---- ok +-STATEMENT CREATE (t:test {prop: 371468}); +---- ok +-STATEMENT CREATE (t:test {prop: 834368}); +---- ok +-STATEMENT CREATE (t:test {prop: 819633}); +---- ok +-STATEMENT CREATE (t:test {prop: 813410}); +---- ok +-STATEMENT CREATE (t:test {prop: 330292}); +---- ok +-STATEMENT CREATE (t:test {prop: 843409}); +---- ok +-STATEMENT CREATE (t:test {prop: 668637}); +---- ok +-STATEMENT CREATE (t:test {prop: 450217}); +---- ok +-STATEMENT CREATE (t:test {prop: 853487}); +---- ok +-STATEMENT CREATE (t:test {prop: 718165}); +---- ok +-STATEMENT CREATE (t:test {prop: 125301}); +---- ok +-STATEMENT CREATE (t:test {prop: 660861}); +---- ok +-STATEMENT CREATE (t:test {prop: 883056}); +---- ok +-STATEMENT CREATE (t:test {prop: 18427}); +---- ok +-STATEMENT CREATE (t:test {prop: 887683}); +---- ok +-STATEMENT CREATE (t:test {prop: 543560}); +---- ok +-STATEMENT CREATE (t:test {prop: 767577}); +---- ok +-STATEMENT CREATE (t:test {prop: 449874}); +---- ok +-STATEMENT CREATE (t:test {prop: 144901}); +---- ok +-STATEMENT CREATE (t:test {prop: 698855}); +---- ok +-STATEMENT CREATE (t:test {prop: 623914}); +---- ok +-STATEMENT CREATE (t:test {prop: 88726}); +---- ok +-STATEMENT CREATE (t:test {prop: 86327}); +---- ok +-STATEMENT CREATE (t:test {prop: 123569}); +---- ok +-STATEMENT CREATE (t:test {prop: 600528}); +---- ok +-STATEMENT CREATE (t:test {prop: 751497}); +---- ok +-STATEMENT CREATE (t:test {prop: 949622}); +---- ok +-STATEMENT CREATE (t:test {prop: 69109}); +---- ok +-STATEMENT CREATE (t:test {prop: 441148}); +---- ok +-STATEMENT CREATE (t:test {prop: 548586}); +---- ok +-STATEMENT CREATE (t:test {prop: 949734}); +---- ok +-STATEMENT CREATE (t:test {prop: 560346}); +---- ok +-STATEMENT CREATE (t:test {prop: 824900}); +---- ok +-STATEMENT CREATE (t:test {prop: 851405}); +---- ok +-STATEMENT CREATE (t:test {prop: 930601}); +---- ok +-STATEMENT CREATE (t:test {prop: 461777}); +---- ok +-STATEMENT CREATE (t:test {prop: 243515}); +---- ok +-STATEMENT CREATE (t:test {prop: 214920}); +---- ok +-STATEMENT CREATE (t:test {prop: 824301}); +---- ok +-STATEMENT CREATE (t:test {prop: 343615}); +---- ok +-STATEMENT CREATE (t:test {prop: 726372}); +---- ok +-STATEMENT CREATE (t:test {prop: 95199}); +---- ok +-STATEMENT CREATE (t:test {prop: 373283}); +---- ok +-STATEMENT CREATE (t:test {prop: 775487}); +---- ok +-STATEMENT CREATE (t:test {prop: 836251}); +---- ok +-STATEMENT CREATE (t:test {prop: 72290}); +---- ok +-STATEMENT CREATE (t:test {prop: 799735}); +---- ok +-STATEMENT CREATE (t:test {prop: 664458}); +---- ok +-STATEMENT CREATE (t:test {prop: 279709}); +---- ok +-STATEMENT CREATE (t:test {prop: 470216}); +---- ok +-STATEMENT CREATE (t:test {prop: 632007}); +---- ok +-STATEMENT CREATE (t:test {prop: 674885}); +---- ok +-STATEMENT CREATE (t:test {prop: 528428}); +---- ok +-STATEMENT CREATE (t:test {prop: 156392}); +---- ok +-STATEMENT CREATE (t:test {prop: 557423}); +---- ok +-STATEMENT CREATE (t:test {prop: 837341}); +---- ok +-STATEMENT CREATE (t:test {prop: 225757}); +---- ok +-STATEMENT CREATE (t:test {prop: 600161}); +---- ok +-STATEMENT CREATE (t:test {prop: 480198}); +---- ok +-STATEMENT CREATE (t:test {prop: 757538}); +---- ok +-STATEMENT CREATE (t:test {prop: 62410}); +---- ok +-STATEMENT CREATE (t:test {prop: 310732}); +---- ok +-STATEMENT CREATE (t:test {prop: 872297}); +---- ok +-STATEMENT CREATE (t:test {prop: 286551}); +---- ok +-STATEMENT CREATE (t:test {prop: 161869}); +---- ok +-STATEMENT CREATE (t:test {prop: 371230}); +---- ok +-STATEMENT CREATE (t:test {prop: 230275}); +---- ok +-STATEMENT CREATE (t:test {prop: 428854}); +---- ok +-STATEMENT CREATE (t:test {prop: 746204}); +---- ok +-STATEMENT CREATE (t:test {prop: 84684}); +---- ok +-STATEMENT CREATE (t:test {prop: 989677}); +---- ok +-STATEMENT CREATE (t:test {prop: 261783}); +---- ok +-STATEMENT CREATE (t:test {prop: 623584}); +---- ok +-STATEMENT CREATE (t:test {prop: 582112}); +---- ok +-STATEMENT CREATE (t:test {prop: 325007}); +---- ok +-STATEMENT CREATE (t:test {prop: 683024}); +---- ok +-STATEMENT CREATE (t:test {prop: 408811}); +---- ok +-STATEMENT CREATE (t:test {prop: 98209}); +---- ok +-STATEMENT CREATE (t:test {prop: 526260}); +---- ok +-STATEMENT CREATE (t:test {prop: 17400}); +---- ok +-STATEMENT CREATE (t:test {prop: 213990}); +---- ok +-STATEMENT CREATE (t:test {prop: 800935}); +---- ok +-STATEMENT CREATE (t:test {prop: 199123}); +---- ok +-STATEMENT CREATE (t:test {prop: 667617}); +---- ok +-STATEMENT CREATE (t:test {prop: 309292}); +---- ok +-STATEMENT CREATE (t:test {prop: 329036}); +---- ok +-STATEMENT CREATE (t:test {prop: 913711}); +---- ok +-STATEMENT CREATE (t:test {prop: 162923}); +---- ok +-STATEMENT CREATE (t:test {prop: 266150}); +---- ok +-STATEMENT CREATE (t:test {prop: 451760}); +---- ok +-STATEMENT CREATE (t:test {prop: 383737}); +---- ok +-STATEMENT CREATE (t:test {prop: 990711}); +---- ok +-STATEMENT CREATE (t:test {prop: 568201}); +---- ok +-STATEMENT CREATE (t:test {prop: 160983}); +---- ok +-STATEMENT CREATE (t:test {prop: 561989}); +---- ok +-STATEMENT CREATE (t:test {prop: 229664}); +---- ok +-STATEMENT CREATE (t:test {prop: 919656}); +---- ok +-STATEMENT CREATE (t:test {prop: 476996}); +---- ok +-STATEMENT CREATE (t:test {prop: 203562}); +---- ok +-STATEMENT CREATE (t:test {prop: 226564}); +---- ok +-STATEMENT CREATE (t:test {prop: 523947}); +---- ok +-STATEMENT CREATE (t:test {prop: 844860}); +---- ok +-STATEMENT CREATE (t:test {prop: 268284}); +---- ok +-STATEMENT CREATE (t:test {prop: 459169}); +---- ok +-STATEMENT CREATE (t:test {prop: 668762}); +---- ok +-STATEMENT CREATE (t:test {prop: 290885}); +---- ok +-STATEMENT CREATE (t:test {prop: 879604}); +---- ok +-STATEMENT CREATE (t:test {prop: 649562}); +---- ok +-STATEMENT CREATE (t:test {prop: 627772}); +---- ok +-STATEMENT CREATE (t:test {prop: 95125}); +---- ok +-STATEMENT CREATE (t:test {prop: 171794}); +---- ok +-STATEMENT CREATE (t:test {prop: 718874}); +---- ok +-STATEMENT CREATE (t:test {prop: 509446}); +---- ok +-STATEMENT CREATE (t:test {prop: 21206}); +---- ok +-STATEMENT CREATE (t:test {prop: 207336}); +---- ok +-STATEMENT CREATE (t:test {prop: 272465}); +---- ok +-STATEMENT CREATE (t:test {prop: 573112}); +---- ok +-STATEMENT CREATE (t:test {prop: 835661}); +---- ok +-STATEMENT CREATE (t:test {prop: 11099}); +---- ok +-STATEMENT CREATE (t:test {prop: 364820}); +---- ok +-STATEMENT CREATE (t:test {prop: 290706}); +---- ok +-STATEMENT CREATE (t:test {prop: 903701}); +---- ok +-STATEMENT CREATE (t:test {prop: 407579}); +---- ok +-STATEMENT CREATE (t:test {prop: 773125}); +---- ok +-STATEMENT CREATE (t:test {prop: 152672}); +---- ok +-STATEMENT CREATE (t:test {prop: 722224}); +---- ok +-STATEMENT CREATE (t:test {prop: 177391}); +---- ok +-STATEMENT CREATE (t:test {prop: 20233}); +---- ok +-STATEMENT CREATE (t:test {prop: 162372}); +---- ok +-STATEMENT CREATE (t:test {prop: 236520}); +---- ok +-STATEMENT CREATE (t:test {prop: 865639}); +---- ok +-STATEMENT CREATE (t:test {prop: 53354}); +---- ok +-STATEMENT CREATE (t:test {prop: 259736}); +---- ok +-STATEMENT CREATE (t:test {prop: 65083}); +---- ok +-STATEMENT CREATE (t:test {prop: 567627}); +---- ok +-STATEMENT CREATE (t:test {prop: 679042}); +---- ok +-STATEMENT CREATE (t:test {prop: 355628}); +---- ok +-STATEMENT CREATE (t:test {prop: 17424}); +---- ok +-STATEMENT CREATE (t:test {prop: 469464}); +---- ok +-STATEMENT CREATE (t:test {prop: 650575}); +---- ok +-STATEMENT CREATE (t:test {prop: 198300}); +---- ok +-STATEMENT CREATE (t:test {prop: 324169}); +---- ok +-STATEMENT CREATE (t:test {prop: 246960}); +---- ok +-STATEMENT CREATE (t:test {prop: 772532}); +---- ok +-STATEMENT CREATE (t:test {prop: 748157}); +---- ok +-STATEMENT CREATE (t:test {prop: 993141}); +---- ok +-STATEMENT CREATE (t:test {prop: 121673}); +---- ok +-STATEMENT CREATE (t:test {prop: 686879}); +---- ok +-STATEMENT CREATE (t:test {prop: 489749}); +---- ok +-STATEMENT CREATE (t:test {prop: 591525}); +---- ok +-STATEMENT CREATE (t:test {prop: 845015}); +---- ok +-STATEMENT CREATE (t:test {prop: 819107}); +---- ok +-STATEMENT CREATE (t:test {prop: 771744}); +---- ok +-STATEMENT CREATE (t:test {prop: 812235}); +---- ok +-STATEMENT CREATE (t:test {prop: 866236}); +---- ok +-STATEMENT CREATE (t:test {prop: 972975}); +---- ok +-STATEMENT CREATE (t:test {prop: 166361}); +---- ok +-STATEMENT CREATE (t:test {prop: 829853}); +---- ok +-STATEMENT CREATE (t:test {prop: 789734}); +---- ok +-STATEMENT CREATE (t:test {prop: 112804}); +---- ok +-STATEMENT CREATE (t:test {prop: 599664}); +---- ok +-STATEMENT CREATE (t:test {prop: 640538}); +---- ok +-STATEMENT CREATE (t:test {prop: 211324}); +---- ok +-STATEMENT CREATE (t:test {prop: 941296}); +---- ok +-STATEMENT CREATE (t:test {prop: 435602}); +---- ok +-STATEMENT CREATE (t:test {prop: 486000}); +---- ok +-STATEMENT CREATE (t:test {prop: 501439}); +---- ok +-STATEMENT CREATE (t:test {prop: 194107}); +---- ok +-STATEMENT CREATE (t:test {prop: 383504}); +---- ok +-STATEMENT CREATE (t:test {prop: 19506}); +---- ok +-STATEMENT CREATE (t:test {prop: 547946}); +---- ok +-STATEMENT CREATE (t:test {prop: 455600}); +---- ok +-STATEMENT CREATE (t:test {prop: 931509}); +---- ok +-STATEMENT CREATE (t:test {prop: 391575}); +---- ok +-STATEMENT CREATE (t:test {prop: 578375}); +---- ok +-STATEMENT CREATE (t:test {prop: 557492}); +---- ok +-STATEMENT CREATE (t:test {prop: 977581}); +---- ok +-STATEMENT CREATE (t:test {prop: 429839}); +---- ok +-STATEMENT CREATE (t:test {prop: 980848}); +---- ok +-STATEMENT CREATE (t:test {prop: 356445}); +---- ok +-STATEMENT CREATE (t:test {prop: 337133}); +---- ok +-STATEMENT CREATE (t:test {prop: 517002}); +---- ok +-STATEMENT CREATE (t:test {prop: 724985}); +---- ok +-STATEMENT CREATE (t:test {prop: 793820}); +---- ok +-STATEMENT CREATE (t:test {prop: 524737}); +---- ok +-STATEMENT CREATE (t:test {prop: 827044}); +---- ok +-STATEMENT CREATE (t:test {prop: 701826}); +---- ok +-STATEMENT CREATE (t:test {prop: 132518}); +---- ok +-STATEMENT CREATE (t:test {prop: 85905}); +---- ok +-STATEMENT CREATE (t:test {prop: 311054}); +---- ok +-STATEMENT CREATE (t:test {prop: 291071}); +---- ok +-STATEMENT CREATE (t:test {prop: 104854}); +---- ok +-STATEMENT CREATE (t:test {prop: 110113}); +---- ok +-STATEMENT CREATE (t:test {prop: 771654}); +---- ok +-STATEMENT CREATE (t:test {prop: 289375}); +---- ok +-STATEMENT CREATE (t:test {prop: 746227}); +---- ok +-STATEMENT CREATE (t:test {prop: 586416}); +---- ok +-STATEMENT CREATE (t:test {prop: 407825}); +---- ok +-STATEMENT CREATE (t:test {prop: 713787}); +---- ok +-STATEMENT CREATE (t:test {prop: 180552}); +---- ok +-STATEMENT CREATE (t:test {prop: 717894}); +---- ok +-STATEMENT CREATE (t:test {prop: 730498}); +---- ok +-STATEMENT CREATE (t:test {prop: 804058}); +---- ok +-STATEMENT CREATE (t:test {prop: 940974}); +---- ok +-STATEMENT CREATE (t:test {prop: 434884}); +---- ok +-STATEMENT CREATE (t:test {prop: 716034}); +---- ok +-STATEMENT CREATE (t:test {prop: 955068}); +---- ok +-STATEMENT CREATE (t:test {prop: 265807}); +---- ok +-STATEMENT CREATE (t:test {prop: 748081}); +---- ok +-STATEMENT CREATE (t:test {prop: 156857}); +---- ok +-STATEMENT CREATE (t:test {prop: 347609}); +---- ok +-STATEMENT CREATE (t:test {prop: 869828}); +---- ok +-STATEMENT CREATE (t:test {prop: 121605}); +---- ok +-STATEMENT CREATE (t:test {prop: 127874}); +---- ok +-STATEMENT CREATE (t:test {prop: 560095}); +---- ok +-STATEMENT CREATE (t:test {prop: 385130}); +---- ok +-STATEMENT CREATE (t:test {prop: 714486}); +---- ok +-STATEMENT CREATE (t:test {prop: 727299}); +---- ok +-STATEMENT CREATE (t:test {prop: 408123}); +---- ok +-STATEMENT CREATE (t:test {prop: 421586}); +---- ok +-STATEMENT CREATE (t:test {prop: 217245}); +---- ok +-STATEMENT CREATE (t:test {prop: 82166}); +---- ok +-STATEMENT CREATE (t:test {prop: 550334}); +---- ok +-STATEMENT CREATE (t:test {prop: 728788}); +---- ok +-STATEMENT CREATE (t:test {prop: 132645}); +---- ok +-STATEMENT CREATE (t:test {prop: 328742}); +---- ok +-STATEMENT CREATE (t:test {prop: 428762}); +---- ok +-STATEMENT CREATE (t:test {prop: 624362}); +---- ok +-STATEMENT CREATE (t:test {prop: 110164}); +---- ok +-STATEMENT CREATE (t:test {prop: 629919}); +---- ok +-STATEMENT CREATE (t:test {prop: 834101}); +---- ok +-STATEMENT CREATE (t:test {prop: 983537}); +---- ok +-STATEMENT CREATE (t:test {prop: 549207}); +---- ok +-STATEMENT CREATE (t:test {prop: 971479}); +---- ok +-STATEMENT CREATE (t:test {prop: 826875}); +---- ok +-STATEMENT CREATE (t:test {prop: 705643}); +---- ok +-STATEMENT CREATE (t:test {prop: 426204}); +---- ok +-STATEMENT CREATE (t:test {prop: 360869}); +---- ok +-STATEMENT CREATE (t:test {prop: 552905}); +---- ok +-STATEMENT CREATE (t:test {prop: 400929}); +---- ok +-STATEMENT CREATE (t:test {prop: 687508}); +---- ok +-STATEMENT CREATE (t:test {prop: 513341}); +---- ok +-STATEMENT CREATE (t:test {prop: 712261}); +---- ok +-STATEMENT CREATE (t:test {prop: 987782}); +---- ok +-STATEMENT CREATE (t:test {prop: 407959}); +---- ok +-STATEMENT CREATE (t:test {prop: 962656}); +---- ok +-STATEMENT CREATE (t:test {prop: 994559}); +---- ok +-STATEMENT CREATE (t:test {prop: 722163}); +---- ok +-STATEMENT CREATE (t:test {prop: 250086}); +---- ok +-STATEMENT CREATE (t:test {prop: 174915}); +---- ok +-STATEMENT CREATE (t:test {prop: 171764}); +---- ok +-STATEMENT CREATE (t:test {prop: 36409}); +---- ok +-STATEMENT CREATE (t:test {prop: 428614}); +---- ok +-STATEMENT CREATE (t:test {prop: 327198}); +---- ok +-STATEMENT CREATE (t:test {prop: 294512}); +---- ok +-STATEMENT CREATE (t:test {prop: 330242}); +---- ok +-STATEMENT CREATE (t:test {prop: 799935}); +---- ok +-STATEMENT CREATE (t:test {prop: 749197}); +---- ok +-STATEMENT CREATE (t:test {prop: 550057}); +---- ok +-STATEMENT CREATE (t:test {prop: 90198}); +---- ok +-STATEMENT CREATE (t:test {prop: 613702}); +---- ok +-STATEMENT CREATE (t:test {prop: 670792}); +---- ok +-STATEMENT CREATE (t:test {prop: 410737}); +---- ok +-STATEMENT CREATE (t:test {prop: 326979}); +---- ok +-STATEMENT CREATE (t:test {prop: 215754}); +---- ok +-STATEMENT CREATE (t:test {prop: 751301}); +---- ok +-STATEMENT CREATE (t:test {prop: 610843}); +---- ok +-STATEMENT CREATE (t:test {prop: 498389}); +---- ok +-STATEMENT CREATE (t:test {prop: 67921}); +---- ok +-STATEMENT CREATE (t:test {prop: 339742}); +---- ok +-STATEMENT CREATE (t:test {prop: 127931}); +---- ok +-STATEMENT CREATE (t:test {prop: 868773}); +---- ok +-STATEMENT CREATE (t:test {prop: 443019}); +---- ok +-STATEMENT CREATE (t:test {prop: 446679}); +---- ok +-STATEMENT CREATE (t:test {prop: 609536}); +---- ok +-STATEMENT CREATE (t:test {prop: 904495}); +---- ok +-STATEMENT CREATE (t:test {prop: 794800}); +---- ok +-STATEMENT CREATE (t:test {prop: 620710}); +---- ok +-STATEMENT CREATE (t:test {prop: 4976}); +---- ok +-STATEMENT CREATE (t:test {prop: 778027}); +---- ok +-STATEMENT CREATE (t:test {prop: 813375}); +---- ok +-STATEMENT CREATE (t:test {prop: 320927}); +---- ok +-STATEMENT CREATE (t:test {prop: 373069}); +---- ok +-STATEMENT CREATE (t:test {prop: 884173}); +---- ok +-STATEMENT CREATE (t:test {prop: 821376}); +---- ok +-STATEMENT CREATE (t:test {prop: 547595}); +---- ok +-STATEMENT CREATE (t:test {prop: 479977}); +---- ok +-STATEMENT CREATE (t:test {prop: 973379}); +---- ok +-STATEMENT CREATE (t:test {prop: 890208}); +---- ok +-STATEMENT CREATE (t:test {prop: 483137}); +---- ok +-STATEMENT CREATE (t:test {prop: 588787}); +---- ok +-STATEMENT CREATE (t:test {prop: 936213}); +---- ok +-STATEMENT CREATE (t:test {prop: 22010}); +---- ok +-STATEMENT CREATE (t:test {prop: 39197}); +---- ok +-STATEMENT CREATE (t:test {prop: 850850}); +---- ok +-STATEMENT CREATE (t:test {prop: 535287}); +---- ok +-STATEMENT CREATE (t:test {prop: 555021}); +---- ok +-STATEMENT CREATE (t:test {prop: 951916}); +---- ok +-STATEMENT CREATE (t:test {prop: 106394}); +---- ok +-STATEMENT CREATE (t:test {prop: 761243}); +---- ok +-STATEMENT CREATE (t:test {prop: 351659}); +---- ok +-STATEMENT CREATE (t:test {prop: 505256}); +---- ok +-STATEMENT CREATE (t:test {prop: 741712}); +---- ok +-STATEMENT CREATE (t:test {prop: 157566}); +---- ok +-STATEMENT CREATE (t:test {prop: 252224}); +---- ok +-STATEMENT CREATE (t:test {prop: 788989}); +---- ok +-STATEMENT CREATE (t:test {prop: 761389}); +---- ok +-STATEMENT CREATE (t:test {prop: 636439}); +---- ok +-STATEMENT CREATE (t:test {prop: 767538}); +---- ok +-STATEMENT CREATE (t:test {prop: 739965}); +---- ok +-STATEMENT CREATE (t:test {prop: 221936}); +---- ok +-STATEMENT CREATE (t:test {prop: 242378}); +---- ok +-STATEMENT CREATE (t:test {prop: 129287}); +---- ok +-STATEMENT CREATE (t:test {prop: 994897}); +---- ok +-STATEMENT CREATE (t:test {prop: 131106}); +---- ok +-STATEMENT CREATE (t:test {prop: 551630}); +---- ok +-STATEMENT CREATE (t:test {prop: 442880}); +---- ok +-STATEMENT CREATE (t:test {prop: 114200}); +---- ok +-STATEMENT CREATE (t:test {prop: 965707}); +---- ok +-STATEMENT CREATE (t:test {prop: 425858}); +---- ok +-STATEMENT CREATE (t:test {prop: 696843}); +---- ok +-STATEMENT CREATE (t:test {prop: 652583}); +---- ok +-STATEMENT CREATE (t:test {prop: 530391}); +---- ok +-STATEMENT CREATE (t:test {prop: 874166}); +---- ok +-STATEMENT CREATE (t:test {prop: 267998}); +---- ok +-STATEMENT CREATE (t:test {prop: 837705}); +---- ok +-STATEMENT CREATE (t:test {prop: 483087}); +---- ok +-STATEMENT CREATE (t:test {prop: 198517}); +---- ok +-STATEMENT CREATE (t:test {prop: 497607}); +---- ok +-STATEMENT CREATE (t:test {prop: 410322}); +---- ok +-STATEMENT CREATE (t:test {prop: 640207}); +---- ok +-STATEMENT CREATE (t:test {prop: 643556}); +---- ok +-STATEMENT CREATE (t:test {prop: 642518}); +---- ok +-STATEMENT CREATE (t:test {prop: 884933}); +---- ok +-STATEMENT CREATE (t:test {prop: 42929}); +---- ok +-STATEMENT CREATE (t:test {prop: 590904}); +---- ok +-STATEMENT CREATE (t:test {prop: 94068}); +---- ok +-STATEMENT CREATE (t:test {prop: 170479}); +---- ok +-STATEMENT CREATE (t:test {prop: 914301}); +---- ok +-STATEMENT CREATE (t:test {prop: 636779}); +---- ok +-STATEMENT CREATE (t:test {prop: 738868}); +---- ok +-STATEMENT CREATE (t:test {prop: 394584}); +---- ok +-STATEMENT CREATE (t:test {prop: 454429}); +---- ok +-STATEMENT CREATE (t:test {prop: 183829}); +---- ok +-STATEMENT CREATE (t:test {prop: 60345}); +---- ok +-STATEMENT CREATE (t:test {prop: 260579}); +---- ok +-STATEMENT CREATE (t:test {prop: 614668}); +---- ok +-STATEMENT CREATE (t:test {prop: 893942}); +---- ok +-STATEMENT CREATE (t:test {prop: 625507}); +---- ok +-STATEMENT CREATE (t:test {prop: 226030}); +---- ok +-STATEMENT CREATE (t:test {prop: 505258}); +---- ok +-STATEMENT CREATE (t:test {prop: 953442}); +---- ok +-STATEMENT CREATE (t:test {prop: 273428}); +---- ok +-STATEMENT CREATE (t:test {prop: 173403}); +---- ok +-STATEMENT CREATE (t:test {prop: 859676}); +---- ok +-STATEMENT CREATE (t:test {prop: 810103}); +---- ok +-STATEMENT CREATE (t:test {prop: 529664}); +---- ok +-STATEMENT CREATE (t:test {prop: 718174}); +---- ok +-STATEMENT CREATE (t:test {prop: 625482}); +---- ok +-STATEMENT CREATE (t:test {prop: 942386}); +---- ok +-STATEMENT CREATE (t:test {prop: 742769}); +---- ok +-STATEMENT CREATE (t:test {prop: 177011}); +---- ok +-STATEMENT CREATE (t:test {prop: 27420}); +---- ok +-STATEMENT CREATE (t:test {prop: 351700}); +---- ok +-STATEMENT CREATE (t:test {prop: 927495}); +---- ok +-STATEMENT CREATE (t:test {prop: 686923}); +---- ok +-STATEMENT CREATE (t:test {prop: 523544}); +---- ok +-STATEMENT CREATE (t:test {prop: 131809}); +---- ok +-STATEMENT CREATE (t:test {prop: 503131}); +---- ok +-STATEMENT CREATE (t:test {prop: 610183}); +---- ok +-STATEMENT CREATE (t:test {prop: 634606}); +---- ok +-STATEMENT CREATE (t:test {prop: 116137}); +---- ok +-STATEMENT CREATE (t:test {prop: 674526}); +---- ok +-STATEMENT CREATE (t:test {prop: 409778}); +---- ok +-STATEMENT CREATE (t:test {prop: 12919}); +---- ok +-STATEMENT CREATE (t:test {prop: 306672}); +---- ok +-STATEMENT CREATE (t:test {prop: 813566}); +---- ok +-STATEMENT CREATE (t:test {prop: 129887}); +---- ok +-STATEMENT CREATE (t:test {prop: 401769}); +---- ok +-STATEMENT CREATE (t:test {prop: 123536}); +---- ok +-STATEMENT CREATE (t:test {prop: 957796}); +---- ok +-STATEMENT CREATE (t:test {prop: 76640}); +---- ok +-STATEMENT CREATE (t:test {prop: 667039}); +---- ok +-STATEMENT CREATE (t:test {prop: 850759}); +---- ok +-STATEMENT CREATE (t:test {prop: 759065}); +---- ok +-STATEMENT CREATE (t:test {prop: 696469}); +---- ok +-STATEMENT CREATE (t:test {prop: 994528}); +---- ok +-STATEMENT CREATE (t:test {prop: 486892}); +---- ok +-STATEMENT CREATE (t:test {prop: 424384}); +---- ok +-STATEMENT CREATE (t:test {prop: 698811}); +---- ok +-STATEMENT CREATE (t:test {prop: 665362}); +---- ok +-STATEMENT CREATE (t:test {prop: 572692}); +---- ok +-STATEMENT CREATE (t:test {prop: 366034}); +---- ok +-STATEMENT CREATE (t:test {prop: 987250}); +---- ok +-STATEMENT CREATE (t:test {prop: 587341}); +---- ok +-STATEMENT CREATE (t:test {prop: 373248}); +---- ok +-STATEMENT CREATE (t:test {prop: 127349}); +---- ok +-STATEMENT CREATE (t:test {prop: 735896}); +---- ok +-STATEMENT CREATE (t:test {prop: 19453}); +---- ok +-STATEMENT CREATE (t:test {prop: 954508}); +---- ok +-STATEMENT CREATE (t:test {prop: 984759}); +---- ok +-STATEMENT CREATE (t:test {prop: 80629}); +---- ok +-STATEMENT CREATE (t:test {prop: 921418}); +---- ok +-STATEMENT CREATE (t:test {prop: 497528}); +---- ok +-STATEMENT CREATE (t:test {prop: 885827}); +---- ok +-STATEMENT CREATE (t:test {prop: 179011}); +---- ok +-STATEMENT CREATE (t:test {prop: 156628}); +---- ok +-STATEMENT CREATE (t:test {prop: 838009}); +---- ok +-STATEMENT CREATE (t:test {prop: 829130}); +---- ok +-STATEMENT CREATE (t:test {prop: 770077}); +---- ok +-STATEMENT CREATE (t:test {prop: 153591}); +---- ok +-STATEMENT CREATE (t:test {prop: 558370}); +---- ok +-STATEMENT CREATE (t:test {prop: 209714}); +---- ok +-STATEMENT CREATE (t:test {prop: 780411}); +---- ok +-STATEMENT CREATE (t:test {prop: 48463}); +---- ok +-STATEMENT CREATE (t:test {prop: 483140}); +---- ok +-STATEMENT CREATE (t:test {prop: 533608}); +---- ok +-STATEMENT CREATE (t:test {prop: 914707}); +---- ok +-STATEMENT CREATE (t:test {prop: 523321}); +---- ok +-STATEMENT CREATE (t:test {prop: 961400}); +---- ok +-STATEMENT CREATE (t:test {prop: 962533}); +---- ok +-STATEMENT CREATE (t:test {prop: 698658}); +---- ok +-STATEMENT CREATE (t:test {prop: 991059}); +---- ok +-STATEMENT CREATE (t:test {prop: 969487}); +---- ok +-STATEMENT CREATE (t:test {prop: 755501}); +---- ok +-STATEMENT CREATE (t:test {prop: 164702}); +---- ok +-STATEMENT CREATE (t:test {prop: 150604}); +---- ok +-STATEMENT CREATE (t:test {prop: 830188}); +---- ok +-STATEMENT CREATE (t:test {prop: 359581}); +---- ok +-STATEMENT CREATE (t:test {prop: 152490}); +---- ok +-STATEMENT CREATE (t:test {prop: 518962}); +---- ok +-STATEMENT CREATE (t:test {prop: 900138}); +---- ok +-STATEMENT CREATE (t:test {prop: 516671}); +---- ok +-STATEMENT CREATE (t:test {prop: 948924}); +---- ok +-STATEMENT CREATE (t:test {prop: 431278}); +---- ok +-STATEMENT CREATE (t:test {prop: 532302}); +---- ok +-STATEMENT CREATE (t:test {prop: 606789}); +---- ok +-STATEMENT CREATE (t:test {prop: 619533}); +---- ok +-STATEMENT CREATE (t:test {prop: 899321}); +---- ok +-STATEMENT CREATE (t:test {prop: 665239}); +---- ok +-STATEMENT CREATE (t:test {prop: 409944}); +---- ok +-STATEMENT CREATE (t:test {prop: 728339}); +---- ok +-STATEMENT CREATE (t:test {prop: 99214}); +---- ok +-STATEMENT CREATE (t:test {prop: 8452}); +---- ok +-STATEMENT CREATE (t:test {prop: 939692}); +---- ok +-STATEMENT CREATE (t:test {prop: 814747}); +---- ok +-STATEMENT CREATE (t:test {prop: 408421}); +---- ok +-STATEMENT CREATE (t:test {prop: 286761}); +---- ok +-STATEMENT CREATE (t:test {prop: 743584}); +---- ok +-STATEMENT CREATE (t:test {prop: 747020}); +---- ok +-STATEMENT CREATE (t:test {prop: 745833}); +---- ok +-STATEMENT CREATE (t:test {prop: 572754}); +---- ok +-STATEMENT CREATE (t:test {prop: 829176}); +---- ok +-STATEMENT CREATE (t:test {prop: 70889}); +---- ok +-STATEMENT CREATE (t:test {prop: 783213}); +---- ok +-STATEMENT CREATE (t:test {prop: 369543}); +---- ok +-STATEMENT CREATE (t:test {prop: 153947}); +---- ok +-STATEMENT CREATE (t:test {prop: 979728}); +---- ok +-STATEMENT CREATE (t:test {prop: 658038}); +---- ok +-STATEMENT CREATE (t:test {prop: 873031}); +---- ok +-STATEMENT CREATE (t:test {prop: 230462}); +---- ok +-STATEMENT CREATE (t:test {prop: 644638}); +---- ok +-STATEMENT CREATE (t:test {prop: 381930}); +---- ok +-STATEMENT CREATE (t:test {prop: 448815}); +---- ok +-STATEMENT CREATE (t:test {prop: 128559}); +---- ok +-STATEMENT CREATE (t:test {prop: 606420}); +---- ok +-STATEMENT CREATE (t:test {prop: 325763}); +---- ok +-STATEMENT CREATE (t:test {prop: 696039}); +---- ok +-STATEMENT CREATE (t:test {prop: 950020}); +---- ok +-STATEMENT CREATE (t:test {prop: 779742}); +---- ok +-STATEMENT CREATE (t:test {prop: 91797}); +---- ok +-STATEMENT CREATE (t:test {prop: 74565}); +---- ok +-STATEMENT CREATE (t:test {prop: 997222}); +---- ok +-STATEMENT CREATE (t:test {prop: 691990}); +---- ok +-STATEMENT CREATE (t:test {prop: 364892}); +---- ok +-STATEMENT CREATE (t:test {prop: 499097}); +---- ok +-STATEMENT CREATE (t:test {prop: 953126}); +---- ok +-STATEMENT CREATE (t:test {prop: 302648}); +---- ok +-STATEMENT CREATE (t:test {prop: 800774}); +---- ok +-STATEMENT CREATE (t:test {prop: 513801}); +---- ok +-STATEMENT CREATE (t:test {prop: 231352}); +---- ok +-STATEMENT CREATE (t:test {prop: 770724}); +---- ok +-STATEMENT CREATE (t:test {prop: 796}); +---- ok +-STATEMENT CREATE (t:test {prop: 78128}); +---- ok +-STATEMENT CREATE (t:test {prop: 269695}); +---- ok +-STATEMENT CREATE (t:test {prop: 264841}); +---- ok +-STATEMENT CREATE (t:test {prop: 342607}); +---- ok +-STATEMENT CREATE (t:test {prop: 710443}); +---- ok +-STATEMENT CREATE (t:test {prop: 803208}); +---- ok +-STATEMENT CREATE (t:test {prop: 232967}); +---- ok +-STATEMENT CREATE (t:test {prop: 858875}); +---- ok +-STATEMENT CREATE (t:test {prop: 445270}); +---- ok +-STATEMENT CREATE (t:test {prop: 631300}); +---- ok +-STATEMENT CREATE (t:test {prop: 197427}); +---- ok +-STATEMENT CREATE (t:test {prop: 637311}); +---- ok +-STATEMENT CREATE (t:test {prop: 323167}); +---- ok +-STATEMENT CREATE (t:test {prop: 358187}); +---- ok +-STATEMENT CREATE (t:test {prop: 926561}); +---- ok +-STATEMENT CREATE (t:test {prop: 541136}); +---- ok +-STATEMENT CREATE (t:test {prop: 139293}); +---- ok +-STATEMENT CREATE (t:test {prop: 726803}); +---- ok +-STATEMENT CREATE (t:test {prop: 606235}); +---- ok +-STATEMENT CREATE (t:test {prop: 880416}); +---- ok +-STATEMENT CREATE (t:test {prop: 129602}); +---- ok +-STATEMENT CREATE (t:test {prop: 658357}); +---- ok +-STATEMENT CREATE (t:test {prop: 980132}); +---- ok +-STATEMENT CREATE (t:test {prop: 453753}); +---- ok +-STATEMENT CREATE (t:test {prop: 170199}); +---- ok +-STATEMENT CREATE (t:test {prop: 719389}); +---- ok +-STATEMENT CREATE (t:test {prop: 111793}); +---- ok +-STATEMENT CREATE (t:test {prop: 466644}); +---- ok +-STATEMENT CREATE (t:test {prop: 622451}); +---- ok +-STATEMENT CREATE (t:test {prop: 3192}); +---- ok +-STATEMENT CREATE (t:test {prop: 106313}); +---- ok +-STATEMENT CREATE (t:test {prop: 509062}); +---- ok +-STATEMENT CREATE (t:test {prop: 981620}); +---- ok +-STATEMENT CREATE (t:test {prop: 700076}); +---- ok +-STATEMENT CREATE (t:test {prop: 565655}); +---- ok +-STATEMENT CREATE (t:test {prop: 329106}); +---- ok +-STATEMENT CREATE (t:test {prop: 433230}); +---- ok +-STATEMENT CREATE (t:test {prop: 206482}); +---- ok +-STATEMENT CREATE (t:test {prop: 198629}); +---- ok +-STATEMENT CREATE (t:test {prop: 386941}); +---- ok +-STATEMENT CREATE (t:test {prop: 647476}); +---- ok +-STATEMENT CREATE (t:test {prop: 955598}); +---- ok +-STATEMENT CREATE (t:test {prop: 696213}); +---- ok +-STATEMENT CREATE (t:test {prop: 870167}); +---- ok +-STATEMENT CREATE (t:test {prop: 703352}); +---- ok +-STATEMENT CREATE (t:test {prop: 924564}); +---- ok +-STATEMENT CREATE (t:test {prop: 110812}); +---- ok +-STATEMENT CREATE (t:test {prop: 735357}); +---- ok +-STATEMENT CREATE (t:test {prop: 951362}); +---- ok +-STATEMENT CREATE (t:test {prop: 276110}); +---- ok +-STATEMENT CREATE (t:test {prop: 639026}); +---- ok +-STATEMENT CREATE (t:test {prop: 772150}); +---- ok +-STATEMENT CREATE (t:test {prop: 766660}); +---- ok +-STATEMENT CREATE (t:test {prop: 463051}); +---- ok +-STATEMENT CREATE (t:test {prop: 493918}); +---- ok +-STATEMENT CREATE (t:test {prop: 997734}); +---- ok +-STATEMENT CREATE (t:test {prop: 304897}); +---- ok +-STATEMENT CREATE (t:test {prop: 139012}); +---- ok +-STATEMENT CREATE (t:test {prop: 903504}); +---- ok +-STATEMENT CREATE (t:test {prop: 931932}); +---- ok +-STATEMENT CREATE (t:test {prop: 49489}); +---- ok +-STATEMENT CREATE (t:test {prop: 220356}); +---- ok +-STATEMENT CREATE (t:test {prop: 480077}); +---- ok +-STATEMENT CREATE (t:test {prop: 986607}); +---- ok +-STATEMENT CREATE (t:test {prop: 782083}); +---- ok +-STATEMENT CREATE (t:test {prop: 565025}); +---- ok +-STATEMENT CREATE (t:test {prop: 214796}); +---- ok +-STATEMENT CREATE (t:test {prop: 850853}); +---- ok +-STATEMENT CREATE (t:test {prop: 441260}); +---- ok +-STATEMENT CREATE (t:test {prop: 511241}); +---- ok +-STATEMENT CREATE (t:test {prop: 850658}); +---- ok +-STATEMENT CREATE (t:test {prop: 869060}); +---- ok +-STATEMENT CREATE (t:test {prop: 659171}); +---- ok +-STATEMENT CREATE (t:test {prop: 292907}); +---- ok +-STATEMENT CREATE (t:test {prop: 50027}); +---- ok +-STATEMENT CREATE (t:test {prop: 208561}); +---- ok +-STATEMENT CREATE (t:test {prop: 365742}); +---- ok +-STATEMENT CREATE (t:test {prop: 413857}); +---- ok +-STATEMENT CREATE (t:test {prop: 262739}); +---- ok +-STATEMENT CREATE (t:test {prop: 688237}); +---- ok +-STATEMENT CREATE (t:test {prop: 846357}); +---- ok +-STATEMENT CREATE (t:test {prop: 319116}); +---- ok +-STATEMENT CREATE (t:test {prop: 314012}); +---- ok +-STATEMENT CREATE (t:test {prop: 667021}); +---- ok +-STATEMENT CREATE (t:test {prop: 892365}); +---- ok +-STATEMENT CREATE (t:test {prop: 305078}); +---- ok +-STATEMENT CREATE (t:test {prop: 156225}); +---- ok +-STATEMENT CREATE (t:test {prop: 316855}); +---- ok +-STATEMENT CREATE (t:test {prop: 534921}); +---- ok +-STATEMENT CREATE (t:test {prop: 578959}); +---- ok +-STATEMENT CREATE (t:test {prop: 233970}); +---- ok +-STATEMENT CREATE (t:test {prop: 8029}); +---- ok +-STATEMENT CREATE (t:test {prop: 756289}); +---- ok +-STATEMENT CREATE (t:test {prop: 966425}); +---- ok +-STATEMENT CREATE (t:test {prop: 840447}); +---- ok +-STATEMENT CREATE (t:test {prop: 728357}); +---- ok +-STATEMENT CREATE (t:test {prop: 721598}); +---- ok +-STATEMENT CREATE (t:test {prop: 738724}); +---- ok +-STATEMENT CREATE (t:test {prop: 572790}); +---- ok +-STATEMENT CREATE (t:test {prop: 801931}); +---- ok +-STATEMENT CREATE (t:test {prop: 635109}); +---- ok +-STATEMENT CREATE (t:test {prop: 160035}); +---- ok +-STATEMENT CREATE (t:test {prop: 551154}); +---- ok +-STATEMENT CREATE (t:test {prop: 391456}); +---- ok +-STATEMENT CREATE (t:test {prop: 3789}); +---- ok +-STATEMENT CREATE (t:test {prop: 668239}); +---- ok +-STATEMENT CREATE (t:test {prop: 584345}); +---- ok +-STATEMENT CREATE (t:test {prop: 746072}); +---- ok +-STATEMENT CREATE (t:test {prop: 569798}); +---- ok +-STATEMENT CREATE (t:test {prop: 623587}); +---- ok +-STATEMENT CREATE (t:test {prop: 508593}); +---- ok +-STATEMENT CREATE (t:test {prop: 933443}); +---- ok +-STATEMENT CREATE (t:test {prop: 11445}); +---- ok +-STATEMENT CREATE (t:test {prop: 371217}); +---- ok +-STATEMENT CREATE (t:test {prop: 289465}); +---- ok +-STATEMENT CREATE (t:test {prop: 658586}); +---- ok +-STATEMENT CREATE (t:test {prop: 372267}); +---- ok +-STATEMENT CREATE (t:test {prop: 276906}); +---- ok +-STATEMENT CREATE (t:test {prop: 848763}); +---- ok +-STATEMENT CREATE (t:test {prop: 97629}); +---- ok +-STATEMENT CREATE (t:test {prop: 115490}); +---- ok +-STATEMENT CREATE (t:test {prop: 539067}); +---- ok +-STATEMENT CREATE (t:test {prop: 978171}); +---- ok +-STATEMENT CREATE (t:test {prop: 679821}); +---- ok +-STATEMENT CREATE (t:test {prop: 103794}); +---- ok +-STATEMENT CREATE (t:test {prop: 462516}); +---- ok +-STATEMENT CREATE (t:test {prop: 236561}); +---- ok +-STATEMENT CREATE (t:test {prop: 655434}); +---- ok +-STATEMENT CREATE (t:test {prop: 216269}); +---- ok +-STATEMENT CREATE (t:test {prop: 195447}); +---- ok +-STATEMENT CREATE (t:test {prop: 524245}); +---- ok +-STATEMENT CREATE (t:test {prop: 174734}); +---- ok +-STATEMENT CREATE (t:test {prop: 930858}); +---- ok +-STATEMENT CREATE (t:test {prop: 784987}); +---- ok +-STATEMENT CREATE (t:test {prop: 243295}); +---- ok +-STATEMENT CREATE (t:test {prop: 329442}); +---- ok +-STATEMENT CREATE (t:test {prop: 734498}); +---- ok +-STATEMENT CREATE (t:test {prop: 750269}); +---- ok +-STATEMENT CREATE (t:test {prop: 693270}); +---- ok +-STATEMENT CREATE (t:test {prop: 165948}); +---- ok +-STATEMENT CREATE (t:test {prop: 903552}); +---- ok +-STATEMENT CREATE (t:test {prop: 878504}); +---- ok +-STATEMENT CREATE (t:test {prop: 257854}); +---- ok +-STATEMENT CREATE (t:test {prop: 711459}); +---- ok +-STATEMENT CREATE (t:test {prop: 949778}); +---- ok +-STATEMENT CREATE (t:test {prop: 766834}); +---- ok +-STATEMENT CREATE (t:test {prop: 438792}); +---- ok +-STATEMENT CREATE (t:test {prop: 191119}); +---- ok +-STATEMENT CREATE (t:test {prop: 589222}); +---- ok +-STATEMENT CREATE (t:test {prop: 800927}); +---- ok +-STATEMENT CREATE (t:test {prop: 598447}); +---- ok +-STATEMENT CREATE (t:test {prop: 649828}); +---- ok +-STATEMENT CREATE (t:test {prop: 937593}); +---- ok +-STATEMENT CREATE (t:test {prop: 786427}); +---- ok +-STATEMENT CREATE (t:test {prop: 126617}); +---- ok +-STATEMENT CREATE (t:test {prop: 569992}); +---- ok +-STATEMENT CREATE (t:test {prop: 577794}); +---- ok +-STATEMENT CREATE (t:test {prop: 882578}); +---- ok +-STATEMENT CREATE (t:test {prop: 268515}); +---- ok +-STATEMENT CREATE (t:test {prop: 652230}); +---- ok +-STATEMENT CREATE (t:test {prop: 437965}); +---- ok +-STATEMENT CREATE (t:test {prop: 156207}); +---- ok +-STATEMENT CREATE (t:test {prop: 616198}); +---- ok +-STATEMENT CREATE (t:test {prop: 258296}); +---- ok +-STATEMENT CREATE (t:test {prop: 785379}); +---- ok +-STATEMENT CREATE (t:test {prop: 638068}); +---- ok +-STATEMENT CREATE (t:test {prop: 172542}); +---- ok +-STATEMENT CREATE (t:test {prop: 562216}); +---- ok +-STATEMENT CREATE (t:test {prop: 268246}); +---- ok +-STATEMENT CREATE (t:test {prop: 695080}); +---- ok +-STATEMENT CREATE (t:test {prop: 339600}); +---- ok +-STATEMENT CREATE (t:test {prop: 406426}); +---- ok +-STATEMENT CREATE (t:test {prop: 493337}); +---- ok +-STATEMENT CREATE (t:test {prop: 503209}); +---- ok +-STATEMENT CREATE (t:test {prop: 292027}); +---- ok +-STATEMENT CREATE (t:test {prop: 398067}); +---- ok +-STATEMENT CREATE (t:test {prop: 377136}); +---- ok +-STATEMENT CREATE (t:test {prop: 578879}); +---- ok +-STATEMENT CREATE (t:test {prop: 856467}); +---- ok +-STATEMENT CREATE (t:test {prop: 565648}); +---- ok +-STATEMENT CREATE (t:test {prop: 486885}); +---- ok +-STATEMENT CREATE (t:test {prop: 329951}); +---- ok +-STATEMENT CREATE (t:test {prop: 840550}); +---- ok +-STATEMENT CREATE (t:test {prop: 746172}); +---- ok +-STATEMENT CREATE (t:test {prop: 378526}); +---- ok +-STATEMENT CREATE (t:test {prop: 756057}); +---- ok +-STATEMENT CREATE (t:test {prop: 927917}); +---- ok +-STATEMENT CREATE (t:test {prop: 999916}); +---- ok +-STATEMENT CREATE (t:test {prop: 76668}); +---- ok +-STATEMENT CREATE (t:test {prop: 896086}); +---- ok +-STATEMENT CREATE (t:test {prop: 140004}); +---- ok +-STATEMENT CREATE (t:test {prop: 889100}); +---- ok +-STATEMENT CREATE (t:test {prop: 688990}); +---- ok +-STATEMENT CREATE (t:test {prop: 513144}); +---- ok +-STATEMENT CREATE (t:test {prop: 958831}); +---- ok +-STATEMENT CREATE (t:test {prop: 924702}); +---- ok +-STATEMENT CREATE (t:test {prop: 489701}); +---- ok +-STATEMENT CREATE (t:test {prop: 645302}); +---- ok +-STATEMENT CREATE (t:test {prop: 645036}); +---- ok +-STATEMENT CREATE (t:test {prop: 371515}); +---- ok +-STATEMENT CREATE (t:test {prop: 871610}); +---- ok +-STATEMENT CREATE (t:test {prop: 746509}); +---- ok +-STATEMENT CREATE (t:test {prop: 957400}); +---- ok +-STATEMENT CREATE (t:test {prop: 374279}); +---- ok +-STATEMENT CREATE (t:test {prop: 236794}); +---- ok +-STATEMENT CREATE (t:test {prop: 560435}); +---- ok +-STATEMENT CREATE (t:test {prop: 832076}); +---- ok +-STATEMENT CREATE (t:test {prop: 653014}); +---- ok +-STATEMENT CREATE (t:test {prop: 492656}); +---- ok +-STATEMENT CREATE (t:test {prop: 15349}); +---- ok +-STATEMENT CREATE (t:test {prop: 394704}); +---- ok +-STATEMENT CREATE (t:test {prop: 521154}); +---- ok +-STATEMENT CREATE (t:test {prop: 160445}); +---- ok +-STATEMENT CREATE (t:test {prop: 407972}); +---- ok +-STATEMENT CREATE (t:test {prop: 578500}); +---- ok +-STATEMENT CREATE (t:test {prop: 933778}); +---- ok +-STATEMENT CREATE (t:test {prop: 695618}); +---- ok +-STATEMENT CREATE (t:test {prop: 364488}); +---- ok +-STATEMENT CREATE (t:test {prop: 736845}); +---- ok +-STATEMENT CREATE (t:test {prop: 587646}); +---- ok +-STATEMENT CREATE (t:test {prop: 643077}); +---- ok +-STATEMENT CREATE (t:test {prop: 583188}); +---- ok +-STATEMENT CREATE (t:test {prop: 440329}); +---- ok +-STATEMENT CREATE (t:test {prop: 584465}); +---- ok +-STATEMENT CREATE (t:test {prop: 228426}); +---- ok +-STATEMENT CREATE (t:test {prop: 438770}); +---- ok +-STATEMENT CREATE (t:test {prop: 467974}); +---- ok +-STATEMENT CREATE (t:test {prop: 119406}); +---- ok +-STATEMENT CREATE (t:test {prop: 199210}); +---- ok +-STATEMENT CREATE (t:test {prop: 953539}); +---- ok +-STATEMENT CREATE (t:test {prop: 678537}); +---- ok +-STATEMENT CREATE (t:test {prop: 884594}); +---- ok +-STATEMENT CREATE (t:test {prop: 693228}); +---- ok +-STATEMENT CREATE (t:test {prop: 358166}); +---- ok +-STATEMENT CREATE (t:test {prop: 365020}); +---- ok +-STATEMENT CREATE (t:test {prop: 895197}); +---- ok +-STATEMENT CREATE (t:test {prop: 86431}); +---- ok +-STATEMENT CREATE (t:test {prop: 248858}); +---- ok +-STATEMENT CREATE (t:test {prop: 11697}); +---- ok +-STATEMENT CREATE (t:test {prop: 660214}); +---- ok +-STATEMENT CREATE (t:test {prop: 101664}); +---- ok +-STATEMENT CREATE (t:test {prop: 999773}); +---- ok +-STATEMENT CREATE (t:test {prop: 988088}); +---- ok +-STATEMENT CREATE (t:test {prop: 512720}); +---- ok +-STATEMENT CREATE (t:test {prop: 557561}); +---- ok +-STATEMENT CREATE (t:test {prop: 940860}); +---- ok +-STATEMENT CREATE (t:test {prop: 349774}); +---- ok +-STATEMENT CREATE (t:test {prop: 200330}); +---- ok +-STATEMENT CREATE (t:test {prop: 586630}); +---- ok +-STATEMENT CREATE (t:test {prop: 268536}); +---- ok +-STATEMENT CREATE (t:test {prop: 936880}); +---- ok +-STATEMENT CREATE (t:test {prop: 690921}); +---- ok +-STATEMENT CREATE (t:test {prop: 37917}); +---- ok +-STATEMENT CREATE (t:test {prop: 788249}); +---- ok +-STATEMENT CREATE (t:test {prop: 159779}); +---- ok +-STATEMENT CREATE (t:test {prop: 856333}); +---- ok +-STATEMENT CREATE (t:test {prop: 310983}); +---- ok +-STATEMENT CREATE (t:test {prop: 970043}); +---- ok +-STATEMENT CREATE (t:test {prop: 411001}); +---- ok +-STATEMENT CREATE (t:test {prop: 184497}); +---- ok +-STATEMENT CREATE (t:test {prop: 851410}); +---- ok +-STATEMENT CREATE (t:test {prop: 351121}); +---- ok +-STATEMENT CREATE (t:test {prop: 710044}); +---- ok +-STATEMENT CREATE (t:test {prop: 385289}); +---- ok +-STATEMENT CREATE (t:test {prop: 970247}); +---- ok +-STATEMENT CREATE (t:test {prop: 766285}); +---- ok +-STATEMENT CREATE (t:test {prop: 65783}); +---- ok +-STATEMENT CREATE (t:test {prop: 7743}); +---- ok +-STATEMENT CREATE (t:test {prop: 807540}); +---- ok +-STATEMENT CREATE (t:test {prop: 865571}); +---- ok +-STATEMENT CREATE (t:test {prop: 684534}); +---- ok +-STATEMENT CREATE (t:test {prop: 581290}); +---- ok +-STATEMENT CREATE (t:test {prop: 736570}); +---- ok +-STATEMENT CREATE (t:test {prop: 279889}); +---- ok +-STATEMENT CREATE (t:test {prop: 568406}); +---- ok +-STATEMENT CREATE (t:test {prop: 587682}); +---- ok +-STATEMENT CREATE (t:test {prop: 900897}); +---- ok +-STATEMENT CREATE (t:test {prop: 271972}); +---- ok +-STATEMENT CREATE (t:test {prop: 338171}); +---- ok +-STATEMENT CREATE (t:test {prop: 53959}); +---- ok +-STATEMENT CREATE (t:test {prop: 125125}); +---- ok +-STATEMENT CREATE (t:test {prop: 121191}); +---- ok +-STATEMENT CREATE (t:test {prop: 462685}); +---- ok +-STATEMENT CREATE (t:test {prop: 796530}); +---- ok +-STATEMENT CREATE (t:test {prop: 893377}); +---- ok +-STATEMENT CREATE (t:test {prop: 311982}); +---- ok +-STATEMENT CREATE (t:test {prop: 306567}); +---- ok +-STATEMENT CREATE (t:test {prop: 866515}); +---- ok +-STATEMENT CREATE (t:test {prop: 165633}); +---- ok +-STATEMENT CREATE (t:test {prop: 113151}); +---- ok +-STATEMENT CREATE (t:test {prop: 50969}); +---- ok +-STATEMENT CREATE (t:test {prop: 167301}); +---- ok +-STATEMENT CREATE (t:test {prop: 69305}); +---- ok +-STATEMENT CREATE (t:test {prop: 390583}); +---- ok +-STATEMENT CREATE (t:test {prop: 628188}); +---- ok +-STATEMENT CREATE (t:test {prop: 157424}); +---- ok +-STATEMENT CREATE (t:test {prop: 330831}); +---- ok +-STATEMENT CREATE (t:test {prop: 206421}); +---- ok +-STATEMENT CREATE (t:test {prop: 87973}); +---- ok +-STATEMENT CREATE (t:test {prop: 719866}); +---- ok +-STATEMENT CREATE (t:test {prop: 539357}); +---- ok +-STATEMENT CREATE (t:test {prop: 405147}); +---- ok +-STATEMENT CREATE (t:test {prop: 69264}); +---- ok +-STATEMENT CREATE (t:test {prop: 972962}); +---- ok +-STATEMENT CREATE (t:test {prop: 276579}); +---- ok +-STATEMENT CREATE (t:test {prop: 641270}); +---- ok +-STATEMENT CREATE (t:test {prop: 340207}); +---- ok +-STATEMENT CREATE (t:test {prop: 478991}); +---- ok +-STATEMENT CREATE (t:test {prop: 626745}); +---- ok +-STATEMENT CREATE (t:test {prop: 69852}); +---- ok +-STATEMENT CREATE (t:test {prop: 527536}); +---- ok +-STATEMENT CREATE (t:test {prop: 819345}); +---- ok +-STATEMENT CREATE (t:test {prop: 883015}); +---- ok +-STATEMENT CREATE (t:test {prop: 588951}); +---- ok +-STATEMENT CREATE (t:test {prop: 380308}); +---- ok +-STATEMENT CREATE (t:test {prop: 730750}); +---- ok +-STATEMENT CREATE (t:test {prop: 733984}); +---- ok +-STATEMENT CREATE (t:test {prop: 65762}); +---- ok +-STATEMENT CREATE (t:test {prop: 938625}); +---- ok +-STATEMENT CREATE (t:test {prop: 436799}); +---- ok +-STATEMENT CREATE (t:test {prop: 982366}); +---- ok +-STATEMENT CREATE (t:test {prop: 178921}); +---- ok +-STATEMENT CREATE (t:test {prop: 668505}); +---- ok +-STATEMENT CREATE (t:test {prop: 748814}); +---- ok +-STATEMENT CREATE (t:test {prop: 692259}); +---- ok +-STATEMENT CREATE (t:test {prop: 996049}); +---- ok +-STATEMENT CREATE (t:test {prop: 977792}); +---- ok +-STATEMENT CREATE (t:test {prop: 827075}); +---- ok +-STATEMENT CREATE (t:test {prop: 754360}); +---- ok +-STATEMENT CREATE (t:test {prop: 199185}); +---- ok +-STATEMENT CREATE (t:test {prop: 641218}); +---- ok +-STATEMENT CREATE (t:test {prop: 561141}); +---- ok +-STATEMENT CREATE (t:test {prop: 384017}); +---- ok +-STATEMENT CREATE (t:test {prop: 75629}); +---- ok +-STATEMENT CREATE (t:test {prop: 49745}); +---- ok +-STATEMENT CREATE (t:test {prop: 603810}); +---- ok +-STATEMENT CREATE (t:test {prop: 446153}); +---- ok +-STATEMENT CREATE (t:test {prop: 981309}); +---- ok +-STATEMENT CREATE (t:test {prop: 181242}); +---- ok +-STATEMENT CREATE (t:test {prop: 379372}); +---- ok +-STATEMENT CREATE (t:test {prop: 555979}); +---- ok +-STATEMENT CREATE (t:test {prop: 414495}); +---- ok +-STATEMENT CREATE (t:test {prop: 364927}); +---- ok +-STATEMENT CREATE (t:test {prop: 568220}); +---- ok +-STATEMENT CREATE (t:test {prop: 550116}); +---- ok +-STATEMENT CREATE (t:test {prop: 495649}); +---- ok +-STATEMENT CREATE (t:test {prop: 329395}); +---- ok +-STATEMENT CREATE (t:test {prop: 561955}); +---- ok +-STATEMENT CREATE (t:test {prop: 868102}); +---- ok +-STATEMENT CREATE (t:test {prop: 143864}); +---- ok +-STATEMENT CREATE (t:test {prop: 249129}); +---- ok +-STATEMENT CREATE (t:test {prop: 879468}); +---- ok +-STATEMENT CREATE (t:test {prop: 967969}); +---- ok +-STATEMENT CREATE (t:test {prop: 253487}); +---- ok +-STATEMENT CREATE (t:test {prop: 39762}); +---- ok +-STATEMENT CREATE (t:test {prop: 918062}); +---- ok +-STATEMENT CREATE (t:test {prop: 987236}); +---- ok +-STATEMENT CREATE (t:test {prop: 723841}); +---- ok +-STATEMENT CREATE (t:test {prop: 558386}); +---- ok +-STATEMENT CREATE (t:test {prop: 274903}); +---- ok +-STATEMENT CREATE (t:test {prop: 318861}); +---- ok +-STATEMENT CREATE (t:test {prop: 545545}); +---- ok +-STATEMENT CREATE (t:test {prop: 966818}); +---- ok +-STATEMENT CREATE (t:test {prop: 715937}); +---- ok +-STATEMENT CREATE (t:test {prop: 679218}); +---- ok +-STATEMENT CREATE (t:test {prop: 127832}); +---- ok +-STATEMENT CREATE (t:test {prop: 952650}); +---- ok +-STATEMENT CREATE (t:test {prop: 610500}); +---- ok +-STATEMENT CREATE (t:test {prop: 773827}); +---- ok +-STATEMENT CREATE (t:test {prop: 358881}); +---- ok +-STATEMENT CREATE (t:test {prop: 757179}); +---- ok +-STATEMENT CREATE (t:test {prop: 63809}); +---- ok +-STATEMENT CREATE (t:test {prop: 686183}); +---- ok +-STATEMENT CREATE (t:test {prop: 515116}); +---- ok +-STATEMENT CREATE (t:test {prop: 632537}); +---- ok +-STATEMENT CREATE (t:test {prop: 985821}); +---- ok +-STATEMENT CREATE (t:test {prop: 4286}); +---- ok +-STATEMENT CREATE (t:test {prop: 334201}); +---- ok +-STATEMENT CREATE (t:test {prop: 993601}); +---- ok +-STATEMENT CREATE (t:test {prop: 398471}); +---- ok +-STATEMENT CREATE (t:test {prop: 780671}); +---- ok +-STATEMENT CREATE (t:test {prop: 329716}); +---- ok +-STATEMENT CREATE (t:test {prop: 795359}); +---- ok +-STATEMENT CREATE (t:test {prop: 457163}); +---- ok +-STATEMENT CREATE (t:test {prop: 302714}); +---- ok +-STATEMENT CREATE (t:test {prop: 31374}); +---- ok +-STATEMENT CREATE (t:test {prop: 842213}); +---- ok +-STATEMENT CREATE (t:test {prop: 865403}); +---- ok +-STATEMENT CREATE (t:test {prop: 134808}); +---- ok +-STATEMENT CREATE (t:test {prop: 846978}); +---- ok +-STATEMENT CREATE (t:test {prop: 730666}); +---- ok +-STATEMENT CREATE (t:test {prop: 400898}); +---- ok +-STATEMENT CREATE (t:test {prop: 474718}); +---- ok +-STATEMENT CREATE (t:test {prop: 776295}); +---- ok +-STATEMENT CREATE (t:test {prop: 413429}); +---- ok +-STATEMENT CREATE (t:test {prop: 530403}); +---- ok +-STATEMENT CREATE (t:test {prop: 272590}); +---- ok +-STATEMENT CREATE (t:test {prop: 695790}); +---- ok +-STATEMENT CREATE (t:test {prop: 644720}); +---- ok +-STATEMENT CREATE (t:test {prop: 204072}); +---- ok +-STATEMENT CREATE (t:test {prop: 960962}); +---- ok +-STATEMENT CREATE (t:test {prop: 604296}); +---- ok +-STATEMENT CREATE (t:test {prop: 277078}); +---- ok +-STATEMENT CREATE (t:test {prop: 770125}); +---- ok +-STATEMENT CREATE (t:test {prop: 397804}); +---- ok +-STATEMENT CREATE (t:test {prop: 615261}); +---- ok +-STATEMENT CREATE (t:test {prop: 903314}); +---- ok +-STATEMENT CREATE (t:test {prop: 224150}); +---- ok +-STATEMENT CREATE (t:test {prop: 570675}); +---- ok +-STATEMENT CREATE (t:test {prop: 672134}); +---- ok +-STATEMENT CREATE (t:test {prop: 825128}); +---- ok +-STATEMENT CREATE (t:test {prop: 136566}); +---- ok +-STATEMENT CREATE (t:test {prop: 878508}); +---- ok +-STATEMENT CREATE (t:test {prop: 619767}); +---- ok +-STATEMENT CREATE (t:test {prop: 769743}); +---- ok +-STATEMENT CREATE (t:test {prop: 268434}); +---- ok +-STATEMENT CREATE (t:test {prop: 307021}); +---- ok +-STATEMENT CREATE (t:test {prop: 533634}); +---- ok +-STATEMENT CREATE (t:test {prop: 173584}); +---- ok +-STATEMENT CREATE (t:test {prop: 341185}); +---- ok +-STATEMENT CREATE (t:test {prop: 557119}); +---- ok +-STATEMENT CREATE (t:test {prop: 580706}); +---- ok +-STATEMENT CREATE (t:test {prop: 870249}); +---- ok +-STATEMENT CREATE (t:test {prop: 245646}); +---- ok +-STATEMENT CREATE (t:test {prop: 182524}); +---- ok +-STATEMENT CREATE (t:test {prop: 275114}); +---- ok +-STATEMENT CREATE (t:test {prop: 550458}); +---- ok +-STATEMENT CREATE (t:test {prop: 623515}); +---- ok +-STATEMENT CREATE (t:test {prop: 842986}); +---- ok +-STATEMENT CREATE (t:test {prop: 137675}); +---- ok +-STATEMENT CREATE (t:test {prop: 89188}); +---- ok +-STATEMENT CREATE (t:test {prop: 152178}); +---- ok +-STATEMENT CREATE (t:test {prop: 870899}); +---- ok +-STATEMENT CREATE (t:test {prop: 542183}); +---- ok +-STATEMENT CREATE (t:test {prop: 971662}); +---- ok +-STATEMENT CREATE (t:test {prop: 958097}); +---- ok +-STATEMENT CREATE (t:test {prop: 668545}); +---- ok +-STATEMENT CREATE (t:test {prop: 790325}); +---- ok +-STATEMENT CREATE (t:test {prop: 480534}); +---- ok +-STATEMENT CREATE (t:test {prop: 892489}); +---- ok +-STATEMENT CREATE (t:test {prop: 878189}); +---- ok +-STATEMENT CREATE (t:test {prop: 177067}); +---- ok +-STATEMENT CREATE (t:test {prop: 520970}); +---- ok +-STATEMENT CREATE (t:test {prop: 120730}); +---- ok +-STATEMENT CREATE (t:test {prop: 725540}); +---- ok +-STATEMENT CREATE (t:test {prop: 714994}); +---- ok +-STATEMENT CREATE (t:test {prop: 757678}); +---- ok +-STATEMENT CREATE (t:test {prop: 681664}); +---- ok +-STATEMENT CREATE (t:test {prop: 651393}); +---- ok +-STATEMENT CREATE (t:test {prop: 405477}); +---- ok +-STATEMENT CREATE (t:test {prop: 275065}); +---- ok +-STATEMENT CREATE (t:test {prop: 956607}); +---- ok +-STATEMENT CREATE (t:test {prop: 737284}); +---- ok +-STATEMENT CREATE (t:test {prop: 248870}); +---- ok +-STATEMENT CREATE (t:test {prop: 299765}); +---- ok +-STATEMENT CREATE (t:test {prop: 401090}); +---- ok +-STATEMENT CREATE (t:test {prop: 442072}); +---- ok +-STATEMENT CREATE (t:test {prop: 392062}); +---- ok +-STATEMENT CREATE (t:test {prop: 354698}); +---- ok +-STATEMENT CREATE (t:test {prop: 305486}); +---- ok +-STATEMENT CREATE (t:test {prop: 79183}); +---- ok +-STATEMENT CREATE (t:test {prop: 804448}); +---- ok +-STATEMENT CREATE (t:test {prop: 695239}); +---- ok +-STATEMENT CREATE (t:test {prop: 407048}); +---- ok +-STATEMENT CREATE (t:test {prop: 54293}); +---- ok +-STATEMENT CREATE (t:test {prop: 444363}); +---- ok +-STATEMENT CREATE (t:test {prop: 766125}); +---- ok +-STATEMENT CREATE (t:test {prop: 18914}); +---- ok +-STATEMENT CREATE (t:test {prop: 379675}); +---- ok +-STATEMENT CREATE (t:test {prop: 182746}); +---- ok +-STATEMENT CREATE (t:test {prop: 868703}); +---- ok +-STATEMENT CREATE (t:test {prop: 57991}); +---- ok +-STATEMENT CREATE (t:test {prop: 255050}); +---- ok +-STATEMENT CREATE (t:test {prop: 615488}); +---- ok +-STATEMENT CREATE (t:test {prop: 137545}); +---- ok +-STATEMENT CREATE (t:test {prop: 827672}); +---- ok +-STATEMENT CREATE (t:test {prop: 912507}); +---- ok +-STATEMENT CREATE (t:test {prop: 562802}); +---- ok +-STATEMENT CREATE (t:test {prop: 527916}); +---- ok +-STATEMENT CREATE (t:test {prop: 64515}); +---- ok +-STATEMENT CREATE (t:test {prop: 812889}); +---- ok +-STATEMENT CREATE (t:test {prop: 4382}); +---- ok +-STATEMENT CREATE (t:test {prop: 921241}); +---- ok +-STATEMENT CREATE (t:test {prop: 964557}); +---- ok +-STATEMENT CREATE (t:test {prop: 36251}); +---- ok +-STATEMENT CREATE (t:test {prop: 893058}); +---- ok +-STATEMENT CREATE (t:test {prop: 497326}); +---- ok +-STATEMENT CREATE (t:test {prop: 185838}); +---- ok +-STATEMENT CREATE (t:test {prop: 284225}); +---- ok +-STATEMENT CREATE (t:test {prop: 878048}); +---- ok +-STATEMENT CREATE (t:test {prop: 818797}); +---- ok +-STATEMENT CREATE (t:test {prop: 498576}); +---- ok +-STATEMENT CREATE (t:test {prop: 543056}); +---- ok +-STATEMENT CREATE (t:test {prop: 987231}); +---- ok +-STATEMENT CREATE (t:test {prop: 929561}); +---- ok +-STATEMENT CREATE (t:test {prop: 754374}); +---- ok +-STATEMENT CREATE (t:test {prop: 960431}); +---- ok +-STATEMENT CREATE (t:test {prop: 483539}); +---- ok +-STATEMENT CREATE (t:test {prop: 419056}); +---- ok +-STATEMENT CREATE (t:test {prop: 4377}); +---- ok +-STATEMENT CREATE (t:test {prop: 276399}); +---- ok +-STATEMENT CREATE (t:test {prop: 553210}); +---- ok +-STATEMENT CREATE (t:test {prop: 52332}); +---- ok +-STATEMENT CREATE (t:test {prop: 294625}); +---- ok +-STATEMENT CREATE (t:test {prop: 64802}); +---- ok +-STATEMENT CREATE (t:test {prop: 662239}); +---- ok +-STATEMENT CREATE (t:test {prop: 231538}); +---- ok +-STATEMENT CREATE (t:test {prop: 68717}); +---- ok +-STATEMENT CREATE (t:test {prop: 705338}); +---- ok +-STATEMENT CREATE (t:test {prop: 282195}); +---- ok +-STATEMENT CREATE (t:test {prop: 255642}); +---- ok +-STATEMENT CREATE (t:test {prop: 559791}); +---- ok +-STATEMENT CREATE (t:test {prop: 961460}); +---- ok +-STATEMENT CREATE (t:test {prop: 417863}); +---- ok +-STATEMENT CREATE (t:test {prop: 108188}); +---- ok +-STATEMENT CREATE (t:test {prop: 541039}); +---- ok +-STATEMENT CREATE (t:test {prop: 676960}); +---- ok +-STATEMENT CREATE (t:test {prop: 282561}); +---- ok +-STATEMENT CREATE (t:test {prop: 421596}); +---- ok +-STATEMENT CREATE (t:test {prop: 702813}); +---- ok +-STATEMENT CREATE (t:test {prop: 781955}); +---- ok +-STATEMENT CREATE (t:test {prop: 622647}); +---- ok +-STATEMENT CREATE (t:test {prop: 510373}); +---- ok +-STATEMENT CREATE (t:test {prop: 950211}); +---- ok +-STATEMENT CREATE (t:test {prop: 731976}); +---- ok +-STATEMENT CREATE (t:test {prop: 205952}); +---- ok +-STATEMENT CREATE (t:test {prop: 377785}); +---- ok +-STATEMENT CREATE (t:test {prop: 793978}); +---- ok +-STATEMENT CREATE (t:test {prop: 976991}); +---- ok +-STATEMENT CREATE (t:test {prop: 804451}); +---- ok +-STATEMENT CREATE (t:test {prop: 149490}); +---- ok +-STATEMENT CREATE (t:test {prop: 328618}); +---- ok +-STATEMENT CREATE (t:test {prop: 778575}); +---- ok +-STATEMENT CREATE (t:test {prop: 973365}); +---- ok +-STATEMENT CREATE (t:test {prop: 330983}); +---- ok +-STATEMENT CREATE (t:test {prop: 620434}); +---- ok +-STATEMENT CREATE (t:test {prop: 533433}); +---- ok +-STATEMENT CREATE (t:test {prop: 207228}); +---- ok +-STATEMENT CREATE (t:test {prop: 56512}); +---- ok +-STATEMENT CREATE (t:test {prop: 997635}); +---- ok +-STATEMENT CREATE (t:test {prop: 501703}); +---- ok +-STATEMENT CREATE (t:test {prop: 390556}); +---- ok +-STATEMENT CREATE (t:test {prop: 455852}); +---- ok +-STATEMENT CREATE (t:test {prop: 627035}); +---- ok +-STATEMENT CREATE (t:test {prop: 842821}); +---- ok +-STATEMENT CREATE (t:test {prop: 357461}); +---- ok +-STATEMENT CREATE (t:test {prop: 849556}); +---- ok +-STATEMENT CREATE (t:test {prop: 959123}); +---- ok +-STATEMENT CREATE (t:test {prop: 101321}); +---- ok +-STATEMENT CREATE (t:test {prop: 74522}); +---- ok +-STATEMENT CREATE (t:test {prop: 457589}); +---- ok +-STATEMENT CREATE (t:test {prop: 178156}); +---- ok +-STATEMENT CREATE (t:test {prop: 403808}); +---- ok +-STATEMENT CREATE (t:test {prop: 358675}); +---- ok +-STATEMENT CREATE (t:test {prop: 966672}); +---- ok +-STATEMENT CREATE (t:test {prop: 701816}); +---- ok +-STATEMENT CREATE (t:test {prop: 107235}); +---- ok +-STATEMENT CREATE (t:test {prop: 169923}); +---- ok +-STATEMENT CREATE (t:test {prop: 707341}); +---- ok +-STATEMENT CREATE (t:test {prop: 273288}); +---- ok +-STATEMENT CREATE (t:test {prop: 769232}); +---- ok +-STATEMENT CREATE (t:test {prop: 538284}); +---- ok +-STATEMENT CREATE (t:test {prop: 560265}); +---- ok +-STATEMENT CREATE (t:test {prop: 912187}); +---- ok +-STATEMENT CREATE (t:test {prop: 561538}); +---- ok +-STATEMENT CREATE (t:test {prop: 271591}); +---- ok +-STATEMENT CREATE (t:test {prop: 511326}); +---- ok +-STATEMENT CREATE (t:test {prop: 736030}); +---- ok +-STATEMENT CREATE (t:test {prop: 238414}); +---- ok +-STATEMENT CREATE (t:test {prop: 756542}); +---- ok +-STATEMENT CREATE (t:test {prop: 892108}); +---- ok +-STATEMENT CREATE (t:test {prop: 804956}); +---- ok +-STATEMENT CREATE (t:test {prop: 248480}); +---- ok +-STATEMENT CREATE (t:test {prop: 836009}); +---- ok +-STATEMENT CREATE (t:test {prop: 679403}); +---- ok +-STATEMENT CREATE (t:test {prop: 443237}); +---- ok +-STATEMENT CREATE (t:test {prop: 151793}); +---- ok +-STATEMENT CREATE (t:test {prop: 795741}); +---- ok +-STATEMENT CREATE (t:test {prop: 818111}); +---- ok +-STATEMENT CREATE (t:test {prop: 925039}); +---- ok +-STATEMENT CREATE (t:test {prop: 218589}); +---- ok +-STATEMENT CREATE (t:test {prop: 485409}); +---- ok +-STATEMENT CREATE (t:test {prop: 58487}); +---- ok +-STATEMENT CREATE (t:test {prop: 767839}); +---- ok +-STATEMENT CREATE (t:test {prop: 423643}); +---- ok +-STATEMENT CREATE (t:test {prop: 930409}); +---- ok +-STATEMENT CREATE (t:test {prop: 118915}); +---- ok +-STATEMENT CREATE (t:test {prop: 831247}); +---- ok +-STATEMENT CREATE (t:test {prop: 548100}); +---- ok +-STATEMENT CREATE (t:test {prop: 816588}); +---- ok +-STATEMENT CREATE (t:test {prop: 133145}); +---- ok +-STATEMENT CREATE (t:test {prop: 329771}); +---- ok +-STATEMENT CREATE (t:test {prop: 746525}); +---- ok +-STATEMENT CREATE (t:test {prop: 441876}); +---- ok +-STATEMENT CREATE (t:test {prop: 864833}); +---- ok +-STATEMENT CREATE (t:test {prop: 392146}); +---- ok +-STATEMENT CREATE (t:test {prop: 164566}); +---- ok +-STATEMENT CREATE (t:test {prop: 331772}); +---- ok +-STATEMENT CREATE (t:test {prop: 54303}); +---- ok +-STATEMENT CREATE (t:test {prop: 63748}); +---- ok +-STATEMENT CREATE (t:test {prop: 814200}); +---- ok +-STATEMENT CREATE (t:test {prop: 663377}); +---- ok +-STATEMENT CREATE (t:test {prop: 564017}); +---- ok +-STATEMENT CREATE (t:test {prop: 157930}); +---- ok +-STATEMENT CREATE (t:test {prop: 54099}); +---- ok +-STATEMENT CREATE (t:test {prop: 452753}); +---- ok +-STATEMENT CREATE (t:test {prop: 969058}); +---- ok +-STATEMENT CREATE (t:test {prop: 62902}); +---- ok +-STATEMENT CREATE (t:test {prop: 283747}); +---- ok +-STATEMENT CREATE (t:test {prop: 155243}); +---- ok +-STATEMENT CREATE (t:test {prop: 448361}); +---- ok +-STATEMENT CREATE (t:test {prop: 288233}); +---- ok +-STATEMENT CREATE (t:test {prop: 620560}); +---- ok +-STATEMENT CREATE (t:test {prop: 33772}); +---- ok +-STATEMENT CREATE (t:test {prop: 275952}); +---- ok +-STATEMENT CREATE (t:test {prop: 994515}); +---- ok +-STATEMENT CREATE (t:test {prop: 90851}); +---- ok +-STATEMENT CREATE (t:test {prop: 780649}); +---- ok +-STATEMENT CREATE (t:test {prop: 588839}); +---- ok +-STATEMENT CREATE (t:test {prop: 913413}); +---- ok +-STATEMENT CREATE (t:test {prop: 209530}); +---- ok +-STATEMENT CREATE (t:test {prop: 628760}); +---- ok +-STATEMENT CREATE (t:test {prop: 185237}); +---- ok +-STATEMENT CREATE (t:test {prop: 289281}); +---- ok +-STATEMENT CREATE (t:test {prop: 660870}); +---- ok +-STATEMENT CREATE (t:test {prop: 328359}); +---- ok +-STATEMENT CREATE (t:test {prop: 892221}); +---- ok +-STATEMENT CREATE (t:test {prop: 738679}); +---- ok +-STATEMENT CREATE (t:test {prop: 522663}); +---- ok +-STATEMENT CREATE (t:test {prop: 383433}); +---- ok +-STATEMENT CREATE (t:test {prop: 969654}); +---- ok +-STATEMENT CREATE (t:test {prop: 40985}); +---- ok +-STATEMENT CREATE (t:test {prop: 619871}); +---- ok +-STATEMENT CREATE (t:test {prop: 810952}); +---- ok +-STATEMENT CREATE (t:test {prop: 550385}); +---- ok +-STATEMENT CREATE (t:test {prop: 455155}); +---- ok +-STATEMENT CREATE (t:test {prop: 808103}); +---- ok +-STATEMENT CREATE (t:test {prop: 44202}); +---- ok +-STATEMENT CREATE (t:test {prop: 10640}); +---- ok +-STATEMENT CREATE (t:test {prop: 731918}); +---- ok +-STATEMENT CREATE (t:test {prop: 914977}); +---- ok +-STATEMENT CREATE (t:test {prop: 272156}); +---- ok +-STATEMENT CREATE (t:test {prop: 528264}); +---- ok +-STATEMENT CREATE (t:test {prop: 324115}); +---- ok +-STATEMENT CREATE (t:test {prop: 830288}); +---- ok +-STATEMENT CREATE (t:test {prop: 896558}); +---- ok +-STATEMENT CREATE (t:test {prop: 284870}); +---- ok +-STATEMENT CREATE (t:test {prop: 133790}); +---- ok +-STATEMENT CREATE (t:test {prop: 278614}); +---- ok +-STATEMENT CREATE (t:test {prop: 77672}); +---- ok +-STATEMENT CREATE (t:test {prop: 841261}); +---- ok +-STATEMENT CREATE (t:test {prop: 544095}); +---- ok +-STATEMENT CREATE (t:test {prop: 689848}); +---- ok +-STATEMENT CREATE (t:test {prop: 339258}); +---- ok +-STATEMENT CREATE (t:test {prop: 459857}); +---- ok +-STATEMENT CREATE (t:test {prop: 269459}); +---- ok +-STATEMENT CREATE (t:test {prop: 328923}); +---- ok +-STATEMENT CREATE (t:test {prop: 766628}); +---- ok +-STATEMENT CREATE (t:test {prop: 677768}); +---- ok +-STATEMENT CREATE (t:test {prop: 324402}); +---- ok +-STATEMENT CREATE (t:test {prop: 856228}); +---- ok +-STATEMENT CREATE (t:test {prop: 687221}); +---- ok +-STATEMENT CREATE (t:test {prop: 45943}); +---- ok +-STATEMENT CREATE (t:test {prop: 157778}); +---- ok +-STATEMENT CREATE (t:test {prop: 251746}); +---- ok +-STATEMENT CREATE (t:test {prop: 900569}); +---- ok +-STATEMENT CREATE (t:test {prop: 242763}); +---- ok +-STATEMENT CREATE (t:test {prop: 50420}); +---- ok +-STATEMENT CREATE (t:test {prop: 936117}); +---- ok +-STATEMENT CREATE (t:test {prop: 959210}); +---- ok +-STATEMENT CREATE (t:test {prop: 834988}); +---- ok +-STATEMENT CREATE (t:test {prop: 13714}); +---- ok +-STATEMENT CREATE (t:test {prop: 919830}); +---- ok +-STATEMENT CREATE (t:test {prop: 82788}); +---- ok +-STATEMENT CREATE (t:test {prop: 359114}); +---- ok +-STATEMENT CREATE (t:test {prop: 979803}); +---- ok +-STATEMENT CREATE (t:test {prop: 80384}); +---- ok +-STATEMENT CREATE (t:test {prop: 262307}); +---- ok +-STATEMENT CREATE (t:test {prop: 551957}); +---- ok +-STATEMENT CREATE (t:test {prop: 736625}); +---- ok +-STATEMENT CREATE (t:test {prop: 354765}); +---- ok +-STATEMENT CREATE (t:test {prop: 633982}); +---- ok +-STATEMENT CREATE (t:test {prop: 571258}); +---- ok +-STATEMENT CREATE (t:test {prop: 515139}); +---- ok +-STATEMENT CREATE (t:test {prop: 594556}); +---- ok +-STATEMENT CREATE (t:test {prop: 322996}); +---- ok +-STATEMENT CREATE (t:test {prop: 521577}); +---- ok +-STATEMENT CREATE (t:test {prop: 313899}); +---- ok +-STATEMENT CREATE (t:test {prop: 582090}); +---- ok +-STATEMENT CREATE (t:test {prop: 361839}); +---- ok +-STATEMENT CREATE (t:test {prop: 442825}); +---- ok +-STATEMENT CREATE (t:test {prop: 441000}); +---- ok +-STATEMENT CREATE (t:test {prop: 399331}); +---- ok +-STATEMENT CREATE (t:test {prop: 784445}); +---- ok +-STATEMENT CREATE (t:test {prop: 786067}); +---- ok +-STATEMENT CREATE (t:test {prop: 868840}); +---- ok +-STATEMENT CREATE (t:test {prop: 366990}); +---- ok +-STATEMENT CREATE (t:test {prop: 895789}); +---- ok +-STATEMENT CREATE (t:test {prop: 524712}); +---- ok +-STATEMENT CREATE (t:test {prop: 279286}); +---- ok +-STATEMENT CREATE (t:test {prop: 143194}); +---- ok +-STATEMENT CREATE (t:test {prop: 169337}); +---- ok +-STATEMENT CREATE (t:test {prop: 860691}); +---- ok +-STATEMENT CREATE (t:test {prop: 448923}); +---- ok +-STATEMENT CREATE (t:test {prop: 256769}); +---- ok +-STATEMENT CREATE (t:test {prop: 39873}); +---- ok +-STATEMENT CREATE (t:test {prop: 208170}); +---- ok +-STATEMENT CREATE (t:test {prop: 226598}); +---- ok +-STATEMENT CREATE (t:test {prop: 381053}); +---- ok +-STATEMENT CREATE (t:test {prop: 357262}); +---- ok +-STATEMENT CREATE (t:test {prop: 850660}); +---- ok +-STATEMENT CREATE (t:test {prop: 9344}); +---- ok +-STATEMENT CREATE (t:test {prop: 942232}); +---- ok +-STATEMENT CREATE (t:test {prop: 216899}); +---- ok +-STATEMENT CREATE (t:test {prop: 295935}); +---- ok +-STATEMENT CREATE (t:test {prop: 127672}); +---- ok +-STATEMENT CREATE (t:test {prop: 436220}); +---- ok +-STATEMENT CREATE (t:test {prop: 937525}); +---- ok +-STATEMENT CREATE (t:test {prop: 472668}); +---- ok +-STATEMENT CREATE (t:test {prop: 250512}); +---- ok +-STATEMENT CREATE (t:test {prop: 80622}); +---- ok +-STATEMENT CREATE (t:test {prop: 186961}); +---- ok +-STATEMENT CREATE (t:test {prop: 56135}); +---- ok +-STATEMENT CREATE (t:test {prop: 313907}); +---- ok +-STATEMENT CREATE (t:test {prop: 912242}); +---- ok +-STATEMENT CREATE (t:test {prop: 979749}); +---- ok +-STATEMENT CREATE (t:test {prop: 328942}); +---- ok +-STATEMENT CREATE (t:test {prop: 30301}); +---- ok +-STATEMENT CREATE (t:test {prop: 920549}); +---- ok +-STATEMENT CREATE (t:test {prop: 670037}); +---- ok +-STATEMENT CREATE (t:test {prop: 800698}); +---- ok +-STATEMENT CREATE (t:test {prop: 528927}); +---- ok +-STATEMENT CREATE (t:test {prop: 394794}); +---- ok +-STATEMENT CREATE (t:test {prop: 282146}); +---- ok +-STATEMENT CREATE (t:test {prop: 1203}); +---- ok +-STATEMENT CREATE (t:test {prop: 160885}); +---- ok +-STATEMENT CREATE (t:test {prop: 8516}); +---- ok +-STATEMENT CREATE (t:test {prop: 40993}); +---- ok +-STATEMENT CREATE (t:test {prop: 191541}); +---- ok +-STATEMENT CREATE (t:test {prop: 655643}); +---- ok +-STATEMENT CREATE (t:test {prop: 451317}); +---- ok +-STATEMENT CREATE (t:test {prop: 136060}); +---- ok +-STATEMENT CREATE (t:test {prop: 163448}); +---- ok +-STATEMENT CREATE (t:test {prop: 275765}); +---- ok +-STATEMENT CREATE (t:test {prop: 537302}); +---- ok +-STATEMENT CREATE (t:test {prop: 282264}); +---- ok +-STATEMENT CREATE (t:test {prop: 880294}); +---- ok +-STATEMENT CREATE (t:test {prop: 947212}); +---- ok +-STATEMENT CREATE (t:test {prop: 480114}); +---- ok +-STATEMENT CREATE (t:test {prop: 277115}); +---- ok +-STATEMENT CREATE (t:test {prop: 334709}); +---- ok +-STATEMENT CREATE (t:test {prop: 182999}); +---- ok +-STATEMENT CREATE (t:test {prop: 147077}); +---- ok +-STATEMENT CREATE (t:test {prop: 683989}); +---- ok +-STATEMENT CREATE (t:test {prop: 443467}); +---- ok +-STATEMENT CREATE (t:test {prop: 635072}); +---- ok +-STATEMENT CREATE (t:test {prop: 588189}); +---- ok +-STATEMENT CREATE (t:test {prop: 906317}); +---- ok +-STATEMENT CREATE (t:test {prop: 339619}); +---- ok +-STATEMENT CREATE (t:test {prop: 598520}); +---- ok +-STATEMENT CREATE (t:test {prop: 59021}); +---- ok +-STATEMENT CREATE (t:test {prop: 149210}); +---- ok +-STATEMENT CREATE (t:test {prop: 295451}); +---- ok +-STATEMENT CREATE (t:test {prop: 431631}); +---- ok +-STATEMENT CREATE (t:test {prop: 700915}); +---- ok +-STATEMENT CREATE (t:test {prop: 811549}); +---- ok +-STATEMENT CREATE (t:test {prop: 719542}); +---- ok +-STATEMENT CREATE (t:test {prop: 527400}); +---- ok +-STATEMENT CREATE (t:test {prop: 498667}); +---- ok +-STATEMENT CREATE (t:test {prop: 613430}); +---- ok +-STATEMENT CREATE (t:test {prop: 813731}); +---- ok +-STATEMENT CREATE (t:test {prop: 378390}); +---- ok +-STATEMENT CREATE (t:test {prop: 933020}); +---- ok +-STATEMENT CREATE (t:test {prop: 95095}); +---- ok +-STATEMENT CREATE (t:test {prop: 474626}); +---- ok +-STATEMENT CREATE (t:test {prop: 83407}); +---- ok +-STATEMENT CREATE (t:test {prop: 393761}); +---- ok +-STATEMENT CREATE (t:test {prop: 533331}); +---- ok +-STATEMENT CREATE (t:test {prop: 592066}); +---- ok +-STATEMENT CREATE (t:test {prop: 196445}); +---- ok +-STATEMENT CREATE (t:test {prop: 291381}); +---- ok +-STATEMENT CREATE (t:test {prop: 530347}); +---- ok +-STATEMENT CREATE (t:test {prop: 549822}); +---- ok +-STATEMENT CREATE (t:test {prop: 102210}); +---- ok +-STATEMENT CREATE (t:test {prop: 702725}); +---- ok +-STATEMENT CREATE (t:test {prop: 818738}); +---- ok +-STATEMENT CREATE (t:test {prop: 464082}); +---- ok +-STATEMENT CREATE (t:test {prop: 405267}); +---- ok +-STATEMENT CREATE (t:test {prop: 283334}); +---- ok +-STATEMENT CREATE (t:test {prop: 106097}); +---- ok +-STATEMENT CREATE (t:test {prop: 618136}); +---- ok +-STATEMENT CREATE (t:test {prop: 913224}); +---- ok +-STATEMENT CREATE (t:test {prop: 364848}); +---- ok +-STATEMENT CREATE (t:test {prop: 620502}); +---- ok +-STATEMENT CREATE (t:test {prop: 909755}); +---- ok +-STATEMENT CREATE (t:test {prop: 135093}); +---- ok +-STATEMENT CREATE (t:test {prop: 482415}); +---- ok +-STATEMENT CREATE (t:test {prop: 475457}); +---- ok +-STATEMENT CREATE (t:test {prop: 315411}); +---- ok +-STATEMENT CREATE (t:test {prop: 666986}); +---- ok +-STATEMENT CREATE (t:test {prop: 926615}); +---- ok +-STATEMENT CREATE (t:test {prop: 260816}); +---- ok +-STATEMENT CREATE (t:test {prop: 575664}); +---- ok +-STATEMENT CREATE (t:test {prop: 128779}); +---- ok +-STATEMENT CREATE (t:test {prop: 929030}); +---- ok +-STATEMENT CREATE (t:test {prop: 361699}); +---- ok +-STATEMENT CREATE (t:test {prop: 615884}); +---- ok +-STATEMENT CREATE (t:test {prop: 79023}); +---- ok +-STATEMENT CREATE (t:test {prop: 464609}); +---- ok +-STATEMENT CREATE (t:test {prop: 429263}); +---- ok +-STATEMENT CREATE (t:test {prop: 137255}); +---- ok +-STATEMENT CREATE (t:test {prop: 825205}); +---- ok +-STATEMENT CREATE (t:test {prop: 581490}); +---- ok +-STATEMENT CREATE (t:test {prop: 56797}); +---- ok +-STATEMENT CREATE (t:test {prop: 55099}); +---- ok +-STATEMENT CREATE (t:test {prop: 314119}); +---- ok +-STATEMENT CREATE (t:test {prop: 441418}); +---- ok +-STATEMENT CREATE (t:test {prop: 756314}); +---- ok +-STATEMENT CREATE (t:test {prop: 604985}); +---- ok +-STATEMENT CREATE (t:test {prop: 107070}); +---- ok +-STATEMENT CREATE (t:test {prop: 543755}); +---- ok +-STATEMENT CREATE (t:test {prop: 236896}); +---- ok +-STATEMENT CREATE (t:test {prop: 756950}); +---- ok +-STATEMENT CREATE (t:test {prop: 135494}); +---- ok +-STATEMENT CREATE (t:test {prop: 212180}); +---- ok +-STATEMENT CREATE (t:test {prop: 982298}); +---- ok +-STATEMENT CREATE (t:test {prop: 577953}); +---- ok +-STATEMENT CREATE (t:test {prop: 561015}); +---- ok +-STATEMENT CREATE (t:test {prop: 785518}); +---- ok +-STATEMENT CREATE (t:test {prop: 62428}); +---- ok +-STATEMENT CREATE (t:test {prop: 567387}); +---- ok +-STATEMENT CREATE (t:test {prop: 800688}); +---- ok +-STATEMENT CREATE (t:test {prop: 507144}); +---- ok +-STATEMENT CREATE (t:test {prop: 329099}); +---- ok +-STATEMENT CREATE (t:test {prop: 906703}); +---- ok +-STATEMENT CREATE (t:test {prop: 872430}); +---- ok +-STATEMENT CREATE (t:test {prop: 66802}); +---- ok +-STATEMENT CREATE (t:test {prop: 558425}); +---- ok +-STATEMENT CREATE (t:test {prop: 217135}); +---- ok +-STATEMENT CREATE (t:test {prop: 219591}); +---- ok +-STATEMENT CREATE (t:test {prop: 857720}); +---- ok +-STATEMENT CREATE (t:test {prop: 443684}); +---- ok +-STATEMENT CREATE (t:test {prop: 483061}); +---- ok +-STATEMENT CREATE (t:test {prop: 755253}); +---- ok +-STATEMENT CREATE (t:test {prop: 51360}); +---- ok +-STATEMENT CREATE (t:test {prop: 729801}); +---- ok +-STATEMENT CREATE (t:test {prop: 485182}); +---- ok +-STATEMENT CREATE (t:test {prop: 173614}); +---- ok +-STATEMENT CREATE (t:test {prop: 967196}); +---- ok +-STATEMENT CREATE (t:test {prop: 915644}); +---- ok +-STATEMENT CREATE (t:test {prop: 198012}); +---- ok +-STATEMENT CREATE (t:test {prop: 80341}); +---- ok +-STATEMENT CREATE (t:test {prop: 965973}); +---- ok +-STATEMENT CREATE (t:test {prop: 169895}); +---- ok +-STATEMENT CREATE (t:test {prop: 997664}); +---- ok +-STATEMENT CREATE (t:test {prop: 992352}); +---- ok +-STATEMENT CREATE (t:test {prop: 907505}); +---- ok +-STATEMENT CREATE (t:test {prop: 662682}); +---- ok +-STATEMENT CREATE (t:test {prop: 39893}); +---- ok +-STATEMENT CREATE (t:test {prop: 848606}); +---- ok +-STATEMENT CREATE (t:test {prop: 239209}); +---- ok +-STATEMENT CREATE (t:test {prop: 862292}); +---- ok +-STATEMENT CREATE (t:test {prop: 551511}); +---- ok +-STATEMENT CREATE (t:test {prop: 905356}); +---- ok +-STATEMENT CREATE (t:test {prop: 966167}); +---- ok +-STATEMENT CREATE (t:test {prop: 349166}); +---- ok +-STATEMENT CREATE (t:test {prop: 675997}); +---- ok +-STATEMENT CREATE (t:test {prop: 946007}); +---- ok +-STATEMENT CREATE (t:test {prop: 938840}); +---- ok +-STATEMENT CREATE (t:test {prop: 404733}); +---- ok +-STATEMENT CREATE (t:test {prop: 844643}); +---- ok +-STATEMENT CREATE (t:test {prop: 503186}); +---- ok +-STATEMENT CREATE (t:test {prop: 128436}); +---- ok +-STATEMENT CREATE (t:test {prop: 193205}); +---- ok +-STATEMENT CREATE (t:test {prop: 1187}); +---- ok +-STATEMENT CREATE (t:test {prop: 447444}); +---- ok +-STATEMENT CREATE (t:test {prop: 43876}); +---- ok +-STATEMENT CREATE (t:test {prop: 417686}); +---- ok +-STATEMENT CREATE (t:test {prop: 171183}); +---- ok +-STATEMENT CREATE (t:test {prop: 677083}); +---- ok +-STATEMENT CREATE (t:test {prop: 60991}); +---- ok +-STATEMENT CREATE (t:test {prop: 254326}); +---- ok +-STATEMENT CREATE (t:test {prop: 837740}); +---- ok +-STATEMENT CREATE (t:test {prop: 163600}); +---- ok +-STATEMENT CREATE (t:test {prop: 877179}); +---- ok +-STATEMENT CREATE (t:test {prop: 71524}); +---- ok +-STATEMENT CREATE (t:test {prop: 65772}); +---- ok +-STATEMENT CREATE (t:test {prop: 177140}); +---- ok +-STATEMENT CREATE (t:test {prop: 819997}); +---- ok +-STATEMENT CREATE (t:test {prop: 670592}); +---- ok +-STATEMENT CREATE (t:test {prop: 783889}); +---- ok +-STATEMENT CREATE (t:test {prop: 575426}); +---- ok +-STATEMENT CREATE (t:test {prop: 440614}); +---- ok +-STATEMENT CREATE (t:test {prop: 881183}); +---- ok +-STATEMENT CREATE (t:test {prop: 7468}); +---- ok +-STATEMENT CREATE (t:test {prop: 807525}); +---- ok +-STATEMENT CREATE (t:test {prop: 160483}); +---- ok +-STATEMENT CREATE (t:test {prop: 313934}); +---- ok +-STATEMENT CREATE (t:test {prop: 196918}); +---- ok +-STATEMENT CREATE (t:test {prop: 937980}); +---- ok +-STATEMENT CREATE (t:test {prop: 122643}); +---- ok +-STATEMENT CREATE (t:test {prop: 663688}); +---- ok +-STATEMENT CREATE (t:test {prop: 633878}); +---- ok +-STATEMENT CREATE (t:test {prop: 550045}); +---- ok +-STATEMENT CREATE (t:test {prop: 94402}); +---- ok +-STATEMENT CREATE (t:test {prop: 644303}); +---- ok +-STATEMENT CREATE (t:test {prop: 59639}); +---- ok +-STATEMENT CREATE (t:test {prop: 961361}); +---- ok +-STATEMENT CREATE (t:test {prop: 41424}); +---- ok +-STATEMENT CREATE (t:test {prop: 437221}); +---- ok +-STATEMENT CREATE (t:test {prop: 610119}); +---- ok +-STATEMENT CREATE (t:test {prop: 584144}); +---- ok +-STATEMENT CREATE (t:test {prop: 116817}); +---- ok +-STATEMENT CREATE (t:test {prop: 846215}); +---- ok +-STATEMENT CREATE (t:test {prop: 496989}); +---- ok +-STATEMENT CREATE (t:test {prop: 864955}); +---- ok +-STATEMENT CREATE (t:test {prop: 715114}); +---- ok +-STATEMENT CREATE (t:test {prop: 158254}); +---- ok +-STATEMENT CREATE (t:test {prop: 222826}); +---- ok +-STATEMENT CREATE (t:test {prop: 310416}); +---- ok +-STATEMENT CREATE (t:test {prop: 66629}); +---- ok +-STATEMENT CREATE (t:test {prop: 997784}); +---- ok +-STATEMENT CREATE (t:test {prop: 423546}); +---- ok +-STATEMENT CREATE (t:test {prop: 135153}); +---- ok +-STATEMENT CREATE (t:test {prop: 809081}); +---- ok +-STATEMENT CREATE (t:test {prop: 5324}); +---- ok +-STATEMENT CREATE (t:test {prop: 239767}); +---- ok +-STATEMENT CREATE (t:test {prop: 395449}); +---- ok +-STATEMENT CREATE (t:test {prop: 349842}); +---- ok +-STATEMENT CREATE (t:test {prop: 667165}); +---- ok +-STATEMENT CREATE (t:test {prop: 564806}); +---- ok +-STATEMENT CREATE (t:test {prop: 371968}); +---- ok +-STATEMENT CREATE (t:test {prop: 237053}); +---- ok +-STATEMENT CREATE (t:test {prop: 142127}); +---- ok +-STATEMENT CREATE (t:test {prop: 623016}); +---- ok +-STATEMENT CREATE (t:test {prop: 147674}); +---- ok +-STATEMENT CREATE (t:test {prop: 353521}); +---- ok +-STATEMENT CREATE (t:test {prop: 352915}); +---- ok +-STATEMENT CREATE (t:test {prop: 541235}); +---- ok +-STATEMENT CREATE (t:test {prop: 649524}); +---- ok +-STATEMENT CREATE (t:test {prop: 394327}); +---- ok +-STATEMENT CREATE (t:test {prop: 393403}); +---- ok +-STATEMENT CREATE (t:test {prop: 994429}); +---- ok +-STATEMENT CREATE (t:test {prop: 783537}); +---- ok +-STATEMENT CREATE (t:test {prop: 10025}); +---- ok +-STATEMENT CREATE (t:test {prop: 858131}); +---- ok +-STATEMENT CREATE (t:test {prop: 522438}); +---- ok +-STATEMENT CREATE (t:test {prop: 100041}); +---- ok +-STATEMENT CREATE (t:test {prop: 803461}); +---- ok +-STATEMENT CREATE (t:test {prop: 944002}); +---- ok +-STATEMENT CREATE (t:test {prop: 480775}); +---- ok +-STATEMENT CREATE (t:test {prop: 15230}); +---- ok +-STATEMENT CREATE (t:test {prop: 557430}); +---- ok +-STATEMENT CREATE (t:test {prop: 96174}); +---- ok +-STATEMENT CREATE (t:test {prop: 86022}); +---- ok +-STATEMENT CREATE (t:test {prop: 402337}); +---- ok +-STATEMENT CREATE (t:test {prop: 708180}); +---- ok +-STATEMENT CREATE (t:test {prop: 385800}); +---- ok +-STATEMENT CREATE (t:test {prop: 889472}); +---- ok +-STATEMENT CREATE (t:test {prop: 445396}); +---- ok +-STATEMENT CREATE (t:test {prop: 947216}); +---- ok +-STATEMENT CREATE (t:test {prop: 24568}); +---- ok +-STATEMENT CREATE (t:test {prop: 604126}); +---- ok +-STATEMENT CREATE (t:test {prop: 715785}); +---- ok +-STATEMENT CREATE (t:test {prop: 517512}); +---- ok +-STATEMENT CREATE (t:test {prop: 230678}); +---- ok +-STATEMENT CREATE (t:test {prop: 79667}); +---- ok +-STATEMENT CREATE (t:test {prop: 35926}); +---- ok +-STATEMENT CREATE (t:test {prop: 477322}); +---- ok +-STATEMENT CREATE (t:test {prop: 355368}); +---- ok +-STATEMENT CREATE (t:test {prop: 749446}); +---- ok +-STATEMENT CREATE (t:test {prop: 556836}); +---- ok +-STATEMENT CREATE (t:test {prop: 232341}); +---- ok +-STATEMENT CREATE (t:test {prop: 374715}); +---- ok +-STATEMENT CREATE (t:test {prop: 805103}); +---- ok +-STATEMENT CREATE (t:test {prop: 5500}); +---- ok +-STATEMENT CREATE (t:test {prop: 887967}); +---- ok +-STATEMENT CREATE (t:test {prop: 768206}); +---- ok +-STATEMENT CREATE (t:test {prop: 10066}); +---- ok +-STATEMENT CREATE (t:test {prop: 306717}); +---- ok +-STATEMENT CREATE (t:test {prop: 470323}); +---- ok +-STATEMENT CREATE (t:test {prop: 734460}); +---- ok +-STATEMENT CREATE (t:test {prop: 924983}); +---- ok +-STATEMENT CREATE (t:test {prop: 127144}); +---- ok +-STATEMENT CREATE (t:test {prop: 104047}); +---- ok +-STATEMENT CREATE (t:test {prop: 792249}); +---- ok +-STATEMENT CREATE (t:test {prop: 263404}); +---- ok +-STATEMENT CREATE (t:test {prop: 277599}); +---- ok +-STATEMENT CREATE (t:test {prop: 965770}); +---- ok +-STATEMENT CREATE (t:test {prop: 442886}); +---- ok +-STATEMENT CREATE (t:test {prop: 349963}); +---- ok +-STATEMENT CREATE (t:test {prop: 156077}); +---- ok +-STATEMENT CREATE (t:test {prop: 624971}); +---- ok +-STATEMENT CREATE (t:test {prop: 939743}); +---- ok +-STATEMENT CREATE (t:test {prop: 913488}); +---- ok +-STATEMENT CREATE (t:test {prop: 249028}); +---- ok +-STATEMENT CREATE (t:test {prop: 443040}); +---- ok +-STATEMENT CREATE (t:test {prop: 371436}); +---- ok +-STATEMENT CREATE (t:test {prop: 291466}); +---- ok +-STATEMENT CREATE (t:test {prop: 25152}); +---- ok +-STATEMENT CREATE (t:test {prop: 396648}); +---- ok +-STATEMENT CREATE (t:test {prop: 74814}); +---- ok +-STATEMENT CREATE (t:test {prop: 898604}); +---- ok +-STATEMENT CREATE (t:test {prop: 367822}); +---- ok +-STATEMENT CREATE (t:test {prop: 421116}); +---- ok +-STATEMENT CREATE (t:test {prop: 90861}); +---- ok +-STATEMENT CREATE (t:test {prop: 552260}); +---- ok +-STATEMENT CREATE (t:test {prop: 306592}); +---- ok +-STATEMENT CREATE (t:test {prop: 249186}); +---- ok +-STATEMENT CREATE (t:test {prop: 480296}); +---- ok +-STATEMENT CREATE (t:test {prop: 436015}); +---- ok +-STATEMENT CREATE (t:test {prop: 525944}); +---- ok +-STATEMENT CREATE (t:test {prop: 434242}); +---- ok +-STATEMENT CREATE (t:test {prop: 506023}); +---- ok +-STATEMENT CREATE (t:test {prop: 316835}); +---- ok +-STATEMENT CREATE (t:test {prop: 619723}); +---- ok +-STATEMENT CREATE (t:test {prop: 277446}); +---- ok +-STATEMENT CREATE (t:test {prop: 551796}); +---- ok +-STATEMENT CREATE (t:test {prop: 289691}); +---- ok +-STATEMENT CREATE (t:test {prop: 258101}); +---- ok +-STATEMENT CREATE (t:test {prop: 899767}); +---- ok +-STATEMENT CREATE (t:test {prop: 442455}); +---- ok +-STATEMENT CREATE (t:test {prop: 369453}); +---- ok +-STATEMENT CREATE (t:test {prop: 988196}); +---- ok +-STATEMENT CREATE (t:test {prop: 631179}); +---- ok +-STATEMENT CREATE (t:test {prop: 876816}); +---- ok +-STATEMENT CREATE (t:test {prop: 543841}); +---- ok +-STATEMENT CREATE (t:test {prop: 914452}); +---- ok +-STATEMENT CREATE (t:test {prop: 353847}); +---- ok +-STATEMENT CREATE (t:test {prop: 240874}); +---- ok +-STATEMENT CREATE (t:test {prop: 686283}); +---- ok +-STATEMENT CREATE (t:test {prop: 10911}); +---- ok +-STATEMENT CREATE (t:test {prop: 27594}); +---- ok +-STATEMENT CREATE (t:test {prop: 637527}); +---- ok +-STATEMENT CREATE (t:test {prop: 919112}); +---- ok +-STATEMENT CREATE (t:test {prop: 887906}); +---- ok +-STATEMENT CREATE (t:test {prop: 837937}); +---- ok +-STATEMENT CREATE (t:test {prop: 273186}); +---- ok +-STATEMENT CREATE (t:test {prop: 712313}); +---- ok +-STATEMENT CREATE (t:test {prop: 663586}); +---- ok +-STATEMENT CREATE (t:test {prop: 626363}); +---- ok +-STATEMENT CREATE (t:test {prop: 705011}); +---- ok +-STATEMENT CREATE (t:test {prop: 39274}); +---- ok +-STATEMENT CREATE (t:test {prop: 782612}); +---- ok +-STATEMENT CREATE (t:test {prop: 948974}); +---- ok +-STATEMENT CREATE (t:test {prop: 330773}); +---- ok +-STATEMENT CREATE (t:test {prop: 634245}); +---- ok +-STATEMENT CREATE (t:test {prop: 488152}); +---- ok +-STATEMENT CREATE (t:test {prop: 565608}); +---- ok +-STATEMENT CREATE (t:test {prop: 104884}); +---- ok +-STATEMENT CREATE (t:test {prop: 304718}); +---- ok +-STATEMENT CREATE (t:test {prop: 294729}); +---- ok +-STATEMENT CREATE (t:test {prop: 413059}); +---- ok +-STATEMENT CREATE (t:test {prop: 454858}); +---- ok +-STATEMENT CREATE (t:test {prop: 883765}); +---- ok +-STATEMENT CREATE (t:test {prop: 257401}); +---- ok +-STATEMENT CREATE (t:test {prop: 823353}); +---- ok +-STATEMENT CREATE (t:test {prop: 646587}); +---- ok +-STATEMENT CREATE (t:test {prop: 864161}); +---- ok +-STATEMENT CREATE (t:test {prop: 451670}); +---- ok +-STATEMENT CREATE (t:test {prop: 921618}); +---- ok +-STATEMENT CREATE (t:test {prop: 136938}); +---- ok +-STATEMENT CREATE (t:test {prop: 564986}); +---- ok +-STATEMENT CREATE (t:test {prop: 923248}); +---- ok +-STATEMENT CREATE (t:test {prop: 825987}); +---- ok +-STATEMENT CREATE (t:test {prop: 779708}); +---- ok +-STATEMENT CREATE (t:test {prop: 707009}); +---- ok +-STATEMENT CREATE (t:test {prop: 170812}); +---- ok +-STATEMENT CREATE (t:test {prop: 822187}); +---- ok +-STATEMENT CREATE (t:test {prop: 248719}); +---- ok +-STATEMENT CREATE (t:test {prop: 565302}); +---- ok +-STATEMENT CREATE (t:test {prop: 804908}); +---- ok +-STATEMENT CREATE (t:test {prop: 684298}); +---- ok +-STATEMENT CREATE (t:test {prop: 468716}); +---- ok +-STATEMENT CREATE (t:test {prop: 883384}); +---- ok +-STATEMENT CREATE (t:test {prop: 953611}); +---- ok +-STATEMENT CREATE (t:test {prop: 801503}); +---- ok +-STATEMENT CREATE (t:test {prop: 866779}); +---- ok +-STATEMENT CREATE (t:test {prop: 972954}); +---- ok +-STATEMENT CREATE (t:test {prop: 69409}); +---- ok +-STATEMENT CREATE (t:test {prop: 661058}); +---- ok +-STATEMENT CREATE (t:test {prop: 126298}); +---- ok +-STATEMENT CREATE (t:test {prop: 701204}); +---- ok +-STATEMENT CREATE (t:test {prop: 155360}); +---- ok +-STATEMENT CREATE (t:test {prop: 27939}); +---- ok +-STATEMENT CREATE (t:test {prop: 878090}); +---- ok +-STATEMENT CREATE (t:test {prop: 695907}); +---- ok +-STATEMENT CREATE (t:test {prop: 551492}); +---- ok +-STATEMENT CREATE (t:test {prop: 935417}); +---- ok +-STATEMENT CREATE (t:test {prop: 856009}); +---- ok +-STATEMENT CREATE (t:test {prop: 623929}); +---- ok +-STATEMENT CREATE (t:test {prop: 628419}); +---- ok +-STATEMENT CREATE (t:test {prop: 148618}); +---- ok +-STATEMENT CREATE (t:test {prop: 167532}); +---- ok +-STATEMENT CREATE (t:test {prop: 663961}); +---- ok +-STATEMENT CREATE (t:test {prop: 329480}); +---- ok +-STATEMENT CREATE (t:test {prop: 150811}); +---- ok +-STATEMENT CREATE (t:test {prop: 664608}); +---- ok +-STATEMENT CREATE (t:test {prop: 425602}); +---- ok +-STATEMENT CREATE (t:test {prop: 431326}); +---- ok +-STATEMENT CREATE (t:test {prop: 217996}); +---- ok +-STATEMENT CREATE (t:test {prop: 679750}); +---- ok +-STATEMENT CREATE (t:test {prop: 672772}); +---- ok +-STATEMENT CREATE (t:test {prop: 510352}); +---- ok +-STATEMENT CREATE (t:test {prop: 887155}); +---- ok +-STATEMENT CREATE (t:test {prop: 522556}); +---- ok +-STATEMENT CREATE (t:test {prop: 517773}); +---- ok +-STATEMENT CREATE (t:test {prop: 707106}); +---- ok +-STATEMENT CREATE (t:test {prop: 183905}); +---- ok +-STATEMENT CREATE (t:test {prop: 830418}); +---- ok +-STATEMENT CREATE (t:test {prop: 264184}); +---- ok +-STATEMENT CREATE (t:test {prop: 75642}); +---- ok +-STATEMENT CREATE (t:test {prop: 158345}); +---- ok +-STATEMENT CREATE (t:test {prop: 826090}); +---- ok +-STATEMENT CREATE (t:test {prop: 53203}); +---- ok +-STATEMENT CREATE (t:test {prop: 279764}); +---- ok +-STATEMENT CREATE (t:test {prop: 599579}); +---- ok +-STATEMENT CREATE (t:test {prop: 276985}); +---- ok +-STATEMENT CREATE (t:test {prop: 864896}); +---- ok +-STATEMENT CREATE (t:test {prop: 173288}); +---- ok +-STATEMENT CREATE (t:test {prop: 36100}); +---- ok +-STATEMENT CREATE (t:test {prop: 279540}); +---- ok +-STATEMENT CREATE (t:test {prop: 364667}); +---- ok +-STATEMENT CREATE (t:test {prop: 524855}); +---- ok +-STATEMENT CREATE (t:test {prop: 257979}); +---- ok +-STATEMENT CREATE (t:test {prop: 824244}); +---- ok +-STATEMENT CREATE (t:test {prop: 559877}); +---- ok +-STATEMENT CREATE (t:test {prop: 144228}); +---- ok +-STATEMENT CREATE (t:test {prop: 851618}); +---- ok +-STATEMENT CREATE (t:test {prop: 127549}); +---- ok +-STATEMENT CREATE (t:test {prop: 526554}); +---- ok +-STATEMENT CREATE (t:test {prop: 667291}); +---- ok +-STATEMENT CREATE (t:test {prop: 621470}); +---- ok +-STATEMENT CREATE (t:test {prop: 108022}); +---- ok +-STATEMENT CREATE (t:test {prop: 338715}); +---- ok +-STATEMENT CREATE (t:test {prop: 948603}); +---- ok +-STATEMENT CREATE (t:test {prop: 620917}); +---- ok +-STATEMENT CREATE (t:test {prop: 49011}); +---- ok +-STATEMENT CREATE (t:test {prop: 724736}); +---- ok +-STATEMENT CREATE (t:test {prop: 419132}); +---- ok +-STATEMENT CREATE (t:test {prop: 288031}); +---- ok +-STATEMENT CREATE (t:test {prop: 198678}); +---- ok +-STATEMENT CREATE (t:test {prop: 91220}); +---- ok +-STATEMENT CREATE (t:test {prop: 349613}); +---- ok +-STATEMENT CREATE (t:test {prop: 725591}); +---- ok +-STATEMENT CREATE (t:test {prop: 530772}); +---- ok +-STATEMENT CREATE (t:test {prop: 591822}); +---- ok +-STATEMENT CREATE (t:test {prop: 960744}); +---- ok +-STATEMENT CREATE (t:test {prop: 967891}); +---- ok +-STATEMENT CREATE (t:test {prop: 338187}); +---- ok +-STATEMENT CREATE (t:test {prop: 966181}); +---- ok +-STATEMENT CREATE (t:test {prop: 124427}); +---- ok +-STATEMENT CREATE (t:test {prop: 48942}); +---- ok +-STATEMENT CREATE (t:test {prop: 180623}); +---- ok +-STATEMENT CREATE (t:test {prop: 537536}); +---- ok +-STATEMENT CREATE (t:test {prop: 603791}); +---- ok +-STATEMENT CREATE (t:test {prop: 793167}); +---- ok +-STATEMENT CREATE (t:test {prop: 889552}); +---- ok +-STATEMENT CREATE (t:test {prop: 957908}); +---- ok +-STATEMENT CREATE (t:test {prop: 80664}); +---- ok +-STATEMENT CREATE (t:test {prop: 620374}); +---- ok +-STATEMENT CREATE (t:test {prop: 112066}); +---- ok +-STATEMENT CREATE (t:test {prop: 420270}); +---- ok +-STATEMENT CREATE (t:test {prop: 971124}); +---- ok +-STATEMENT CREATE (t:test {prop: 532581}); +---- ok +-STATEMENT CREATE (t:test {prop: 606271}); +---- ok +-STATEMENT CREATE (t:test {prop: 398544}); +---- ok +-STATEMENT CREATE (t:test {prop: 463913}); +---- ok +-STATEMENT CREATE (t:test {prop: 756463}); +---- ok +-STATEMENT CREATE (t:test {prop: 765818}); +---- ok +-STATEMENT CREATE (t:test {prop: 470133}); +---- ok +-STATEMENT CREATE (t:test {prop: 656532}); +---- ok +-STATEMENT CREATE (t:test {prop: 282433}); +---- ok +-STATEMENT CREATE (t:test {prop: 290273}); +---- ok +-STATEMENT CREATE (t:test {prop: 185429}); +---- ok +-STATEMENT CREATE (t:test {prop: 762810}); +---- ok +-STATEMENT CREATE (t:test {prop: 805397}); +---- ok +-STATEMENT CREATE (t:test {prop: 808752}); +---- ok +-STATEMENT CREATE (t:test {prop: 297604}); +---- ok +-STATEMENT CREATE (t:test {prop: 850409}); +---- ok +-STATEMENT CREATE (t:test {prop: 946733}); +---- ok +-STATEMENT CREATE (t:test {prop: 689146}); +---- ok +-STATEMENT CREATE (t:test {prop: 152873}); +---- ok +-STATEMENT CREATE (t:test {prop: 831910}); +---- ok +-STATEMENT CREATE (t:test {prop: 755255}); +---- ok +-STATEMENT CREATE (t:test {prop: 445848}); +---- ok +-STATEMENT CREATE (t:test {prop: 489944}); +---- ok +-STATEMENT CREATE (t:test {prop: 413354}); +---- ok +-STATEMENT CREATE (t:test {prop: 587406}); +---- ok +-STATEMENT CREATE (t:test {prop: 128776}); +---- ok +-STATEMENT CREATE (t:test {prop: 705954}); +---- ok +-STATEMENT CREATE (t:test {prop: 535802}); +---- ok +-STATEMENT CREATE (t:test {prop: 524721}); +---- ok +-STATEMENT CREATE (t:test {prop: 969901}); +---- ok +-STATEMENT CREATE (t:test {prop: 653405}); +---- ok +-STATEMENT CREATE (t:test {prop: 85666}); +---- ok +-STATEMENT CREATE (t:test {prop: 936005}); +---- ok +-STATEMENT CREATE (t:test {prop: 828195}); +---- ok +-STATEMENT CREATE (t:test {prop: 9026}); +---- ok +-STATEMENT CREATE (t:test {prop: 370003}); +---- ok +-STATEMENT CREATE (t:test {prop: 905336}); +---- ok +-STATEMENT CREATE (t:test {prop: 911382}); +---- ok +-STATEMENT CREATE (t:test {prop: 333157}); +---- ok +-STATEMENT CREATE (t:test {prop: 969664}); +---- ok +-STATEMENT CREATE (t:test {prop: 938396}); +---- ok +-STATEMENT CREATE (t:test {prop: 81915}); +---- ok +-STATEMENT CREATE (t:test {prop: 337138}); +---- ok +-STATEMENT CREATE (t:test {prop: 297662}); +---- ok +-STATEMENT CREATE (t:test {prop: 898350}); +---- ok +-STATEMENT CREATE (t:test {prop: 233507}); +---- ok +-STATEMENT CREATE (t:test {prop: 337548}); +---- ok +-STATEMENT CREATE (t:test {prop: 28481}); +---- ok +-STATEMENT CREATE (t:test {prop: 825971}); +---- ok +-STATEMENT CREATE (t:test {prop: 935738}); +---- ok +-STATEMENT CREATE (t:test {prop: 479095}); +---- ok +-STATEMENT CREATE (t:test {prop: 156655}); +---- ok +-STATEMENT CREATE (t:test {prop: 447130}); +---- ok +-STATEMENT CREATE (t:test {prop: 238102}); +---- ok +-STATEMENT CREATE (t:test {prop: 522907}); +---- ok +-STATEMENT CREATE (t:test {prop: 913621}); +---- ok +-STATEMENT CREATE (t:test {prop: 28027}); +---- ok +-STATEMENT CREATE (t:test {prop: 829107}); +---- ok +-STATEMENT CREATE (t:test {prop: 660678}); +---- ok +-STATEMENT CREATE (t:test {prop: 77222}); +---- ok +-STATEMENT CREATE (t:test {prop: 637879}); +---- ok +-STATEMENT CREATE (t:test {prop: 516013}); +---- ok +-STATEMENT CREATE (t:test {prop: 730340}); +---- ok +-STATEMENT CREATE (t:test {prop: 634902}); +---- ok +-STATEMENT CREATE (t:test {prop: 472497}); +---- ok +-STATEMENT CREATE (t:test {prop: 264664}); +---- ok +-STATEMENT CREATE (t:test {prop: 792190}); +---- ok +-STATEMENT CREATE (t:test {prop: 525298}); +---- ok +-STATEMENT CREATE (t:test {prop: 576861}); +---- ok +-STATEMENT CREATE (t:test {prop: 153680}); +---- ok +-STATEMENT CREATE (t:test {prop: 403722}); +---- ok +-STATEMENT CREATE (t:test {prop: 587637}); +---- ok +-STATEMENT CREATE (t:test {prop: 138366}); +---- ok +-STATEMENT CREATE (t:test {prop: 392685}); +---- ok +-STATEMENT CREATE (t:test {prop: 328420}); +---- ok +-STATEMENT CREATE (t:test {prop: 378700}); +---- ok +-STATEMENT CREATE (t:test {prop: 145425}); +---- ok +-STATEMENT CREATE (t:test {prop: 569065}); +---- ok +-STATEMENT CREATE (t:test {prop: 746558}); +---- ok +-STATEMENT CREATE (t:test {prop: 815737}); +---- ok +-STATEMENT CREATE (t:test {prop: 874755}); +---- ok +-STATEMENT CREATE (t:test {prop: 267972}); +---- ok +-STATEMENT CREATE (t:test {prop: 898635}); +---- ok +-STATEMENT CREATE (t:test {prop: 981082}); +---- ok +-STATEMENT CREATE (t:test {prop: 125680}); +---- ok +-STATEMENT CREATE (t:test {prop: 270386}); +---- ok +-STATEMENT CREATE (t:test {prop: 805762}); +---- ok +-STATEMENT CREATE (t:test {prop: 498413}); +---- ok +-STATEMENT CREATE (t:test {prop: 407375}); +---- ok +-STATEMENT CREATE (t:test {prop: 373157}); +---- ok +-STATEMENT CREATE (t:test {prop: 16370}); +---- ok +-STATEMENT CREATE (t:test {prop: 729287}); +---- ok +-STATEMENT CREATE (t:test {prop: 829570}); +---- ok +-STATEMENT CREATE (t:test {prop: 644381}); +---- ok +-STATEMENT CREATE (t:test {prop: 515351}); +---- ok +-STATEMENT CREATE (t:test {prop: 564057}); +---- ok +-STATEMENT CREATE (t:test {prop: 56987}); +---- ok +-STATEMENT CREATE (t:test {prop: 277626}); +---- ok +-STATEMENT CREATE (t:test {prop: 765395}); +---- ok +-STATEMENT CREATE (t:test {prop: 224997}); +---- ok +-STATEMENT CREATE (t:test {prop: 989916}); +---- ok +-STATEMENT CREATE (t:test {prop: 40598}); +---- ok +-STATEMENT CREATE (t:test {prop: 950712}); +---- ok +-STATEMENT CREATE (t:test {prop: 780027}); +---- ok +-STATEMENT CREATE (t:test {prop: 933336}); +---- ok +-STATEMENT CREATE (t:test {prop: 679841}); +---- ok +-STATEMENT CREATE (t:test {prop: 202955}); +---- ok +-STATEMENT CREATE (t:test {prop: 587949}); +---- ok +-STATEMENT CREATE (t:test {prop: 931835}); +---- ok +-STATEMENT CREATE (t:test {prop: 382848}); +---- ok +-STATEMENT CREATE (t:test {prop: 207304}); +---- ok +-STATEMENT CREATE (t:test {prop: 266080}); +---- ok +-STATEMENT CREATE (t:test {prop: 36132}); +---- ok +-STATEMENT CREATE (t:test {prop: 548226}); +---- ok +-STATEMENT CREATE (t:test {prop: 285597}); +---- ok +-STATEMENT CREATE (t:test {prop: 161323}); +---- ok +-STATEMENT CREATE (t:test {prop: 573711}); +---- ok +-STATEMENT CREATE (t:test {prop: 690505}); +---- ok +-STATEMENT CREATE (t:test {prop: 119956}); +---- ok +-STATEMENT CREATE (t:test {prop: 330611}); +---- ok +-STATEMENT CREATE (t:test {prop: 943669}); +---- ok +-STATEMENT CREATE (t:test {prop: 489704}); +---- ok +-STATEMENT CREATE (t:test {prop: 794946}); +---- ok +-STATEMENT CREATE (t:test {prop: 577563}); +---- ok +-STATEMENT CREATE (t:test {prop: 512300}); +---- ok +-STATEMENT CREATE (t:test {prop: 570799}); +---- ok +-STATEMENT CREATE (t:test {prop: 195906}); +---- ok +-STATEMENT CREATE (t:test {prop: 319414}); +---- ok +-STATEMENT CREATE (t:test {prop: 724702}); +---- ok +-STATEMENT CREATE (t:test {prop: 625522}); +---- ok +-STATEMENT CREATE (t:test {prop: 307766}); +---- ok +-STATEMENT CREATE (t:test {prop: 179447}); +---- ok +-STATEMENT CREATE (t:test {prop: 334245}); +---- ok +-STATEMENT CREATE (t:test {prop: 260494}); +---- ok +-STATEMENT CREATE (t:test {prop: 792524}); +---- ok +-STATEMENT CREATE (t:test {prop: 232508}); +---- ok +-STATEMENT CREATE (t:test {prop: 245971}); +---- ok +-STATEMENT CREATE (t:test {prop: 499139}); +---- ok +-STATEMENT CREATE (t:test {prop: 311007}); +---- ok +-STATEMENT CREATE (t:test {prop: 195960}); +---- ok +-STATEMENT CREATE (t:test {prop: 794317}); +---- ok +-STATEMENT CREATE (t:test {prop: 760389}); +---- ok +-STATEMENT CREATE (t:test {prop: 16392}); +---- ok +-STATEMENT CREATE (t:test {prop: 687863}); +---- ok +-STATEMENT CREATE (t:test {prop: 440770}); +---- ok +-STATEMENT CREATE (t:test {prop: 160488}); +---- ok +-STATEMENT CREATE (t:test {prop: 471704}); +---- ok +-STATEMENT CREATE (t:test {prop: 822058}); +---- ok +-STATEMENT CREATE (t:test {prop: 450933}); +---- ok +-STATEMENT CREATE (t:test {prop: 183194}); +---- ok +-STATEMENT CREATE (t:test {prop: 590748}); +---- ok +-STATEMENT CREATE (t:test {prop: 828685}); +---- ok +-STATEMENT CREATE (t:test {prop: 383426}); +---- ok +-STATEMENT MATCH (t:test) RETURN SUM(t.prop); +---- 1 +5019488576 diff --git a/test/test_files/update_node/create_read_tinysnb.test b/test/test_files/update_node/create_read_tinysnb.test index 52453a173dd..d97bfc34a9d 100644 --- a/test/test_files/update_node/create_read_tinysnb.test +++ b/test/test_files/update_node/create_read_tinysnb.test @@ -4,6 +4,19 @@ -- -CASE CreateNodeRead1 +-STATEMENT CREATE (a:person {ID:91, fName:'dummy'}) WITH a MATCH (b:person) WHERE b.ID > 9 RETURN a.ID, a.fName, b.ID, b.fName; +---- 2 +91|dummy|10|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff +91|dummy|91|dummy +-STATEMENT CREATE (a:person {ID:93, fName:'dummy'}) WITH a MATCH (b:person) WHERE b.ID = a.ID - 90 RETURN a.ID, a.fName, b.ID, b.fName; +---- 1 +93|dummy|3|Carol +-STATEMENT MATCH (a:person) WHERE a.ID < 3 CREATE (b:person {ID:a.ID+100, fName:a.fName}) WITH a, b MATCH (c:person) WHERE c.ID > 99 RETURN a.ID, a.fName, b.ID, b.fName, c.ID, c.fName; +---- 4 +0|Alice|100|Alice|100|Alice +0|Alice|100|Alice|102|Bob +2|Bob|102|Bob|100|Alice +2|Bob|102|Bob|102|Bob -STATEMENT CREATE (a:person {ID:80, isWorker:true,age:22,eyeSight:1.1}) RETURN a.ID, a.age, a.fName, a.eyeSight; ---- 1 80|22||1.100000 @@ -11,6 +24,18 @@ ---- 1 {_ID: 1:3, _LABEL: organisation, ID: 0, name: test}| + +-CASE OptionalMatchAfterInsert +-STATEMENT CREATE (a:person {ID:200, fName:'test'}) WITH a OPTIONAL MATCH (b:person) RETURN COUNT(*); +---- 1 +9 +-STATEMENT CREATE (a:person {ID:201, fName:'test'}) WITH a OPTIONAL MATCH (b:person) WHERE b.ID > a.ID RETURN COUNT(b); +---- error +Runtime exception: Optional match after update is not supported. Missing right outer join implementation. +-STATEMENT CREATE (a:person {ID:202, fName:'test'}) WITH a OPTIONAL MATCH (a)-[]->(b) RETURN COUNT(*); +---- error +Runtime exception: Optional match after update is not supported. Missing right outer join implementation. + -CASE CreateNodeRead2 -STATEMENT MATCH (a:person) WHERE a.ID < 3 CREATE (b:person {ID: a.ID + 11, fName: 'new', age:a.age * 2}) RETURN a.ID, a.fName, a.age, b.ID, b.fName, b.age diff --git a/test/test_files/update_node/delete_tinysnb.test b/test/test_files/update_node/delete_tinysnb.test index b20d4dc7930..2b6c9846428 100644 --- a/test/test_files/update_node/delete_tinysnb.test +++ b/test/test_files/update_node/delete_tinysnb.test @@ -13,6 +13,11 @@ -STATEMENT MATCH (a:person) WHERE a.ID = 101 RETURN a.ID, a.fName, a.age ---- 1 101|| +-STATEMENT MATCH (a:person) WHERE a.ID = 0 DETACH DELETE a WITH a MATCH (b:person) WHERE b.ID < 6 RETURN a.ID, b.ID; +---- 3 +0|2 +0|3 +0|5 -CASE MixedDeleteInsertTest -STATEMENT CREATE (a:organisation {ID:30, mark:3.3}) @@ -68,7 +73,6 @@ 9 10 - -CASE OptionalDelete -STATEMENT OPTIONAL MATCH (a:person) WHERE a.ID > 100 DELETE a; ---- ok @@ -110,3 +114,9 @@ Runtime exception: Node(nodeOffset: 2) has connected edges in table workAt in th -STATEMENT MATCH (a:person) RETURN COUNT(*) ---- 1 8 + +-CASE DeleteNodeWithSemiMaskBug +-STATEMENT MATCH (a) WHERE a.ID = 0 OR a.ID = 3 OR a.ID= 5 DETACH DELETE a; +---- ok +-STATEMENT MATCH (a:person)-[:knows]->(b:person) WHERE b.ID = 2 RETURN a.fName, b.fName; +---- 0 diff --git a/test/test_files/update_node/merge_tinysnb.test b/test/test_files/update_node/merge_tinysnb.test index b25b0a0a843..b2e1c8c91c0 100644 --- a/test/test_files/update_node/merge_tinysnb.test +++ b/test/test_files/update_node/merge_tinysnb.test @@ -60,3 +60,38 @@ Runtime exception: Found duplicated primary key value 1, which violates the uniq -STATEMENT MATCH (a:person) RETURN COUNT(*); ---- 1 11 + +-CASE MergeDuplicatedKey +-STATEMENT CREATE NODE TABLE user (ID int64, primary key(ID)) +---- ok +-STATEMENT MATCH (a:person) with a.ID % 4 as result, a.age as age MERGE (u:user {ID: result}) RETURN u.ID, age +---- 8 +0|35 +2|30 +3|45 +1|20 +3|20 +0|25 +1|40 +2|83 +-STATEMENT MATCH (a:user) RETURN a.ID +---- 4 +0 +1 +2 +3 +-STATEMENT MATCH (a:person) with a.ID as id MERGE (u:user {ID: 10}) RETURN u.ID, id +---- error +Runtime exception: Constant key in merge clause is not supported yet. +-STATEMENT CREATE NODE TABLE user1 (ID int64, name string, primary key(ID)) +---- ok +-STATEMENT MATCH (a:person) with a.ID % 7 as result, a.fName as name MERGE (u:user1 {ID: result}) ON MATCH SET u.name = 'match: ' + name ON CREATE SET u.name = 'create: ' + name RETURN u.ID, u.name +---- 8 +0|create: Alice +0|match: Elizabeth +1|create: Farooq +2|create: Bob +2|match: Greg +3|create: Carol +3|match: Hubert Blaine Wolfeschlegelsteinhausenbergerdorff +5|create: Dan diff --git a/test/test_files/update_node/set_read.test b/test/test_files/update_node/set_read.test index fcf4277d9c2..fd4ca398bb3 100644 --- a/test/test_files/update_node/set_read.test +++ b/test/test_files/update_node/set_read.test @@ -19,6 +19,15 @@ -STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age, a.gender, a.fName ---- 1 70|1| +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName = 'XX' WITH a MATCH (b:person) WHERE b.ID < 6 RETURN a.ID, a.fName, b.ID, b.fName; +---- 4 +0|XX|0|XX +0|XX|2|Bob +0|XX|3|Carol +0|XX|5|Dan +-STATEMENT MATCH (a:person) WHERE a.ID=2 SET a.fName = 'BB' WITH a MATCH (b:person) WHERE b.ID=a.ID RETURN a.ID, a.fName, b.ID, b.fName; +---- 1 +2|BB|2|BB -CASE SetReadTest2 -STATEMENT CREATE NODE TABLE play(ID INT64, name STRING, PRIMARY KEY(ID)); diff --git a/test/test_files/update_node/set_tinysnb.test b/test/test_files/update_node/set_tinysnb.test index f5cfac72c99..4a66f7286e8 100644 --- a/test/test_files/update_node/set_tinysnb.test +++ b/test/test_files/update_node/set_tinysnb.test @@ -3,86 +3,86 @@ -- -#-CASE SetNodeInt64PropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.age=20 + 50 -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age -#---- 1 -#70 -# -#-CASE SetNodeInt32PropTest -#-STATEMENT MATCH (a:movies) WHERE a.name='Roma' SET a.length=2.2 -#---- ok -#-STATEMENT MATCH (a:movies) WHERE a.name='Roma' RETURN a.length -#---- 1 -#2 -# -#-CASE SetNodeDoublePropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.eyeSight=1.0 -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.eyeSight -#---- 1 -#1.000000 -# -#-CASE SetNodeFloatPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.height=12 -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.height -#---- 1 -#12.000000 -# -#-CASE SetNodeBoolPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.isStudent=false -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.isStudent -#---- 1 -#False -# -#-CASE SetNodeDatePropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.birthdate=date('2200-10-10') -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.birthdate -#---- 1 -#2200-10-10 -# -#-CASE SetNodeTimestampPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.registerTime=timestamp('2200-10-10 12:01:01') -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.registerTime -#---- 1 -#2200-10-10 12:01:01 -# -#-CASE SetNodeEmptyStringPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName='' -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName -#---- 1 -# -## end of SetNodeEmptyStringPropTest -# -#-CASE SetNodeShortStringPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName=string(22) -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName -#---- 1 -#22 -# -#-CASE SetNodeLongStringPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName='abcdefghijklmnopqrstuvwxyz' -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName -#---- 1 -#abcdefghijklmnopqrstuvwxyz -# -#-CASE SetLongListTest -#-DEFINE STRING_EXCEEDS_PAGE ARANGE 0 5990 -#-STATEMENT BEGIN TRANSACTION -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName="${STRING_EXCEEDS_PAGE}" -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName; -#---- 1 -#${STRING_EXCEEDS_PAGE} +-CASE SetNodeInt64PropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.age=20 + 50 +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age +---- 1 +70 + +-CASE SetNodeInt32PropTest +-STATEMENT MATCH (a:movies) WHERE a.name='Roma' SET a.length=2.2 +---- ok +-STATEMENT MATCH (a:movies) WHERE a.name='Roma' RETURN a.length +---- 1 +2 + +-CASE SetNodeDoublePropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.eyeSight=1.0 +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.eyeSight +---- 1 +1.000000 + +-CASE SetNodeFloatPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.height=12 +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.height +---- 1 +12.000000 + +-CASE SetNodeBoolPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.isStudent=false +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.isStudent +---- 1 +False + +-CASE SetNodeDatePropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.birthdate=date('2200-10-10') +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.birthdate +---- 1 +2200-10-10 + +-CASE SetNodeTimestampPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.registerTime=timestamp('2200-10-10 12:01:01') +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.registerTime +---- 1 +2200-10-10 12:01:01 + +-CASE SetNodeEmptyStringPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName='' +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName +---- 1 + +# end of SetNodeEmptyStringPropTest + +-CASE SetNodeShortStringPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName=string(22) +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName +---- 1 +22 + +-CASE SetNodeLongStringPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName='abcdefghijklmnopqrstuvwxyz' +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName +---- 1 +abcdefghijklmnopqrstuvwxyz + +-CASE SetLongListTest +-DEFINE STRING_EXCEEDS_PAGE ARANGE 0 5990 +-STATEMENT BEGIN TRANSACTION +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.fName="${STRING_EXCEEDS_PAGE}" +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.fName; +---- 1 +${STRING_EXCEEDS_PAGE} -CASE SetVeryLongListErrorsTest -DEFINE STRING_EXCEEDS_MEMORY_MANAGER_LIMIT ARANGE 0 50000 @@ -95,245 +95,245 @@ ---- hash 1 1c6f2aee653d75dfc2361ff73d5807f7 -#-CASE SetNodeIntervalPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.lastJobDuration=interval('1 years 1 days') -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.lastJobDuration -#---- 1 -#1 year 1 day -# -#-CASE SetNodePropNullTest -#-STATEMENT MATCH (a:person) SET a.age=null -#---- ok -#-STATEMENT MATCH (a:person) RETURN a.age -#---- 8 -# -# -# -# -# -# -# -# -## end of SetNodePropNullTest. Empty lines represent the expected null values -# -#-CASE SetBothUnflatTest -#-STATEMENT MATCH (a:person) SET a.age=a.ID -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID < 4 RETURN a.ID, a.age -#---- 3 -#0|0 -#2|2 -#3|3 -# -#-CASE SetFlatUnFlatTest -#-STATEMENT MATCH (a:person)-[:knows]->(b:person) WHERE a.ID=0 SET a.age=b.age -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID < 4 RETURN a.ID, a.age -#---- 3 -#0|20 -#2|30 -#3|45 -# -#-CASE SetUnFlatFlatTest -#-STATEMENT MATCH (a:person)-[:knows]->(b:person) WHERE b.ID=2 AND a.ID = 0 SET b.age=a.age -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID < 4 RETURN a.ID, a.age -#---- 3 -#0|35 -#2|35 -#3|45 -# -#-CASE SetTwoHopTest -#-STATEMENT MATCH (a:person)-[:knows]->(b:person)-[:knows]->(c:person) WHERE b.ID=0 AND c.fName = 'Bob' SET a.age=c.age -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID < 6 RETURN a.ID, a.age -#---- 4 -#0|35 -#2|30 -#3|30 -#5|30 -# -#-CASE SetTwoHopNullTest -#-STATEMENT MATCH (a:person)-[:knows]->(b:person)-[:knows]->(c:person) SET a.age=null -#---- ok -#-STATEMENT MATCH (a:person) RETURN a.ID, a.age -#---- 8 -#0| -#10|83 -#2| -#3| -#5| -#7|20 -#8|25 -#9|40 -# -#-CASE SetIndexNestedLoopJoinTest -#-STATEMENT MATCH (a:person), (b:person) WHERE a.ID = b.ID SET a.age=b.gender -#---- ok -#-STATEMENT MATCH (a:person) RETURN a.ID, a.age -#---- 8 -#0|1 -#10|2 -#2|2 -#3|1 -#5|2 -#7|1 -#8|2 -#9|2 -# -#-CASE SetRelInt16PropTest -#-STATEMENT MATCH (a:person)-[e:studyAt]->(b:organisation) WHERE a.ID = 0 SET e.length=99 -#---- ok -#-STATEMENT MATCH (a:person)-[e:studyAt]->(b:organisation) RETURN e.length -#---- 3 -#22 -#55 -#99 -# -#-CASE SetNodeListOfIntPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.workedHours=[10,20] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.workedHours -#---- 1 -#[10,20] -# -#-CASE SetNodeListOfShortStringPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.usedNames=['intel','microsoft'] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.usedNames -#---- 1 -#[intel,microsoft] -# -#-CASE SetNodeListOfLongStringPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.usedNames -#---- 1 -#[abcndwjbwesdsd,microsofthbbjuwgedsd] -# -#-CASE SetNodeListofListPropTest -#-STATEMENT MATCH (a:person) WHERE a.ID=8 SET a.courseScoresPerTerm=[[10,20],[0,0,0]] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=8 RETURN a.courseScoresPerTerm -#---- 1 -#[[10,20],[0,0,0]] -# -#-CASE SETMultiLabelNodePropTest -#-STATEMENT MATCH (a) WHERE a.ID < 2 SET a.age = 1; -#---- ok -#-STATEMENT MATCH (a) WHERE a.ID < 2 RETURN a.ID, a.age; -#---- 2 -#0|1 -#1| -#-STATEMENT CREATE NODE TABLE play(ID INT64, name STRING, PRIMARY KEY(ID)); -#---- ok -#-STATEMENT CREATE (a:play {ID: 0, name: 'AA'}); -#---- ok -#-STATEMENT MATCH (a:organisation:play) RETURN a.ID, a.name; -#---- 4 -#0|AA -#1|ABFsUni -#4|CsWork -#6|DEsWork -#-STATEMENT MATCH (a:organisation:play) WHERE a.ID < 2 SET a.name = string(a.ID * 10); -#---- ok -#-STATEMENT MATCH (a:organisation:play) WHERE a.ID < 2 RETURN a.ID, a.name; -#---- 2 -#0|0 -#1|10 -# -#-CASE SETMultiLabelWithPruning -#-STATEMENT MATCH (a:person)-[:knows]->(b) WHERE a.ID=0 SET b.name = "a", b.fName = "XX" RETURN b.name, b.fName; -#---- 3 -#|XX -#|XX -#|XX -#-STATEMENT MATCH (b) RETURN b.name, b.fName -#---- 14 -#ABFsUni| -#CsWork| -#DEsWork| -#Roma| -#Sóló cón tu párejâ| -#The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie| -#|Alice -#|Elizabeth -#|Farooq -#|Greg -#|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff -#|XX -#|XX -#|XX -#-STATEMENT MATCH (a:person)-[e:knows|:studyAt]->(b:person) WHERE a.ID=0 SET e.year = 2023, e.date = date("2023-11-11") RETURN e.year, e.date; -#---- 3 -#|2023-11-11 -#|2023-11-11 -#|2023-11-11 -#-STATEMENT MATCH (a:person)-[e:knows|:studyAt]->(b:person:organisation) WHERE a.ID=0 RETURN e.year, e.date; -#---- 4 -#2021| -#|2023-11-11 -#|2023-11-11 -#|2023-11-11 -# -#-CASE SetNonNullValueWithWriteTransaction -#-STATEMENT BEGIN TRANSACTION -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age -#---- 1 -#35 -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.age=70 -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age -#---- 1 -#70 -# -#-CASE SetNullValueWithWriteTransaction -#-STATEMENT BEGIN TRANSACTION -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age -#---- 1 -#35 -#-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.age=NULL -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age -#---- 1 -# -#-CASE MultipleSetListValue -#-STATEMENT BEGIN TRANSACTION -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=10 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=5 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=2 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=3 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] -#---- ok -#-STATEMENT COMMIT -#---- ok -#-STATEMENT MATCH (a:person) WHERE a.ID=10 RETURN a.usedNames -#---- 1 -#[abcndwjbwesdsd,microsofthbbjuwgedsd] -#-STATEMENT MATCH (a:person) WHERE a.ID=5 RETURN a.usedNames -#---- 1 -#[abcndwjbwesdsd,microsofthbbjuwgedsd] -# -# -#-CASE OptionalSET -#-STATEMENT OPTIONAL MATCH (a:person) WHERE a.ID > 100 SET a.fName = 'a' RETURN a.fName; -#---- 1 -# -#-STATEMENT MATCH (a:person) WHERE a.ID < 3 RETURN a.fName; -#---- 2 -#Alice -#Bob -#-STATEMENT OPTIONAL MATCH (a) WHERE a.ID > 100 SET a.name, a.fName; -#----1 -# -#-STATEMENT MATCH (a) WHERE a.ID < 3 RETURN a.name, a.fName; -#---- 3 -#ABFsUni| -#|Alice -#|Bob +-CASE SetNodeIntervalPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.lastJobDuration=interval('1 years 1 days') +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.lastJobDuration +---- 1 +1 year 1 day + +-CASE SetNodePropNullTest +-STATEMENT MATCH (a:person) SET a.age=null +---- ok +-STATEMENT MATCH (a:person) RETURN a.age +---- 8 + + + + + + + + +# end of SetNodePropNullTest. Empty lines represent the expected null values + +-CASE SetBothUnflatTest +-STATEMENT MATCH (a:person) SET a.age=a.ID +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID < 4 RETURN a.ID, a.age +---- 3 +0|0 +2|2 +3|3 + +-CASE SetFlatUnFlatTest +-STATEMENT MATCH (a:person)-[:knows]->(b:person) WHERE a.ID=0 SET a.age=b.age +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID < 4 RETURN a.ID, a.age +---- 3 +0|20 +2|30 +3|45 + +-CASE SetUnFlatFlatTest +-STATEMENT MATCH (a:person)-[:knows]->(b:person) WHERE b.ID=2 AND a.ID = 0 SET b.age=a.age +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID < 4 RETURN a.ID, a.age +---- 3 +0|35 +2|35 +3|45 + +-CASE SetTwoHopTest +-STATEMENT MATCH (a:person)-[:knows]->(b:person)-[:knows]->(c:person) WHERE b.ID=0 AND c.fName = 'Bob' SET a.age=c.age +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID < 6 RETURN a.ID, a.age +---- 4 +0|35 +2|30 +3|30 +5|30 + +-CASE SetTwoHopNullTest +-STATEMENT MATCH (a:person)-[:knows]->(b:person)-[:knows]->(c:person) SET a.age=null +---- ok +-STATEMENT MATCH (a:person) RETURN a.ID, a.age +---- 8 +0| +10|83 +2| +3| +5| +7|20 +8|25 +9|40 + +-CASE SetIndexNestedLoopJoinTest +-STATEMENT MATCH (a:person), (b:person) WHERE a.ID = b.ID SET a.age=b.gender +---- ok +-STATEMENT MATCH (a:person) RETURN a.ID, a.age +---- 8 +0|1 +10|2 +2|2 +3|1 +5|2 +7|1 +8|2 +9|2 + +-CASE SetRelInt16PropTest +-STATEMENT MATCH (a:person)-[e:studyAt]->(b:organisation) WHERE a.ID = 0 SET e.length=99 +---- ok +-STATEMENT MATCH (a:person)-[e:studyAt]->(b:organisation) RETURN e.length +---- 3 +22 +55 +99 + +-CASE SetNodeListOfIntPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.workedHours=[10,20] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.workedHours +---- 1 +[10,20] + +-CASE SetNodeListOfShortStringPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.usedNames=['intel','microsoft'] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.usedNames +---- 1 +[intel,microsoft] + +-CASE SetNodeListOfLongStringPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.usedNames +---- 1 +[abcndwjbwesdsd,microsofthbbjuwgedsd] + +-CASE SetNodeListofListPropTest +-STATEMENT MATCH (a:person) WHERE a.ID=8 SET a.courseScoresPerTerm=[[10,20],[0,0,0]] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=8 RETURN a.courseScoresPerTerm +---- 1 +[[10,20],[0,0,0]] + +-CASE SETMultiLabelNodePropTest +-STATEMENT MATCH (a) WHERE a.ID < 2 SET a.age = 1; +---- ok +-STATEMENT MATCH (a) WHERE a.ID < 2 RETURN a.ID, a.age; +---- 2 +0|1 +1| +-STATEMENT CREATE NODE TABLE play(ID INT64, name STRING, PRIMARY KEY(ID)); +---- ok +-STATEMENT CREATE (a:play {ID: 0, name: 'AA'}); +---- ok +-STATEMENT MATCH (a:organisation:play) RETURN a.ID, a.name; +---- 4 +0|AA +1|ABFsUni +4|CsWork +6|DEsWork +-STATEMENT MATCH (a:organisation:play) WHERE a.ID < 2 SET a.name = string(a.ID * 10); +---- ok +-STATEMENT MATCH (a:organisation:play) WHERE a.ID < 2 RETURN a.ID, a.name; +---- 2 +0|0 +1|10 + +-CASE SETMultiLabelWithPruning +-STATEMENT MATCH (a:person)-[:knows]->(b) WHERE a.ID=0 SET b.name = "a", b.fName = "XX" RETURN b.name, b.fName; +---- 3 +|XX +|XX +|XX +-STATEMENT MATCH (b) RETURN b.name, b.fName +---- 14 +ABFsUni| +CsWork| +DEsWork| +Roma| +Sóló cón tu párejâ| +The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie| +|Alice +|Elizabeth +|Farooq +|Greg +|Hubert Blaine Wolfeschlegelsteinhausenbergerdorff +|XX +|XX +|XX +-STATEMENT MATCH (a:person)-[e:knows|:studyAt]->(b:person) WHERE a.ID=0 SET e.year = 2023, e.date = date("2023-11-11") RETURN e.year, e.date; +---- 3 +|2023-11-11 +|2023-11-11 +|2023-11-11 +-STATEMENT MATCH (a:person)-[e:knows|:studyAt]->(b:person:organisation) WHERE a.ID=0 RETURN e.year, e.date; +---- 4 +2021| +|2023-11-11 +|2023-11-11 +|2023-11-11 + +-CASE SetNonNullValueWithWriteTransaction +-STATEMENT BEGIN TRANSACTION +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age +---- 1 +35 +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.age=70 +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age +---- 1 +70 + +-CASE SetNullValueWithWriteTransaction +-STATEMENT BEGIN TRANSACTION +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age +---- 1 +35 +-STATEMENT MATCH (a:person) WHERE a.ID=0 SET a.age=NULL +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=0 RETURN a.age +---- 1 + +-CASE MultipleSetListValue +-STATEMENT BEGIN TRANSACTION +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=10 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=5 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=2 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=3 SET a.usedNames=['abcndwjbwesdsd','microsofthbbjuwgedsd'] +---- ok +-STATEMENT COMMIT +---- ok +-STATEMENT MATCH (a:person) WHERE a.ID=10 RETURN a.usedNames +---- 1 +[abcndwjbwesdsd,microsofthbbjuwgedsd] +-STATEMENT MATCH (a:person) WHERE a.ID=5 RETURN a.usedNames +---- 1 +[abcndwjbwesdsd,microsofthbbjuwgedsd] + + +-CASE OptionalSET +-STATEMENT OPTIONAL MATCH (a:person) WHERE a.ID > 100 SET a.fName = 'a' RETURN a.fName; +---- 1 + +-STATEMENT MATCH (a:person) WHERE a.ID < 3 RETURN a.fName; +---- 2 +Alice +Bob +-STATEMENT OPTIONAL MATCH (a) WHERE a.ID > 100 SET a.name, a.fName; +----1 + +-STATEMENT MATCH (a) WHERE a.ID < 3 RETURN a.name, a.fName; +---- 3 +ABFsUni| +|Alice +|Bob diff --git a/test/test_files/update_rel/create_empty.test b/test/test_files/update_rel/create_empty.test index 0703d6d67e2..79b7d45212a 100644 --- a/test/test_files/update_rel/create_empty.test +++ b/test/test_files/update_rel/create_empty.test @@ -182,6 +182,9 @@ ---- ok -STATEMENT MATCH (n1:N1), (n2:N2) WHERE n1.ID=10 AND n2.ID=12 CREATE (n1)-[r:Rel1]->(n2) ---- ok +-STATEMENT MATCH (n1:N1)-[r:Rel1]->(n2:N2) WHERE n1.ID=10 AND n2.ID=12 RETURN r +---- 1 +(0:0)-{_LABEL: Rel1, _ID: 2:0}->(1:0) -STATEMENT MATCH (n1:N1)-[r:Rel1]->(n2:N2) WHERE n1.ID=10 AND n2.ID=12 DELETE r ---- ok -STATEMENT MATCH (n:N1)-[r:Rel1]->(m:N2) RETURN n.ID, m.ID diff --git a/test/test_files/update_rel/create_read_tinysnb.test b/test/test_files/update_rel/create_read_tinysnb.test index eda65f2d098..4d9fe9dd754 100644 --- a/test/test_files/update_rel/create_read_tinysnb.test +++ b/test/test_files/update_rel/create_read_tinysnb.test @@ -5,26 +5,38 @@ -CASE CreateRelRead1 -STATEMENT MATCH (a:person), (b:person) WHERE a.ID = 0 AND b.ID = 2 CREATE (a)-[e:knows {date:date('2023-03-03')}]->(b) RETURN id(e), e.date; ---- 1 -0:14|2023-03-03 +3:14|2023-03-03 -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 AND b.ID = 2 RETURN e; ---- 2 (0:0)-{_LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}}->(0:1) (0:0)-{_LABEL: knows, _ID: 3:14, date: 2023-03-03}->(0:1) -STATEMENT MATCH (a:person), (b:person) WHERE a.ID = 0 AND b.ID = 2 CREATE (a)-[e:knows {date:date('2023-04-04')}]->(b) RETURN e; ---- 1 -(0:0)-{_LABEL: knows, _ID: 0:15, date: 2023-04-04}->(0:1) +(0:0)-{_LABEL: knows, _ID: 3:15, date: 2023-04-04}->(0:1) -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 AND b.ID = 2 RETURN e; ---- 3 (0:0)-{_LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}}->(0:1) (0:0)-{_LABEL: knows, _ID: 3:14, date: 2023-03-03}->(0:1) (0:0)-{_LABEL: knows, _ID: 3:15, date: 2023-04-04}->(0:1) +-STATEMENT MATCH (a:person), (b:person) WHERE a.ID = 0 AND b.ID = 2 CREATE (a)-[e:knows {date:date('2024-01-01')}]-(b) WITH a MATCH (a)-[e:knows]->(b) RETURN a.fName, e.date, b.fName; +---- 6 +Alice|2021-06-30|Bob +Alice|2021-06-30|Carol +Alice|2021-06-30|Dan +Alice|2023-03-03|Bob +Alice|2023-04-04|Bob +Alice|2024-01-01|Bob +-STATEMENT MATCH (a:person), (b:person) WHERE a.ID = 0 AND b.ID = 2 CREATE (a)-[e:knows {date:date('2023-12-20')}]-(b) WITH a, e MATCH (a)-[e2:knows]->(b) WHERE e.date<=e2.date RETURN a.fName, e.date, e2.date, b.fName; +---- 2 +Alice|2023-12-20|2023-12-20|Bob +Alice|2023-12-20|2024-01-01|Bob -CASE CreateRelRead2 -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 CREATE (a)-[f:knows {date:date('2023-04-04')}]->(b) RETURN f; ---- 3 -(0:0)-{_LABEL: knows, _ID: 0:14, date: 2023-04-04}->(0:1) -(0:0)-{_LABEL: knows, _ID: 0:15, date: 2023-04-04}->(0:2) -(0:0)-{_LABEL: knows, _ID: 0:16, date: 2023-04-04}->(0:3) +(0:0)-{_LABEL: knows, _ID: 3:14, date: 2023-04-04}->(0:1) +(0:0)-{_LABEL: knows, _ID: 3:15, date: 2023-04-04}->(0:2) +(0:0)-{_LABEL: knows, _ID: 3:16, date: 2023-04-04}->(0:3) -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 RETURN e; ---- 6 (0:0)-{_LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}}->(0:1) diff --git a/test/test_files/update_rel/delete_tinysnb.test b/test/test_files/update_rel/delete_tinysnb.test index afb7e44c240..acec18d8748 100644 --- a/test/test_files/update_rel/delete_tinysnb.test +++ b/test/test_files/update_rel/delete_tinysnb.test @@ -14,6 +14,20 @@ -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID=0 RETURN COUNT(*) ---- 1 2 +-STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID=2 AND b.ID = 0 DELETE e WITH e MATCH (a:person)-[e2:knows]->(b:person) RETURN e.date, a.fName, e2.date, b.fName; +---- 12 +2021-06-30|Alice|2021-06-30|Bob +2021-06-30|Alice|2021-06-30|Dan +2021-06-30|Bob|1950-05-14|Carol +2021-06-30|Bob|1950-05-14|Dan +2021-06-30|Carol|1950-05-14|Bob +2021-06-30|Carol|2000-01-01|Dan +2021-06-30|Carol|2021-06-30|Alice +2021-06-30|Dan|1950-05-14|Bob +2021-06-30|Dan|2000-01-01|Carol +2021-06-30|Dan|2021-06-30|Alice +2021-06-30|Elizabeth|1905-12-12|Farooq +2021-06-30|Elizabeth|1905-12-12|Greg -CASE DeleteFromKnows2 -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID=0 AND b.ID>=3 DELETE e diff --git a/test/test_files/update_rel/merge_tinysnb.test b/test/test_files/update_rel/merge_tinysnb.test index 08ea21fa05a..0705a325fde 100644 --- a/test/test_files/update_rel/merge_tinysnb.test +++ b/test/test_files/update_rel/merge_tinysnb.test @@ -32,7 +32,7 @@ -CASE Merge3 -STATEMENT MATCH (a:person), (b:person) WHERE a.ID = 0 AND b.ID = 7 MERGE (a)-[r:knows {date:a.birthdate}]->(b) RETURN r; ---- 1 -(0:0)-{_LABEL: knows, _ID: 0:14, date: 1900-01-01}->(0:4) +(0:0)-{_LABEL: knows, _ID: 3:14, date: 1900-01-01}->(0:4) -CASE MergeOneToOne -STATEMENT MATCH (a:person), (b:person) WHERE a.ID = 9 AND b.ID = 10 MERGE (a)-[r:marries]->(b) ON CREATE SET a.age = 0, r.note = 'merged ntoes' diff --git a/test/test_files/update_rel/set_read_tinysnb.test b/test/test_files/update_rel/set_read_tinysnb.test index c4f8680b08c..660f182264b 100644 --- a/test/test_files/update_rel/set_read_tinysnb.test +++ b/test/test_files/update_rel/set_read_tinysnb.test @@ -18,6 +18,16 @@ -STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID=0 AND b.ID=5 RETURN e.date; ---- 1 +-STATEMENT MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID=0 AND b.ID=5 SET e.date=date('1999-01-02') WITH e MATCH (x:person)-[e2:knows]->(y:person) WHERE e2.date <= e.date RETURN e.date, x.fName, e2.date, y.fName; +---- 7 +1999-01-02|Alice|1999-01-02|Dan +1999-01-02|Bob|1950-05-14|Carol +1999-01-02|Bob|1950-05-14|Dan +1999-01-02|Carol|1950-05-14|Bob +1999-01-02|Dan|1950-05-14|Bob +1999-01-02|Elizabeth|1905-12-12|Farooq +1999-01-02|Elizabeth|1905-12-12|Greg + -CASE SetReadTest2 -STATEMENT CREATE REL TABLE play(FROM person TO person, date DATE, year INT64); ---- ok diff --git a/test/test_helper/test_helper.cpp b/test/test_helper/test_helper.cpp index 61832015020..afe7d6b04c4 100644 --- a/test/test_helper/test_helper.cpp +++ b/test/test_helper/test_helper.cpp @@ -13,8 +13,8 @@ namespace kuzu { namespace testing { // Deprecated -std::vector> TestHelper::parseTestFile( - const std::string& path, bool checkOutputOrder) { +std::vector> TestHelper::parseTestFile(const std::string& path, + bool checkOutputOrder) { std::vector> result; if (access(path.c_str(), 0) != 0) { throw Exception("Test file not exists! [" + path + "]."); @@ -56,8 +56,8 @@ std::vector> TestHelper::parseTestFile( return result; } -std::vector TestHelper::convertResultToString( - QueryResult& queryResult, bool checkOutputOrder) { +std::vector TestHelper::convertResultToString(QueryResult& queryResult, + bool checkOutputOrder) { std::vector actualOutput; while (queryResult.hasNext()) { auto tuple = queryResult.getNext(); diff --git a/test/test_runner/CMakeLists.txt b/test/test_runner/CMakeLists.txt index 594f6028b60..f1703a45723 100644 --- a/test/test_runner/CMakeLists.txt +++ b/test/test_runner/CMakeLists.txt @@ -1,6 +1,7 @@ add_library( test_runner OBJECT + csv_to_parquet_converter.cpp test_parser.cpp test_runner.cpp ) diff --git a/test/test_runner/csv_to_parquet_converter.cpp b/test/test_runner/csv_to_parquet_converter.cpp new file mode 100644 index 00000000000..a76047b2c9e --- /dev/null +++ b/test/test_runner/csv_to_parquet_converter.cpp @@ -0,0 +1,191 @@ +#include "test_runner/csv_to_parquet_converter.h" + +#include + +#include "common/exception/test.h" +#include "common/file_system/local_file_system.h" +#include "common/string_utils.h" +#include "spdlog/spdlog.h" +#include "test_helper/test_helper.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace testing { + +void CSVToParquetConverter::copySchemaFile() { + LocalFileSystem localFileSystem; + auto csvSchemaFile = + localFileSystem.joinPath(csvDatasetPath, std::string(TestHelper::SCHEMA_FILE_NAME)); + auto parquetSchemaFile = + localFileSystem.joinPath(parquetDatasetPath, std::string(TestHelper::SCHEMA_FILE_NAME)); + if (!localFileSystem.fileOrPathExists(parquetSchemaFile)) { + localFileSystem.copyFile(csvSchemaFile, parquetSchemaFile); + } else { + localFileSystem.overwriteFile(csvSchemaFile, parquetSchemaFile); + } + createTableInfo(parquetSchemaFile); +} + +void CSVToParquetConverter::createTableInfo(std::string schemaFile) { + std::ifstream file(schemaFile); + if (!file.is_open()) { + throw TestException(stringFormat("Error opening file: {}, errno: {}.", schemaFile, errno)); + } + // This implementation stays as a temporary solution to create copy statements for rel tables + // We'll switch to use table_info once that function can provide everything needed + // table_info is mentioned in this issue https://github.com/kuzudb/kuzu/issues/2991 + std::string line; + while (getline(file, line)) { + auto tokens = StringUtils::split(line, " "); + + std::transform(tokens[0].begin(), tokens[0].end(), tokens[0].begin(), + [](unsigned char c) { return std::tolower(c); }); + std::transform(tokens[2].begin(), tokens[2].end(), tokens[2].begin(), + [](unsigned char c) { return std::tolower(c); }); + if (tokens[0] != "create" || tokens[2] != "table") { + throw TestException(stringFormat("Invalid CREATE statement: {}", line)); + } + + auto tableType = tokens[1]; + std::transform(tableType.begin(), tableType.end(), tableType.begin(), + [](unsigned char c) { return std::tolower(c); }); + auto tableName = tokens[3]; + + std::shared_ptr table; + if (tableType == "node") { + auto nodeTable = std::make_shared(); + size_t primaryKeyPos = line.find("PRIMARY KEY"); + if (primaryKeyPos != std::string::npos) { + size_t openParenPos = line.find("(", primaryKeyPos); + size_t closeParenPos = line.find(")", primaryKeyPos); + if (openParenPos != std::string::npos && closeParenPos != std::string::npos && + openParenPos < closeParenPos) { + nodeTable->primaryKey = + line.substr(openParenPos + 1, closeParenPos - openParenPos - 1); + table = nodeTable; + } else { + throw TestException( + stringFormat("PRIMARY KEY is not defined in node table: {}", line)); + } + } else { + throw TestException( + stringFormat("PRIMARY KEY is not defined in node table: {}", line)); + } + } else { + auto relTable = std::make_shared(); + size_t startPos = line.find("FROM"); + if (startPos != std::string::npos) { + size_t endPos = line.find_first_of(",)", startPos); + if (endPos != std::string::npos) { + auto tmp = StringUtils::splitBySpace(line.substr(startPos, endPos - startPos)); + relTable->fromTable = + std::dynamic_pointer_cast(tableNameMap[tmp[1]]); + relTable->toTable = + std::dynamic_pointer_cast(tableNameMap[tmp[3]]); + table = relTable; + } else { + throw TestException(stringFormat( + "FROM node and TO node are not defined in rel table: {}", line)); + } + } else { + throw TestException( + stringFormat("FROM node and TO node are not defined in rel table: {}", line)); + } + } + table->name = tableName; + tables.push_back(table); + tableNameMap[tableName] = table; + } +} + +std::string extractPath(std::string& str, char delimiter) { + std::string::size_type posStart = str.find_first_of(delimiter); + std::string::size_type posEnd = str.find_last_of(delimiter); + return str.substr(posStart + 1, posEnd - posStart - 1); +} + +void CSVToParquetConverter::readCopyCommandsFromCSVDataset() { + auto csvCopyFile = + LocalFileSystem::joinPath(csvDatasetPath, std::string(TestHelper::COPY_FILE_NAME)); + std::ifstream file(csvCopyFile); + if (!file.is_open()) { + throw TestException(stringFormat("Error opening file: {}, errno: {}.", csvCopyFile, errno)); + } + std::string line; + while (getline(file, line)) { + auto tokens = StringUtils::split(line, " "); + auto path = std::filesystem::path(extractPath(tokens[3], '"')); + auto table = tableNameMap[tokens[1]]; + table->csvFilePath = TestHelper::appendKuzuRootPath(path.string()); + auto parquetFileName = path.stem().string() + ".parquet"; + table->parquetFilePath = parquetDatasetPath + "/" + parquetFileName; + } +} + +void CSVToParquetConverter::createCopyFile() { + readCopyCommandsFromCSVDataset(); + auto parquetCopyFile = + LocalFileSystem::joinPath(parquetDatasetPath, std::string(TestHelper::COPY_FILE_NAME)); + std::ofstream outfile(parquetCopyFile); + if (!outfile.is_open()) { + throw TestException( + stringFormat("Error opening file: {}, errno: {}.", parquetCopyFile, errno)); + } + std::string kuzuRootPath = KUZU_ROOT_DIRECTORY + std::string("/"); + for (auto table : tables) { + auto cmd = stringFormat("COPY {} FROM \"{}\";", table->name, + table->parquetFilePath.substr(kuzuRootPath.length())); + outfile << cmd << '\n'; + } +} + +void CSVToParquetConverter::convertCSVFilesToParquet() { + // Load CSV Files to temp database + TestHelper::executeScript( + LocalFileSystem::joinPath(csvDatasetPath, std::string(TestHelper::SCHEMA_FILE_NAME)), + *tempConn); + TestHelper::executeScript( + LocalFileSystem::joinPath(csvDatasetPath, std::string(TestHelper::COPY_FILE_NAME)), + *tempConn); + + spdlog::set_level(spdlog::level::info); + for (auto table : tables) { + spdlog::info("Converting: {} to {}", table->csvFilePath, table->parquetFilePath); + auto cmd = table->getConverterQuery(); + tempConn->query(cmd); + spdlog::info("Executed query: {}", cmd); + } +} + +void CSVToParquetConverter::convertCSVDatasetToParquet() { + LocalFileSystem localFileSystem; + if (!localFileSystem.fileOrPathExists(parquetDatasetPath)) { + localFileSystem.createDir(parquetDatasetPath); + } + + copySchemaFile(); + createCopyFile(); + + systemConfig = std::make_unique(bufferPoolSize); + std::string tempDatabasePath = TestHelper::appendKuzuRootPath( + std::string(TestHelper::TMP_TEST_DIR) + "csv_to_parquet_converter_" + + TestHelper::getMillisecondsSuffix()); + tempDb = std::make_unique(tempDatabasePath, *systemConfig); + tempConn = std::make_unique(tempDb.get()); + + convertCSVFilesToParquet(); + std::filesystem::remove_all(tempDatabasePath); +} + +std::string CSVToParquetConverter::NodeTableInfo::getConverterQuery() const { + return stringFormat("COPY (MATCH (a:{}) RETURN a.*) TO \"{}\";", name, parquetFilePath); +} + +std::string CSVToParquetConverter::RelTableInfo::getConverterQuery() const { + return stringFormat("COPY (MATCH (a)-[e:{}]->(b) RETURN a.{}, b.{}, e.*) TO \"{}\";", name, + fromTable->primaryKey, toTable->primaryKey, parquetFilePath); +} + +} // namespace testing +} // namespace kuzu diff --git a/test/test_runner/test_parser.cpp b/test/test_runner/test_parser.cpp index 8441d94034b..01d4b23614e 100644 --- a/test/test_runner/test_parser.cpp +++ b/test/test_runner/test_parser.cpp @@ -173,8 +173,8 @@ std::string TestParser::extractTextBeforeNextStatement(bool ignoreLineBreak) { return extractedText; } -TestStatement* TestParser::extractStatement( - TestStatement* statement, const std::string& testCaseName) { +TestStatement* TestParser::extractStatement(TestStatement* statement, + const std::string& testCaseName) { if (endOfFile()) { return statement; } diff --git a/test/test_runner/test_runner.cpp b/test/test_runner/test_runner.cpp index 055d3ae6f38..829ef4a1427 100644 --- a/test/test_runner/test_runner.cpp +++ b/test/test_runner/test_runner.cpp @@ -36,8 +36,8 @@ void replaceEnv(std::string& queryToReplace, const std::string& env) { } } -bool TestRunner::testStatement( - TestStatement* statement, Connection& conn, std::string& databasePath) { +bool TestRunner::testStatement(TestStatement* statement, Connection& conn, + std::string& databasePath) { std::unique_ptr preparedStatement; StringUtils::replaceAll(statement->query, "${DATABASE_PATH}", databasePath); StringUtils::replaceAll(statement->query, "${KUZU_ROOT_DIRECTORY}", KUZU_ROOT_DIRECTORY); @@ -46,9 +46,9 @@ bool TestRunner::testStatement( replaceEnv(statement->query, "AWS_S3_ACCESS_KEY_ID"); replaceEnv(statement->query, "AWS_S3_SECRET_ACCESS_KEY"); replaceEnv(statement->query, "RUN_ID"); - auto parsedStatements = std::vector>(); + auto parsedStatements = std::vector>(); try { - parsedStatements = conn.parseQuery(statement->query); + parsedStatements = conn.getClientContext()->parseQuery(statement->query); } catch (std::exception& exception) { auto errorPreparedStatement = conn.preparedStatementWithError(exception.what()); return checkLogicalPlan(errorPreparedStatement, statement, conn, 0); @@ -63,9 +63,9 @@ bool TestRunner::testStatement( } auto parsedStatement = std::move(parsedStatements[0]); if (statement->encodedJoin.empty()) { - preparedStatement = conn.prepareNoLock(parsedStatement.get(), statement->enumerate); + preparedStatement = conn.prepareNoLock(parsedStatement, statement->enumerate); } else { - preparedStatement = conn.prepareNoLock(parsedStatement.get(), true, statement->encodedJoin); + preparedStatement = conn.prepareNoLock(parsedStatement, true, statement->encodedJoin); } // Check for wrong statements if (!statement->expectedError && !statement->expectedErrorRegex && @@ -116,6 +116,11 @@ bool TestRunner::checkLogicalPlan(std::unique_ptr& preparedSt } else if (statement->expectedOk && result->isSuccess()) { return true; } else { + if (!preparedStatement->success) { + spdlog::info("Query compilation failed with error: {}", + preparedStatement->getErrorMessage()); + return false; + } auto planStr = preparedStatement->logicalPlans[planIdx]->toString(); if (checkPlanResult(result, statement, planStr, planIdx)) { return true; @@ -148,8 +153,8 @@ bool TestRunner::checkPlanResult(std::unique_ptr& result, TestState if (resultTuples.size() == result->getNumTuples() && resultHash == statement->expectedHashValue && resultTuples.size() == statement->expectedNumTuples) { - spdlog::info( - "PLAN{} PASSED in {}ms.", planIdx, result->getQuerySummary()->getExecutionTime()); + spdlog::info("PLAN{} PASSED in {}ms.", planIdx, + result->getQuerySummary()->getExecutionTime()); return true; } else { spdlog::error("PLAN{} NOT PASSED.", planIdx); @@ -164,8 +169,8 @@ bool TestRunner::checkPlanResult(std::unique_ptr& result, TestState } if (resultTuples.size() == result->getNumTuples() && resultTuples == statement->expectedTuples) { - spdlog::info( - "PLAN{} PASSED in {}ms.", planIdx, result->getQuerySummary()->getExecutionTime()); + spdlog::info("PLAN{} PASSED in {}ms.", planIdx, + result->getQuerySummary()->getExecutionTime()); return true; } else { spdlog::error("PLAN{} NOT PASSED.", planIdx); @@ -178,8 +183,8 @@ bool TestRunner::checkPlanResult(std::unique_ptr& result, TestState return false; } -std::vector TestRunner::convertResultToString( - QueryResult& queryResult, bool checkOutputOrder) { +std::vector TestRunner::convertResultToString(QueryResult& queryResult, + bool checkOutputOrder) { std::vector actualOutput; while (queryResult.hasNext()) { auto tuple = queryResult.getNext(); @@ -205,8 +210,8 @@ std::string TestRunner::convertResultToMD5Hash(QueryResult& queryResult, bool ch return std::string(hasher.finishMD5()); } -std::unique_ptr TestRunner::getLogicalPlan( - const std::string& query, kuzu::main::Connection& conn) { +std::unique_ptr TestRunner::getLogicalPlan(const std::string& query, + kuzu::main::Connection& conn) { return std::move(conn.prepare(query)->logicalPlans[0]); } diff --git a/test/transaction/transaction_manager_test.cpp b/test/transaction/transaction_manager_test.cpp index d76bc1e440f..3ca6311917e 100644 --- a/test/transaction/transaction_manager_test.cpp +++ b/test/transaction/transaction_manager_test.cpp @@ -18,19 +18,19 @@ class TransactionManagerTest : public EmptyDBTest { bufferManager = getBufferManager(*database); std::make_unique(BufferPoolConstants::DEFAULT_BUFFER_POOL_SIZE_FOR_TESTING, BufferPoolConstants::DEFAULT_VM_REGION_MAX_SIZE); - wal = std::make_unique( - databasePath, false /* readOnly */, *bufferManager, getFileSystem(*database)); - transactionManager = - std::make_unique(*wal, getMemoryManager(*database)); + wal = std::make_unique(databasePath, false /* readOnly */, *bufferManager, + getFileSystem(*database)); + transactionManager = std::make_unique(*wal); } void TearDown() override { EmptyDBTest::TearDown(); } public: void runTwoCommitRollback(TransactionType type, bool firstIsCommit, bool secondIsCommit) { - std::unique_ptr trx = TransactionType::WRITE == type ? - transactionManager->beginWriteTransaction() : - transactionManager->beginReadOnlyTransaction(); + std::unique_ptr trx = + TransactionType::WRITE == type ? + transactionManager->beginWriteTransaction(*getClientContext(*conn)) : + transactionManager->beginReadOnlyTransaction(*getClientContext(*conn)); if (firstIsCommit) { transactionManager->commit(trx.get()); } else { @@ -52,9 +52,10 @@ class TransactionManagerTest : public EmptyDBTest { }; TEST_F(TransactionManagerTest, MultipleWriteTransactionsErrors) { - std::unique_ptr trx1 = transactionManager->beginWriteTransaction(); + std::unique_ptr trx1 = + transactionManager->beginWriteTransaction(*getClientContext(*conn)); try { - transactionManager->beginWriteTransaction(); + transactionManager->beginWriteTransaction(*getClientContext(*conn)); FAIL(); } catch (TransactionManagerException& e) {} } @@ -62,34 +63,34 @@ TEST_F(TransactionManagerTest, MultipleWriteTransactionsErrors) { TEST_F(TransactionManagerTest, MultipleCommitsAndRollbacks) { // At TransactionManager level, we disallow multiple commit/rollbacks on a write transaction. try { - runTwoCommitRollback( - TransactionType::WRITE, true /* firstIsCommit */, true /* secondIsCommit */); + runTwoCommitRollback(TransactionType::WRITE, true /* firstIsCommit */, + true /* secondIsCommit */); FAIL(); } catch (TransactionManagerException& e) {} try { - runTwoCommitRollback( - TransactionType::WRITE, true /* firstIsCommit */, false /* secondIsRollback */); + runTwoCommitRollback(TransactionType::WRITE, true /* firstIsCommit */, + false /* secondIsRollback */); FAIL(); } catch (TransactionManagerException& e) {} try { - runTwoCommitRollback( - TransactionType::WRITE, false /* firstIsRollback */, true /* secondIsCommit */); + runTwoCommitRollback(TransactionType::WRITE, false /* firstIsRollback */, + true /* secondIsCommit */); FAIL(); } catch (TransactionManagerException& e) {} try { - runTwoCommitRollback( - TransactionType::WRITE, false /* firstIsRollback */, false /* secondIsRollback */); + runTwoCommitRollback(TransactionType::WRITE, false /* firstIsRollback */, + false /* secondIsRollback */); FAIL(); } catch (TransactionManagerException& e) {} // At TransactionManager level, we allow multiple commit/rollbacks on a read-only transaction. - runTwoCommitRollback( - TransactionType::READ_ONLY, true /* firstIsCommit */, true /* secondIsCommit */); - runTwoCommitRollback( - TransactionType::READ_ONLY, true /* firstIsCommit */, false /* secondIsRollback */); - runTwoCommitRollback( - TransactionType::READ_ONLY, false /* firstIsRollback */, true /* secondIsCommit */); - runTwoCommitRollback( - TransactionType::READ_ONLY, false /* firstIsRollback */, false /* secondIsRollback */); + runTwoCommitRollback(TransactionType::READ_ONLY, true /* firstIsCommit */, + true /* secondIsCommit */); + runTwoCommitRollback(TransactionType::READ_ONLY, true /* firstIsCommit */, + false /* secondIsRollback */); + runTwoCommitRollback(TransactionType::READ_ONLY, false /* firstIsRollback */, + true /* secondIsCommit */); + runTwoCommitRollback(TransactionType::READ_ONLY, false /* firstIsRollback */, + false /* secondIsRollback */); } TEST_F(TransactionManagerTest, BasicOneWriteMultipleReadOnlyTransactions) { @@ -97,9 +98,12 @@ TEST_F(TransactionManagerTest, BasicOneWriteMultipleReadOnlyTransactions) { // before and after commits or rollbacks under concurrent transactions. Specifically we test: // that transaction IDs increase incrementally, the states of activeReadOnlyTransactionIDs set, // and activeWriteTransactionID. - std::unique_ptr trx1 = transactionManager->beginReadOnlyTransaction(); - std::unique_ptr trx2 = transactionManager->beginWriteTransaction(); - std::unique_ptr trx3 = transactionManager->beginReadOnlyTransaction(); + std::unique_ptr trx1 = + transactionManager->beginReadOnlyTransaction(*getClientContext(*conn)); + std::unique_ptr trx2 = + transactionManager->beginWriteTransaction(*getClientContext(*conn)); + std::unique_ptr trx3 = + transactionManager->beginReadOnlyTransaction(*getClientContext(*conn)); ASSERT_EQ(TransactionType::READ_ONLY, trx1->getType()); ASSERT_EQ(TransactionType::WRITE, trx2->getType()); ASSERT_EQ(TransactionType::READ_ONLY, trx3->getType()); @@ -107,26 +111,28 @@ TEST_F(TransactionManagerTest, BasicOneWriteMultipleReadOnlyTransactions) { ASSERT_EQ(trx2->getID() + 1, trx3->getID()); ASSERT_EQ(trx2->getID(), transactionManager->getActiveWriteTransactionID()); std::unordered_set expectedReadOnlyTransactionSet({trx1->getID(), trx3->getID()}); - ASSERT_EQ( - expectedReadOnlyTransactionSet, transactionManager->getActiveReadOnlyTransactionIDs()); + ASSERT_EQ(expectedReadOnlyTransactionSet, + transactionManager->getActiveReadOnlyTransactionIDs()); transactionManager->commit(trx2.get()); ASSERT_FALSE(transactionManager->hasActiveWriteTransactionID()); transactionManager->rollback(trx1.get()); expectedReadOnlyTransactionSet.erase(trx1->getID()); - ASSERT_EQ( - expectedReadOnlyTransactionSet, transactionManager->getActiveReadOnlyTransactionIDs()); + ASSERT_EQ(expectedReadOnlyTransactionSet, + transactionManager->getActiveReadOnlyTransactionIDs()); transactionManager->commit(trx3.get()); expectedReadOnlyTransactionSet.erase(trx3->getID()); - ASSERT_EQ( - expectedReadOnlyTransactionSet, transactionManager->getActiveReadOnlyTransactionIDs()); + ASSERT_EQ(expectedReadOnlyTransactionSet, + transactionManager->getActiveReadOnlyTransactionIDs()); - std::unique_ptr trx4 = transactionManager->beginWriteTransaction(); - std::unique_ptr trx5 = transactionManager->beginReadOnlyTransaction(); + std::unique_ptr trx4 = + transactionManager->beginWriteTransaction(*getClientContext(*conn)); + std::unique_ptr trx5 = + transactionManager->beginReadOnlyTransaction(*getClientContext(*conn)); ASSERT_EQ(trx3->getID() + 1, trx4->getID()); ASSERT_EQ(trx4->getID() + 1, trx5->getID()); ASSERT_EQ(trx4->getID(), transactionManager->getActiveWriteTransactionID()); expectedReadOnlyTransactionSet.insert(trx5->getID()); - ASSERT_EQ( - expectedReadOnlyTransactionSet, transactionManager->getActiveReadOnlyTransactionIDs()); + ASSERT_EQ(expectedReadOnlyTransactionSet, + transactionManager->getActiveReadOnlyTransactionIDs()); } diff --git a/test/util_tests/string_format.cpp b/test/util_tests/string_format.cpp index b113be7a790..76d4a47cefe 100644 --- a/test/util_tests/string_format.cpp +++ b/test/util_tests/string_format.cpp @@ -6,13 +6,13 @@ using namespace kuzu::common; TEST(StringFormat, Basic) { - ASSERT_EQ( - stringFormat("Some formatted data: {} and {}", 'a', 423), "Some formatted data: a and 423"); + ASSERT_EQ(stringFormat("Some formatted data: {} and {}", 'a', 423), + "Some formatted data: a and 423"); } TEST(StringFormat, Escape) { - ASSERT_EQ( - stringFormat("Escape this {{}} but not this {{ }}"), "Escape this {} but not this {{ }}"); + ASSERT_EQ(stringFormat("Escape this {{}} but not this {{ }}"), + "Escape this {} but not this {{ }}"); ASSERT_EQ(stringFormat("Escape before and after value works: {{}} {} {{}}", 4), "Escape before and after value works: {} 4 {}"); } diff --git a/third_party/antlr4_cypher/cypher_lexer.cpp b/third_party/antlr4_cypher/cypher_lexer.cpp index ef3eedf02ce..be35a83528e 100644 --- a/third_party/antlr4_cypher/cypher_lexer.cpp +++ b/third_party/antlr4_cypher/cypher_lexer.cpp @@ -62,11 +62,11 @@ void cypherlexerLexerInitialize() { "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", - "T__41", "T__42", "T__43", "T__44", "CALL", "COMMENT", "MACRO", "GLOB", - "COPY", "FROM", "COLUMN", "EXPORT", "IMPORT", "DATABASE", "NODE", - "TABLE", "GROUP", "RDFGRAPH", "DROP", "ALTER", "DEFAULT", "RENAME", - "ADD", "PRIMARY", "KEY", "REL", "TO", "EXPLAIN", "PROFILE", "BEGIN", - "TRANSACTION", "READ", "ONLY", "WRITE", "COMMIT", "COMMIT_SKIP_CHECKPOINT", + "T__41", "T__42", "T__43", "T__44", "ATTACH", "DBTYPE", "CALL", "COMMENT_", + "MACRO", "GLOB", "COPY", "FROM", "COLUMN", "EXPORT", "IMPORT", "DATABASE", + "NODE", "TABLE", "GROUP", "RDFGRAPH", "DROP", "ALTER", "DEFAULT", + "RENAME", "ADD", "PRIMARY", "KEY", "REL", "TO", "EXPLAIN", "PROFILE", + "BEGIN", "TRANSACTION", "READ", "ONLY", "WRITE", "COMMIT", "COMMIT_SKIP_CHECKPOINT", "ROLLBACK", "ROLLBACK_SKIP_CHECKPOINT", "INSTALL", "EXTENSION", "UNION", "ALL", "LOAD", "HEADERS", "OPTIONAL", "MATCH", "UNWIND", "CREATE", "MERGE", "ON", "SET", "DETACH", "DELETE", "WITH", "RETURN", "DISTINCT", @@ -90,7 +90,7 @@ void cypherlexerLexerInitialize() { "DEFAULT_MODE" }, std::vector{ - "", "';'", "'('", "')'", "','", "'='", "'['", "']'", "'{'", "'}'", + "", "';'", "'('", "','", "')'", "'='", "'['", "']'", "'{'", "'}'", "'|'", "'..'", "'<>'", "'<'", "'<='", "'>'", "'>='", "'&'", "'>>'", "'<<'", "'+'", "'/'", "'%'", "'^'", "'=~'", "'.'", "'$'", "'\\u27E8'", "'\\u3008'", "'\\uFE64'", "'\\uFF1C'", "'\\u27E9'", "'\\u3009'", "'\\uFE65'", @@ -99,34 +99,34 @@ void cypherlexerLexerInitialize() { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "'*'", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "'!='", "'-'", "'!'", "':'", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", "", "", "", "", "'0'" + "", "", "", "'*'", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "'!='", "'-'", "'!'", "':'", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "'0'" }, std::vector{ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", "", "", "CALL", "COMMENT", - "MACRO", "GLOB", "COPY", "FROM", "COLUMN", "EXPORT", "IMPORT", "DATABASE", - "NODE", "TABLE", "GROUP", "RDFGRAPH", "DROP", "ALTER", "DEFAULT", - "RENAME", "ADD", "PRIMARY", "KEY", "REL", "TO", "EXPLAIN", "PROFILE", - "BEGIN", "TRANSACTION", "READ", "ONLY", "WRITE", "COMMIT", "COMMIT_SKIP_CHECKPOINT", - "ROLLBACK", "ROLLBACK_SKIP_CHECKPOINT", "INSTALL", "EXTENSION", "UNION", - "ALL", "LOAD", "HEADERS", "OPTIONAL", "MATCH", "UNWIND", "CREATE", - "MERGE", "ON", "SET", "DETACH", "DELETE", "WITH", "RETURN", "DISTINCT", - "STAR", "AS", "ORDER", "BY", "L_SKIP", "LIMIT", "ASCENDING", "ASC", - "DESCENDING", "DESC", "WHERE", "SHORTEST", "OR", "XOR", "AND", "NOT", - "INVALID_NOT_EQUAL", "MINUS", "FACTORIAL", "COLON", "IN", "STARTS", - "ENDS", "CONTAINS", "IS", "NULL_", "TRUE", "FALSE", "COUNT", "EXISTS", - "CASE", "ELSE", "END", "WHEN", "THEN", "StringLiteral", "EscapedChar", - "DecimalInteger", "HexLetter", "HexDigit", "Digit", "NonZeroDigit", - "NonZeroOctDigit", "ZeroDigit", "RegularDecimalReal", "UnescapedSymbolicName", - "IdentifierStart", "IdentifierPart", "EscapedSymbolicName", "SP", - "WHITESPACE", "Comment", "Unknown" + "", "", "", "", "", "", "", "", "", "", "", "", "ATTACH", "DBTYPE", + "CALL", "COMMENT_", "MACRO", "GLOB", "COPY", "FROM", "COLUMN", "EXPORT", + "IMPORT", "DATABASE", "NODE", "TABLE", "GROUP", "RDFGRAPH", "DROP", + "ALTER", "DEFAULT", "RENAME", "ADD", "PRIMARY", "KEY", "REL", "TO", + "EXPLAIN", "PROFILE", "BEGIN", "TRANSACTION", "READ", "ONLY", "WRITE", + "COMMIT", "COMMIT_SKIP_CHECKPOINT", "ROLLBACK", "ROLLBACK_SKIP_CHECKPOINT", + "INSTALL", "EXTENSION", "UNION", "ALL", "LOAD", "HEADERS", "OPTIONAL", + "MATCH", "UNWIND", "CREATE", "MERGE", "ON", "SET", "DETACH", "DELETE", + "WITH", "RETURN", "DISTINCT", "STAR", "AS", "ORDER", "BY", "L_SKIP", + "LIMIT", "ASCENDING", "ASC", "DESCENDING", "DESC", "WHERE", "SHORTEST", + "OR", "XOR", "AND", "NOT", "INVALID_NOT_EQUAL", "MINUS", "FACTORIAL", + "COLON", "IN", "STARTS", "ENDS", "CONTAINS", "IS", "NULL_", "TRUE", + "FALSE", "COUNT", "EXISTS", "CASE", "ELSE", "END", "WHEN", "THEN", + "StringLiteral", "EscapedChar", "DecimalInteger", "HexLetter", "HexDigit", + "Digit", "NonZeroDigit", "NonZeroOctDigit", "ZeroDigit", "RegularDecimalReal", + "UnescapedSymbolicName", "IdentifierStart", "IdentifierPart", "EscapedSymbolicName", + "SP", "WHITESPACE", "Comment", "Unknown" } ); static const int32_t serializedATNSegment[] = { - 4,0,150,1166,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6, + 4,0,152,1201,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6, 7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2, 14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2, 21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2, @@ -151,611 +151,625 @@ void cypherlexerLexerInitialize() { 7,146,2,147,7,147,2,148,7,148,2,149,7,149,2,150,7,150,2,151,7,151,2,152, 7,152,2,153,7,153,2,154,7,154,2,155,7,155,2,156,7,156,2,157,7,157,2,158, 7,158,2,159,7,159,2,160,7,160,2,161,7,161,2,162,7,162,2,163,7,163,2,164, - 7,164,2,165,7,165,2,166,7,166,2,167,7,167,2,168,7,168,2,169,7,169,1,0, - 1,0,1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,6,1,6,1,7,1,7,1,8,1,8,1, - 9,1,9,1,10,1,10,1,10,1,11,1,11,1,11,1,12,1,12,1,13,1,13,1,13,1,14,1,14, - 1,15,1,15,1,15,1,16,1,16,1,17,1,17,1,17,1,18,1,18,1,18,1,19,1,19,1,20, - 1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,23,1,24,1,24,1,25,1,25,1,26,1,26, - 1,27,1,27,1,28,1,28,1,29,1,29,1,30,1,30,1,31,1,31,1,32,1,32,1,33,1,33, - 1,34,1,34,1,35,1,35,1,36,1,36,1,37,1,37,1,38,1,38,1,39,1,39,1,40,1,40, - 1,41,1,41,1,42,1,42,1,43,1,43,1,44,1,44,1,45,1,45,1,45,1,45,1,45,1,46, - 1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,47,1,47,1,47,1,47,1,47,1,47,1,48, - 1,48,1,48,1,48,1,48,1,49,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,50, - 1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,52,1,52,1,52,1,52,1,52,1,52,1,52, - 1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,54,1,54,1,54,1,54, - 1,54,1,54,1,55,1,55,1,55,1,55,1,55,1,56,1,56,1,56,1,56,1,56,1,56,1,57, - 1,57,1,57,1,57,1,57,1,57,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58, - 1,59,1,59,1,59,1,59,1,59,1,60,1,60,1,60,1,60,1,60,1,60,1,61,1,61,1,61, - 1,61,1,61,1,61,1,61,1,61,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,63,1,63, - 1,63,1,63,1,64,1,64,1,64,1,64,1,64,1,64,1,64,1,64,1,65,1,65,1,65,1,65, - 1,66,1,66,1,66,1,66,1,67,1,67,1,67,1,68,1,68,1,68,1,68,1,68,1,68,1,68, - 1,68,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,70,1,70,1,70,1,70,1,70, - 1,70,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,72, - 1,72,1,72,1,72,1,72,1,73,1,73,1,73,1,73,1,73,1,74,1,74,1,74,1,74,1,74, - 1,74,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,76,1,76,1,76,1,76,1,76,1,76, - 1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76, - 1,76,1,76,1,76,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,78,1,78, - 1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78, - 1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,79,1,79,1,79,1,79,1,79, - 1,79,1,79,1,79,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,81, - 1,81,1,81,1,81,1,81,1,81,1,82,1,82,1,82,1,82,1,83,1,83,1,83,1,83,1,83, - 1,84,1,84,1,84,1,84,1,84,1,84,1,84,1,84,1,85,1,85,1,85,1,85,1,85,1,85, - 1,85,1,85,1,85,1,86,1,86,1,86,1,86,1,86,1,86,1,87,1,87,1,87,1,87,1,87, - 1,87,1,87,1,88,1,88,1,88,1,88,1,88,1,88,1,88,1,89,1,89,1,89,1,89,1,89, - 1,89,1,90,1,90,1,90,1,91,1,91,1,91,1,91,1,92,1,92,1,92,1,92,1,92,1,92, - 1,92,1,93,1,93,1,93,1,93,1,93,1,93,1,93,1,94,1,94,1,94,1,94,1,94,1,95, - 1,95,1,95,1,95,1,95,1,95,1,95,1,96,1,96,1,96,1,96,1,96,1,96,1,96,1,96, - 1,96,1,97,1,97,1,98,1,98,1,98,1,99,1,99,1,99,1,99,1,99,1,99,1,100,1,100, - 1,100,1,101,1,101,1,101,1,101,1,101,1,102,1,102,1,102,1,102,1,102,1,102, - 1,103,1,103,1,103,1,103,1,103,1,103,1,103,1,103,1,103,1,103,1,104,1,104, - 1,104,1,104,1,105,1,105,1,105,1,105,1,105,1,105,1,105,1,105,1,105,1,105, - 1,105,1,106,1,106,1,106,1,106,1,106,1,107,1,107,1,107,1,107,1,107,1,107, - 1,108,1,108,1,108,1,108,1,108,1,108,1,108,1,108,1,108,1,109,1,109,1,109, - 1,110,1,110,1,110,1,110,1,111,1,111,1,111,1,111,1,112,1,112,1,112,1,112, - 1,113,1,113,1,113,1,114,1,114,1,115,1,115,1,116,1,116,1,117,1,117,1,117, - 1,118,1,118,1,118,1,118,1,118,1,118,1,118,1,119,1,119,1,119,1,119,1,119, - 1,120,1,120,1,120,1,120,1,120,1,120,1,120,1,120,1,120,1,121,1,121,1,121, - 1,122,1,122,1,122,1,122,1,122,1,123,1,123,1,123,1,123,1,123,1,124,1,124, - 1,124,1,124,1,124,1,124,1,125,1,125,1,125,1,125,1,125,1,125,1,126,1,126, - 1,126,1,126,1,126,1,126,1,126,1,127,1,127,1,127,1,127,1,127,1,128,1,128, - 1,128,1,128,1,128,1,129,1,129,1,129,1,129,1,130,1,130,1,130,1,130,1,130, - 1,131,1,131,1,131,1,131,1,131,1,132,1,132,1,132,5,132,987,8,132,10,132, - 12,132,990,9,132,1,132,1,132,1,132,1,132,5,132,996,8,132,10,132,12,132, - 999,9,132,1,132,3,132,1002,8,132,1,133,1,133,1,133,1,133,1,133,1,133, - 1,133,1,133,1,133,1,133,1,133,1,133,1,133,1,133,1,133,1,133,1,133,1,133, - 3,133,1022,8,133,1,134,1,134,1,134,5,134,1027,8,134,10,134,12,134,1030, - 9,134,3,134,1032,8,134,1,135,3,135,1035,8,135,1,136,1,136,3,136,1039, - 8,136,1,137,1,137,3,137,1043,8,137,1,138,1,138,3,138,1047,8,138,1,139, - 1,139,1,140,1,140,1,141,5,141,1054,8,141,10,141,12,141,1057,9,141,1,141, - 1,141,4,141,1061,8,141,11,141,12,141,1062,1,142,1,142,5,142,1067,8,142, - 10,142,12,142,1070,9,142,1,143,1,143,3,143,1074,8,143,1,144,1,144,3,144, - 1078,8,144,1,145,1,145,5,145,1082,8,145,10,145,12,145,1085,9,145,1,145, - 4,145,1088,8,145,11,145,12,145,1089,1,146,4,146,1093,8,146,11,146,12, - 146,1094,1,147,1,147,1,147,1,147,1,147,1,147,1,147,1,147,1,147,1,147, - 1,147,1,147,3,147,1109,8,147,1,148,1,148,1,148,1,148,1,148,1,148,5,148, - 1117,8,148,10,148,12,148,1120,9,148,1,148,1,148,1,148,1,149,1,149,1,150, - 1,150,1,151,1,151,1,152,1,152,1,153,1,153,1,154,1,154,1,155,1,155,1,156, - 1,156,1,157,1,157,1,158,1,158,1,159,1,159,1,160,1,160,1,161,1,161,1,162, - 1,162,1,163,1,163,1,164,1,164,1,165,1,165,1,166,1,166,1,167,1,167,1,168, - 1,168,1,169,1,169,0,0,170,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19, - 10,21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21, - 43,22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65, - 33,67,34,69,35,71,36,73,37,75,38,77,39,79,40,81,41,83,42,85,43,87,44, - 89,45,91,46,93,47,95,48,97,49,99,50,101,51,103,52,105,53,107,54,109,55, - 111,56,113,57,115,58,117,59,119,60,121,61,123,62,125,63,127,64,129,65, - 131,66,133,67,135,68,137,69,139,70,141,71,143,72,145,73,147,74,149,75, - 151,76,153,77,155,78,157,79,159,80,161,81,163,82,165,83,167,84,169,85, - 171,86,173,87,175,88,177,89,179,90,181,91,183,92,185,93,187,94,189,95, - 191,96,193,97,195,98,197,99,199,100,201,101,203,102,205,103,207,104,209, - 105,211,106,213,107,215,108,217,109,219,110,221,111,223,112,225,113,227, - 114,229,115,231,116,233,117,235,118,237,119,239,120,241,121,243,122,245, - 123,247,124,249,125,251,126,253,127,255,128,257,129,259,130,261,131,263, - 132,265,133,267,134,269,135,271,136,273,137,275,138,277,139,279,140,281, - 141,283,142,285,143,287,144,289,145,291,146,293,147,295,148,297,149,299, - 0,301,0,303,0,305,0,307,0,309,0,311,0,313,0,315,0,317,0,319,0,321,0,323, - 0,325,0,327,0,329,0,331,0,333,0,335,0,337,0,339,150,1,0,45,2,0,67,67, - 99,99,2,0,65,65,97,97,2,0,76,76,108,108,2,0,79,79,111,111,2,0,77,77,109, - 109,2,0,69,69,101,101,2,0,78,78,110,110,2,0,84,84,116,116,2,0,82,82,114, - 114,2,0,71,71,103,103,2,0,66,66,98,98,2,0,80,80,112,112,2,0,89,89,121, - 121,2,0,70,70,102,102,2,0,85,85,117,117,2,0,88,88,120,120,2,0,73,73,105, - 105,2,0,68,68,100,100,2,0,83,83,115,115,2,0,72,72,104,104,2,0,75,75,107, - 107,2,0,87,87,119,119,13,0,34,34,39,39,66,66,70,70,78,78,82,82,84,84, - 92,92,98,98,102,102,110,110,114,114,116,116,2,0,65,70,97,102,8,0,160, - 160,5760,5760,6158,6158,8192,8202,8232,8233,8239,8239,8287,8287,12288, - 12288,1,0,12,12,1,0,96,96,1,0,30,30,768,0,48,57,65,90,95,95,97,122,170, - 170,181,181,183,183,186,186,192,214,216,246,248,705,710,721,736,740,748, - 748,750,750,768,884,886,887,890,893,895,895,902,906,908,908,910,929,931, - 1013,1015,1153,1155,1159,1162,1327,1329,1366,1369,1369,1376,1416,1425, - 1469,1471,1471,1473,1474,1476,1477,1479,1479,1488,1514,1519,1522,1552, - 1562,1568,1641,1646,1747,1749,1756,1759,1768,1770,1788,1791,1791,1808, - 1866,1869,1969,1984,2037,2042,2042,2045,2045,2048,2093,2112,2139,2144, - 2154,2160,2183,2185,2190,2200,2273,2275,2403,2406,2415,2417,2435,2437, - 2444,2447,2448,2451,2472,2474,2480,2482,2482,2486,2489,2492,2500,2503, - 2504,2507,2510,2519,2519,2524,2525,2527,2531,2534,2545,2556,2556,2558, - 2558,2561,2563,2565,2570,2575,2576,2579,2600,2602,2608,2610,2611,2613, - 2614,2616,2617,2620,2620,2622,2626,2631,2632,2635,2637,2641,2641,2649, - 2652,2654,2654,2662,2677,2689,2691,2693,2701,2703,2705,2707,2728,2730, - 2736,2738,2739,2741,2745,2748,2757,2759,2761,2763,2765,2768,2768,2784, - 2787,2790,2799,2809,2815,2817,2819,2821,2828,2831,2832,2835,2856,2858, - 2864,2866,2867,2869,2873,2876,2884,2887,2888,2891,2893,2901,2903,2908, - 2909,2911,2915,2918,2927,2929,2929,2946,2947,2949,2954,2958,2960,2962, - 2965,2969,2970,2972,2972,2974,2975,2979,2980,2984,2986,2990,3001,3006, - 3010,3014,3016,3018,3021,3024,3024,3031,3031,3046,3055,3072,3084,3086, - 3088,3090,3112,3114,3129,3132,3140,3142,3144,3146,3149,3157,3158,3160, - 3162,3165,3165,3168,3171,3174,3183,3200,3203,3205,3212,3214,3216,3218, - 3240,3242,3251,3253,3257,3260,3268,3270,3272,3274,3277,3285,3286,3293, - 3294,3296,3299,3302,3311,3313,3315,3328,3340,3342,3344,3346,3396,3398, - 3400,3402,3406,3412,3415,3423,3427,3430,3439,3450,3455,3457,3459,3461, - 3478,3482,3505,3507,3515,3517,3517,3520,3526,3530,3530,3535,3540,3542, - 3542,3544,3551,3558,3567,3570,3571,3585,3642,3648,3662,3664,3673,3713, - 3714,3716,3716,3718,3722,3724,3747,3749,3749,3751,3773,3776,3780,3782, - 3782,3784,3790,3792,3801,3804,3807,3840,3840,3864,3865,3872,3881,3893, - 3893,3895,3895,3897,3897,3902,3911,3913,3948,3953,3972,3974,3991,3993, - 4028,4038,4038,4096,4169,4176,4253,4256,4293,4295,4295,4301,4301,4304, - 4346,4348,4680,4682,4685,4688,4694,4696,4696,4698,4701,4704,4744,4746, - 4749,4752,4784,4786,4789,4792,4798,4800,4800,4802,4805,4808,4822,4824, - 4880,4882,4885,4888,4954,4957,4959,4969,4977,4992,5007,5024,5109,5112, - 5117,5121,5740,5743,5759,5761,5786,5792,5866,5870,5880,5888,5909,5919, - 5940,5952,5971,5984,5996,5998,6000,6002,6003,6016,6099,6103,6103,6108, - 6109,6112,6121,6155,6157,6159,6169,6176,6264,6272,6314,6320,6389,6400, - 6430,6432,6443,6448,6459,6470,6509,6512,6516,6528,6571,6576,6601,6608, - 6618,6656,6683,6688,6750,6752,6780,6783,6793,6800,6809,6823,6823,6832, - 6845,6847,6862,6912,6988,6992,7001,7019,7027,7040,7155,7168,7223,7232, - 7241,7245,7293,7296,7304,7312,7354,7357,7359,7376,7378,7380,7418,7424, - 7957,7960,7965,7968,8005,8008,8013,8016,8023,8025,8025,8027,8027,8029, - 8029,8031,8061,8064,8116,8118,8124,8126,8126,8130,8132,8134,8140,8144, - 8147,8150,8155,8160,8172,8178,8180,8182,8188,8255,8256,8276,8276,8305, - 8305,8319,8319,8336,8348,8400,8412,8417,8417,8421,8432,8450,8450,8455, - 8455,8458,8467,8469,8469,8472,8477,8484,8484,8486,8486,8488,8488,8490, - 8505,8508,8511,8517,8521,8526,8526,8544,8584,11264,11492,11499,11507, - 11520,11557,11559,11559,11565,11565,11568,11623,11631,11631,11647,11670, - 11680,11686,11688,11694,11696,11702,11704,11710,11712,11718,11720,11726, - 11728,11734,11736,11742,11744,11775,12293,12295,12321,12335,12337,12341, - 12344,12348,12353,12438,12441,12447,12449,12538,12540,12543,12549,12591, - 12593,12686,12704,12735,12784,12799,13312,19903,19968,42124,42192,42237, - 42240,42508,42512,42539,42560,42607,42612,42621,42623,42737,42775,42783, - 42786,42888,42891,42954,42960,42961,42963,42963,42965,42969,42994,43047, - 43052,43052,43072,43123,43136,43205,43216,43225,43232,43255,43259,43259, - 43261,43309,43312,43347,43360,43388,43392,43456,43471,43481,43488,43518, - 43520,43574,43584,43597,43600,43609,43616,43638,43642,43714,43739,43741, - 43744,43759,43762,43766,43777,43782,43785,43790,43793,43798,43808,43814, - 43816,43822,43824,43866,43868,43881,43888,44010,44012,44013,44016,44025, - 44032,55203,55216,55238,55243,55291,63744,64109,64112,64217,64256,64262, - 64275,64279,64285,64296,64298,64310,64312,64316,64318,64318,64320,64321, - 64323,64324,64326,64433,64467,64829,64848,64911,64914,64967,65008,65019, - 65024,65039,65056,65071,65075,65076,65101,65103,65136,65140,65142,65276, - 65296,65305,65313,65338,65343,65343,65345,65370,65382,65470,65474,65479, - 65482,65487,65490,65495,65498,65500,65536,65547,65549,65574,65576,65594, - 65596,65597,65599,65613,65616,65629,65664,65786,65856,65908,66045,66045, - 66176,66204,66208,66256,66272,66272,66304,66335,66349,66378,66384,66426, - 66432,66461,66464,66499,66504,66511,66513,66517,66560,66717,66720,66729, - 66736,66771,66776,66811,66816,66855,66864,66915,66928,66938,66940,66954, - 66956,66962,66964,66965,66967,66977,66979,66993,66995,67001,67003,67004, - 67072,67382,67392,67413,67424,67431,67456,67461,67463,67504,67506,67514, - 67584,67589,67592,67592,67594,67637,67639,67640,67644,67644,67647,67669, - 67680,67702,67712,67742,67808,67826,67828,67829,67840,67861,67872,67897, - 67968,68023,68030,68031,68096,68099,68101,68102,68108,68115,68117,68119, - 68121,68149,68152,68154,68159,68159,68192,68220,68224,68252,68288,68295, - 68297,68326,68352,68405,68416,68437,68448,68466,68480,68497,68608,68680, - 68736,68786,68800,68850,68864,68903,68912,68921,69248,69289,69291,69292, - 69296,69297,69373,69404,69415,69415,69424,69456,69488,69509,69552,69572, - 69600,69622,69632,69702,69734,69749,69759,69818,69826,69826,69840,69864, - 69872,69881,69888,69940,69942,69951,69956,69959,69968,70003,70006,70006, - 70016,70084,70089,70092,70094,70106,70108,70108,70144,70161,70163,70199, - 70206,70209,70272,70278,70280,70280,70282,70285,70287,70301,70303,70312, - 70320,70378,70384,70393,70400,70403,70405,70412,70415,70416,70419,70440, - 70442,70448,70450,70451,70453,70457,70459,70468,70471,70472,70475,70477, - 70480,70480,70487,70487,70493,70499,70502,70508,70512,70516,70656,70730, - 70736,70745,70750,70753,70784,70853,70855,70855,70864,70873,71040,71093, - 71096,71104,71128,71133,71168,71232,71236,71236,71248,71257,71296,71352, - 71360,71369,71424,71450,71453,71467,71472,71481,71488,71494,71680,71738, - 71840,71913,71935,71942,71945,71945,71948,71955,71957,71958,71960,71989, - 71991,71992,71995,72003,72016,72025,72096,72103,72106,72151,72154,72161, - 72163,72164,72192,72254,72263,72263,72272,72345,72349,72349,72368,72440, - 72704,72712,72714,72758,72760,72768,72784,72793,72818,72847,72850,72871, - 72873,72886,72960,72966,72968,72969,72971,73014,73018,73018,73020,73021, - 73023,73031,73040,73049,73056,73061,73063,73064,73066,73102,73104,73105, - 73107,73112,73120,73129,73440,73462,73472,73488,73490,73530,73534,73538, - 73552,73561,73648,73648,73728,74649,74752,74862,74880,75075,77712,77808, - 77824,78895,78912,78933,82944,83526,92160,92728,92736,92766,92768,92777, - 92784,92862,92864,92873,92880,92909,92912,92916,92928,92982,92992,92995, - 93008,93017,93027,93047,93053,93071,93760,93823,93952,94026,94031,94087, - 94095,94111,94176,94177,94179,94180,94192,94193,94208,100343,100352,101589, - 101632,101640,110576,110579,110581,110587,110589,110590,110592,110882, - 110898,110898,110928,110930,110933,110933,110948,110951,110960,111355, - 113664,113770,113776,113788,113792,113800,113808,113817,113821,113822, - 118528,118573,118576,118598,119141,119145,119149,119154,119163,119170, - 119173,119179,119210,119213,119362,119364,119808,119892,119894,119964, - 119966,119967,119970,119970,119973,119974,119977,119980,119982,119993, - 119995,119995,119997,120003,120005,120069,120071,120074,120077,120084, - 120086,120092,120094,120121,120123,120126,120128,120132,120134,120134, - 120138,120144,120146,120485,120488,120512,120514,120538,120540,120570, - 120572,120596,120598,120628,120630,120654,120656,120686,120688,120712, - 120714,120744,120746,120770,120772,120779,120782,120831,121344,121398, - 121403,121452,121461,121461,121476,121476,121499,121503,121505,121519, - 122624,122654,122661,122666,122880,122886,122888,122904,122907,122913, - 122915,122916,122918,122922,122928,122989,123023,123023,123136,123180, - 123184,123197,123200,123209,123214,123214,123536,123566,123584,123641, - 124112,124153,124896,124902,124904,124907,124909,124910,124912,124926, - 124928,125124,125136,125142,125184,125259,125264,125273,126464,126467, - 126469,126495,126497,126498,126500,126500,126503,126503,126505,126514, - 126516,126519,126521,126521,126523,126523,126530,126530,126535,126535, - 126537,126537,126539,126539,126541,126543,126545,126546,126548,126548, - 126551,126551,126553,126553,126555,126555,126557,126557,126559,126559, - 126561,126562,126564,126564,126567,126570,126572,126578,126580,126583, - 126585,126588,126590,126590,126592,126601,126603,126619,126625,126627, - 126629,126633,126635,126651,130032,130041,131072,173791,173824,177977, - 177984,178205,178208,183969,183984,191456,194560,195101,196608,201546, - 201552,205743,917760,917999,1,0,42,42,2,0,39,39,92,92,2,0,10,10,13,13, - 1,0,47,47,1,0,29,29,1,0,28,28,1,0,13,13,21,0,36,36,162,165,1423,1423, - 1547,1547,2046,2047,2546,2547,2555,2555,2801,2801,3065,3065,3647,3647, - 6107,6107,8352,8384,43064,43064,65020,65020,65129,65129,65284,65284,65504, - 65505,65509,65510,73693,73696,123647,123647,126128,126128,1,0,32,32,6, - 0,95,95,8255,8256,8276,8276,65075,65076,65101,65103,65343,65343,1,0,9, - 9,2,0,34,34,92,92,1,0,10,10,1,0,11,11,1,0,31,31,659,0,65,90,97,122,170, - 170,181,181,186,186,192,214,216,246,248,705,710,721,736,740,748,748,750, - 750,880,884,886,887,890,893,895,895,902,902,904,906,908,908,910,929,931, - 1013,1015,1153,1162,1327,1329,1366,1369,1369,1376,1416,1488,1514,1519, - 1522,1568,1610,1646,1647,1649,1747,1749,1749,1765,1766,1774,1775,1786, - 1788,1791,1791,1808,1808,1810,1839,1869,1957,1969,1969,1994,2026,2036, - 2037,2042,2042,2048,2069,2074,2074,2084,2084,2088,2088,2112,2136,2144, - 2154,2160,2183,2185,2190,2208,2249,2308,2361,2365,2365,2384,2384,2392, - 2401,2417,2432,2437,2444,2447,2448,2451,2472,2474,2480,2482,2482,2486, - 2489,2493,2493,2510,2510,2524,2525,2527,2529,2544,2545,2556,2556,2565, - 2570,2575,2576,2579,2600,2602,2608,2610,2611,2613,2614,2616,2617,2649, - 2652,2654,2654,2674,2676,2693,2701,2703,2705,2707,2728,2730,2736,2738, - 2739,2741,2745,2749,2749,2768,2768,2784,2785,2809,2809,2821,2828,2831, - 2832,2835,2856,2858,2864,2866,2867,2869,2873,2877,2877,2908,2909,2911, - 2913,2929,2929,2947,2947,2949,2954,2958,2960,2962,2965,2969,2970,2972, - 2972,2974,2975,2979,2980,2984,2986,2990,3001,3024,3024,3077,3084,3086, - 3088,3090,3112,3114,3129,3133,3133,3160,3162,3165,3165,3168,3169,3200, - 3200,3205,3212,3214,3216,3218,3240,3242,3251,3253,3257,3261,3261,3293, - 3294,3296,3297,3313,3314,3332,3340,3342,3344,3346,3386,3389,3389,3406, - 3406,3412,3414,3423,3425,3450,3455,3461,3478,3482,3505,3507,3515,3517, - 3517,3520,3526,3585,3632,3634,3635,3648,3654,3713,3714,3716,3716,3718, - 3722,3724,3747,3749,3749,3751,3760,3762,3763,3773,3773,3776,3780,3782, - 3782,3804,3807,3840,3840,3904,3911,3913,3948,3976,3980,4096,4138,4159, - 4159,4176,4181,4186,4189,4193,4193,4197,4198,4206,4208,4213,4225,4238, - 4238,4256,4293,4295,4295,4301,4301,4304,4346,4348,4680,4682,4685,4688, - 4694,4696,4696,4698,4701,4704,4744,4746,4749,4752,4784,4786,4789,4792, - 4798,4800,4800,4802,4805,4808,4822,4824,4880,4882,4885,4888,4954,4992, - 5007,5024,5109,5112,5117,5121,5740,5743,5759,5761,5786,5792,5866,5870, - 5880,5888,5905,5919,5937,5952,5969,5984,5996,5998,6000,6016,6067,6103, - 6103,6108,6108,6176,6264,6272,6312,6314,6314,6320,6389,6400,6430,6480, - 6509,6512,6516,6528,6571,6576,6601,6656,6678,6688,6740,6823,6823,6917, - 6963,6981,6988,7043,7072,7086,7087,7098,7141,7168,7203,7245,7247,7258, - 7293,7296,7304,7312,7354,7357,7359,7401,7404,7406,7411,7413,7414,7418, - 7418,7424,7615,7680,7957,7960,7965,7968,8005,8008,8013,8016,8023,8025, - 8025,8027,8027,8029,8029,8031,8061,8064,8116,8118,8124,8126,8126,8130, - 8132,8134,8140,8144,8147,8150,8155,8160,8172,8178,8180,8182,8188,8305, - 8305,8319,8319,8336,8348,8450,8450,8455,8455,8458,8467,8469,8469,8472, - 8477,8484,8484,8486,8486,8488,8488,8490,8505,8508,8511,8517,8521,8526, - 8526,8544,8584,11264,11492,11499,11502,11506,11507,11520,11557,11559, - 11559,11565,11565,11568,11623,11631,11631,11648,11670,11680,11686,11688, - 11694,11696,11702,11704,11710,11712,11718,11720,11726,11728,11734,11736, - 11742,12293,12295,12321,12329,12337,12341,12344,12348,12353,12438,12443, + 7,164,2,165,7,165,2,166,7,166,2,167,7,167,2,168,7,168,2,169,7,169,2,170, + 7,170,2,171,7,171,1,0,1,0,1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,6, + 1,6,1,7,1,7,1,8,1,8,1,9,1,9,1,10,1,10,1,10,1,11,1,11,1,11,1,12,1,12,1, + 13,1,13,1,13,1,14,1,14,1,15,1,15,1,15,1,16,1,16,1,17,1,17,1,17,1,18,1, + 18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,23,1,24,1, + 24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1,30,1,31,1, + 31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,1,36,1,37,1,37,1,38,1, + 38,1,39,1,39,1,40,1,40,1,41,1,41,1,42,1,42,1,43,1,43,1,44,1,44,1,45,1, + 45,1,45,1,45,1,45,1,45,1,45,1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,47,1, + 47,1,47,1,47,1,47,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1,49,1,49,1, + 49,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1, + 52,1,52,1,52,1,52,1,52,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1, + 54,1,54,1,54,1,54,1,54,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,56,1,56,1, + 56,1,56,1,56,1,56,1,56,1,56,1,56,1,57,1,57,1,57,1,57,1,57,1,58,1,58,1, + 58,1,58,1,58,1,58,1,59,1,59,1,59,1,59,1,59,1,59,1,60,1,60,1,60,1,60,1, + 60,1,60,1,60,1,60,1,60,1,61,1,61,1,61,1,61,1,61,1,62,1,62,1,62,1,62,1, + 62,1,62,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,64,1,64,1,64,1,64,1, + 64,1,64,1,64,1,65,1,65,1,65,1,65,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1, + 66,1,67,1,67,1,67,1,67,1,68,1,68,1,68,1,68,1,69,1,69,1,69,1,70,1,70,1, + 70,1,70,1,70,1,70,1,70,1,70,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1, + 72,1,72,1,72,1,72,1,72,1,72,1,73,1,73,1,73,1,73,1,73,1,73,1,73,1,73,1, + 73,1,73,1,73,1,73,1,74,1,74,1,74,1,74,1,74,1,75,1,75,1,75,1,75,1,75,1, + 76,1,76,1,76,1,76,1,76,1,76,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,78,1, + 78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1, + 78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,79,1,79,1,79,1,79,1,79,1,79,1, + 79,1,79,1,79,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1, + 80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1, + 81,1,81,1,81,1,81,1,81,1,81,1,81,1,81,1,82,1,82,1,82,1,82,1,82,1,82,1, + 82,1,82,1,82,1,82,1,83,1,83,1,83,1,83,1,83,1,83,1,84,1,84,1,84,1,84,1, + 85,1,85,1,85,1,85,1,85,1,86,1,86,1,86,1,86,1,86,1,86,1,86,1,86,1,87,1, + 87,1,87,1,87,1,87,1,87,1,87,1,87,1,87,1,88,1,88,1,88,1,88,1,88,1,88,1, + 89,1,89,1,89,1,89,1,89,1,89,1,89,1,90,1,90,1,90,1,90,1,90,1,90,1,90,1, + 91,1,91,1,91,1,91,1,91,1,91,1,92,1,92,1,92,1,93,1,93,1,93,1,93,1,94,1, + 94,1,94,1,94,1,94,1,94,1,94,1,95,1,95,1,95,1,95,1,95,1,95,1,95,1,96,1, + 96,1,96,1,96,1,96,1,97,1,97,1,97,1,97,1,97,1,97,1,97,1,98,1,98,1,98,1, + 98,1,98,1,98,1,98,1,98,1,98,1,99,1,99,1,100,1,100,1,100,1,101,1,101,1, + 101,1,101,1,101,1,101,1,102,1,102,1,102,1,103,1,103,1,103,1,103,1,103, + 1,104,1,104,1,104,1,104,1,104,1,104,1,105,1,105,1,105,1,105,1,105,1,105, + 1,105,1,105,1,105,1,105,1,106,1,106,1,106,1,106,1,107,1,107,1,107,1,107, + 1,107,1,107,1,107,1,107,1,107,1,107,1,107,1,108,1,108,1,108,1,108,1,108, + 1,109,1,109,1,109,1,109,1,109,1,109,1,110,1,110,1,110,1,110,1,110,1,110, + 1,110,1,110,1,110,1,111,1,111,1,111,1,112,1,112,1,112,1,112,1,113,1,113, + 1,113,1,113,1,114,1,114,1,114,1,114,1,115,1,115,1,115,1,116,1,116,1,117, + 1,117,1,118,1,118,1,119,1,119,1,119,1,120,1,120,1,120,1,120,1,120,1,120, + 1,120,1,121,1,121,1,121,1,121,1,121,1,122,1,122,1,122,1,122,1,122,1,122, + 1,122,1,122,1,122,1,123,1,123,1,123,1,124,1,124,1,124,1,124,1,124,1,125, + 1,125,1,125,1,125,1,125,1,126,1,126,1,126,1,126,1,126,1,126,1,127,1,127, + 1,127,1,127,1,127,1,127,1,128,1,128,1,128,1,128,1,128,1,128,1,128,1,129, + 1,129,1,129,1,129,1,129,1,130,1,130,1,130,1,130,1,130,1,131,1,131,1,131, + 1,131,1,132,1,132,1,132,1,132,1,132,1,133,1,133,1,133,1,133,1,133,1,134, + 1,134,1,134,5,134,1005,8,134,10,134,12,134,1008,9,134,1,134,1,134,1,134, + 1,134,5,134,1014,8,134,10,134,12,134,1017,9,134,1,134,3,134,1020,8,134, + 1,135,1,135,1,135,1,135,1,135,1,135,1,135,1,135,1,135,1,135,1,135,1,135, + 1,135,1,135,1,135,1,135,1,135,1,135,3,135,1040,8,135,1,136,1,136,1,136, + 5,136,1045,8,136,10,136,12,136,1048,9,136,3,136,1050,8,136,1,137,3,137, + 1053,8,137,1,138,1,138,3,138,1057,8,138,1,139,1,139,3,139,1061,8,139, + 1,140,1,140,3,140,1065,8,140,1,141,1,141,1,142,1,142,1,143,5,143,1072, + 8,143,10,143,12,143,1075,9,143,1,143,1,143,4,143,1079,8,143,11,143,12, + 143,1080,1,144,1,144,5,144,1085,8,144,10,144,12,144,1088,9,144,1,145, + 1,145,3,145,1092,8,145,1,146,1,146,3,146,1096,8,146,1,147,1,147,5,147, + 1100,8,147,10,147,12,147,1103,9,147,1,147,4,147,1106,8,147,11,147,12, + 147,1107,1,148,4,148,1111,8,148,11,148,12,148,1112,1,149,1,149,1,149, + 1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,3,149,1127,8,149, + 1,150,1,150,1,150,1,150,1,150,1,150,5,150,1135,8,150,10,150,12,150,1138, + 9,150,1,150,1,150,1,150,1,150,1,150,1,150,5,150,1146,8,150,10,150,12, + 150,1149,9,150,1,150,3,150,1152,8,150,1,150,1,150,3,150,1156,8,150,3, + 150,1158,8,150,1,151,1,151,1,152,1,152,1,153,1,153,1,154,1,154,1,155, + 1,155,1,156,1,156,1,157,1,157,1,158,1,158,1,159,1,159,1,160,1,160,1,161, + 1,161,1,162,1,162,1,163,1,163,1,164,1,164,1,165,1,165,1,166,1,166,1,167, + 1,167,1,168,1,168,1,169,1,169,1,170,1,170,1,171,1,171,0,0,172,1,1,3,2, + 5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31, + 16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27, + 55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,37,75,38,77, + 39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,93,47,95,48,97,49,99,50, + 101,51,103,52,105,53,107,54,109,55,111,56,113,57,115,58,117,59,119,60, + 121,61,123,62,125,63,127,64,129,65,131,66,133,67,135,68,137,69,139,70, + 141,71,143,72,145,73,147,74,149,75,151,76,153,77,155,78,157,79,159,80, + 161,81,163,82,165,83,167,84,169,85,171,86,173,87,175,88,177,89,179,90, + 181,91,183,92,185,93,187,94,189,95,191,96,193,97,195,98,197,99,199,100, + 201,101,203,102,205,103,207,104,209,105,211,106,213,107,215,108,217,109, + 219,110,221,111,223,112,225,113,227,114,229,115,231,116,233,117,235,118, + 237,119,239,120,241,121,243,122,245,123,247,124,249,125,251,126,253,127, + 255,128,257,129,259,130,261,131,263,132,265,133,267,134,269,135,271,136, + 273,137,275,138,277,139,279,140,281,141,283,142,285,143,287,144,289,145, + 291,146,293,147,295,148,297,149,299,150,301,151,303,0,305,0,307,0,309, + 0,311,0,313,0,315,0,317,0,319,0,321,0,323,0,325,0,327,0,329,0,331,0,333, + 0,335,0,337,0,339,0,341,0,343,152,1,0,45,2,0,65,65,97,97,2,0,84,84,116, + 116,2,0,67,67,99,99,2,0,72,72,104,104,2,0,68,68,100,100,2,0,66,66,98, + 98,2,0,89,89,121,121,2,0,80,80,112,112,2,0,69,69,101,101,2,0,76,76,108, + 108,2,0,79,79,111,111,2,0,77,77,109,109,2,0,78,78,110,110,2,0,82,82,114, + 114,2,0,71,71,103,103,2,0,70,70,102,102,2,0,85,85,117,117,2,0,88,88,120, + 120,2,0,73,73,105,105,2,0,83,83,115,115,2,0,75,75,107,107,2,0,87,87,119, + 119,13,0,34,34,39,39,66,66,70,70,78,78,82,82,84,84,92,92,98,98,102,102, + 110,110,114,114,116,116,2,0,65,70,97,102,8,0,160,160,5760,5760,6158,6158, + 8192,8202,8232,8233,8239,8239,8287,8287,12288,12288,1,0,12,12,1,0,96, + 96,1,0,30,30,768,0,48,57,65,90,95,95,97,122,170,170,181,181,183,183,186, + 186,192,214,216,246,248,705,710,721,736,740,748,748,750,750,768,884,886, + 887,890,893,895,895,902,906,908,908,910,929,931,1013,1015,1153,1155,1159, + 1162,1327,1329,1366,1369,1369,1376,1416,1425,1469,1471,1471,1473,1474, + 1476,1477,1479,1479,1488,1514,1519,1522,1552,1562,1568,1641,1646,1747, + 1749,1756,1759,1768,1770,1788,1791,1791,1808,1866,1869,1969,1984,2037, + 2042,2042,2045,2045,2048,2093,2112,2139,2144,2154,2160,2183,2185,2190, + 2200,2273,2275,2403,2406,2415,2417,2435,2437,2444,2447,2448,2451,2472, + 2474,2480,2482,2482,2486,2489,2492,2500,2503,2504,2507,2510,2519,2519, + 2524,2525,2527,2531,2534,2545,2556,2556,2558,2558,2561,2563,2565,2570, + 2575,2576,2579,2600,2602,2608,2610,2611,2613,2614,2616,2617,2620,2620, + 2622,2626,2631,2632,2635,2637,2641,2641,2649,2652,2654,2654,2662,2677, + 2689,2691,2693,2701,2703,2705,2707,2728,2730,2736,2738,2739,2741,2745, + 2748,2757,2759,2761,2763,2765,2768,2768,2784,2787,2790,2799,2809,2815, + 2817,2819,2821,2828,2831,2832,2835,2856,2858,2864,2866,2867,2869,2873, + 2876,2884,2887,2888,2891,2893,2901,2903,2908,2909,2911,2915,2918,2927, + 2929,2929,2946,2947,2949,2954,2958,2960,2962,2965,2969,2970,2972,2972, + 2974,2975,2979,2980,2984,2986,2990,3001,3006,3010,3014,3016,3018,3021, + 3024,3024,3031,3031,3046,3055,3072,3084,3086,3088,3090,3112,3114,3129, + 3132,3140,3142,3144,3146,3149,3157,3158,3160,3162,3165,3165,3168,3171, + 3174,3183,3200,3203,3205,3212,3214,3216,3218,3240,3242,3251,3253,3257, + 3260,3268,3270,3272,3274,3277,3285,3286,3293,3294,3296,3299,3302,3311, + 3313,3315,3328,3340,3342,3344,3346,3396,3398,3400,3402,3406,3412,3415, + 3423,3427,3430,3439,3450,3455,3457,3459,3461,3478,3482,3505,3507,3515, + 3517,3517,3520,3526,3530,3530,3535,3540,3542,3542,3544,3551,3558,3567, + 3570,3571,3585,3642,3648,3662,3664,3673,3713,3714,3716,3716,3718,3722, + 3724,3747,3749,3749,3751,3773,3776,3780,3782,3782,3784,3790,3792,3801, + 3804,3807,3840,3840,3864,3865,3872,3881,3893,3893,3895,3895,3897,3897, + 3902,3911,3913,3948,3953,3972,3974,3991,3993,4028,4038,4038,4096,4169, + 4176,4253,4256,4293,4295,4295,4301,4301,4304,4346,4348,4680,4682,4685, + 4688,4694,4696,4696,4698,4701,4704,4744,4746,4749,4752,4784,4786,4789, + 4792,4798,4800,4800,4802,4805,4808,4822,4824,4880,4882,4885,4888,4954, + 4957,4959,4969,4977,4992,5007,5024,5109,5112,5117,5121,5740,5743,5759, + 5761,5786,5792,5866,5870,5880,5888,5909,5919,5940,5952,5971,5984,5996, + 5998,6000,6002,6003,6016,6099,6103,6103,6108,6109,6112,6121,6155,6157, + 6159,6169,6176,6264,6272,6314,6320,6389,6400,6430,6432,6443,6448,6459, + 6470,6509,6512,6516,6528,6571,6576,6601,6608,6618,6656,6683,6688,6750, + 6752,6780,6783,6793,6800,6809,6823,6823,6832,6845,6847,6862,6912,6988, + 6992,7001,7019,7027,7040,7155,7168,7223,7232,7241,7245,7293,7296,7304, + 7312,7354,7357,7359,7376,7378,7380,7418,7424,7957,7960,7965,7968,8005, + 8008,8013,8016,8023,8025,8025,8027,8027,8029,8029,8031,8061,8064,8116, + 8118,8124,8126,8126,8130,8132,8134,8140,8144,8147,8150,8155,8160,8172, + 8178,8180,8182,8188,8255,8256,8276,8276,8305,8305,8319,8319,8336,8348, + 8400,8412,8417,8417,8421,8432,8450,8450,8455,8455,8458,8467,8469,8469, + 8472,8477,8484,8484,8486,8486,8488,8488,8490,8505,8508,8511,8517,8521, + 8526,8526,8544,8584,11264,11492,11499,11507,11520,11557,11559,11559,11565, + 11565,11568,11623,11631,11631,11647,11670,11680,11686,11688,11694,11696, + 11702,11704,11710,11712,11718,11720,11726,11728,11734,11736,11742,11744, + 11775,12293,12295,12321,12335,12337,12341,12344,12348,12353,12438,12441, 12447,12449,12538,12540,12543,12549,12591,12593,12686,12704,12735,12784, - 12799,13312,19903,19968,42124,42192,42237,42240,42508,42512,42527,42538, - 42539,42560,42606,42623,42653,42656,42735,42775,42783,42786,42888,42891, - 42954,42960,42961,42963,42963,42965,42969,42994,43009,43011,43013,43015, - 43018,43020,43042,43072,43123,43138,43187,43250,43255,43259,43259,43261, - 43262,43274,43301,43312,43334,43360,43388,43396,43442,43471,43471,43488, - 43492,43494,43503,43514,43518,43520,43560,43584,43586,43588,43595,43616, - 43638,43642,43642,43646,43695,43697,43697,43701,43702,43705,43709,43712, - 43712,43714,43714,43739,43741,43744,43754,43762,43764,43777,43782,43785, - 43790,43793,43798,43808,43814,43816,43822,43824,43866,43868,43881,43888, - 44002,44032,55203,55216,55238,55243,55291,63744,64109,64112,64217,64256, - 64262,64275,64279,64285,64285,64287,64296,64298,64310,64312,64316,64318, - 64318,64320,64321,64323,64324,64326,64433,64467,64829,64848,64911,64914, - 64967,65008,65019,65136,65140,65142,65276,65313,65338,65345,65370,65382, - 65470,65474,65479,65482,65487,65490,65495,65498,65500,65536,65547,65549, - 65574,65576,65594,65596,65597,65599,65613,65616,65629,65664,65786,65856, - 65908,66176,66204,66208,66256,66304,66335,66349,66378,66384,66421,66432, - 66461,66464,66499,66504,66511,66513,66517,66560,66717,66736,66771,66776, - 66811,66816,66855,66864,66915,66928,66938,66940,66954,66956,66962,66964, - 66965,66967,66977,66979,66993,66995,67001,67003,67004,67072,67382,67392, - 67413,67424,67431,67456,67461,67463,67504,67506,67514,67584,67589,67592, - 67592,67594,67637,67639,67640,67644,67644,67647,67669,67680,67702,67712, - 67742,67808,67826,67828,67829,67840,67861,67872,67897,67968,68023,68030, - 68031,68096,68096,68112,68115,68117,68119,68121,68149,68192,68220,68224, - 68252,68288,68295,68297,68324,68352,68405,68416,68437,68448,68466,68480, - 68497,68608,68680,68736,68786,68800,68850,68864,68899,69248,69289,69296, - 69297,69376,69404,69415,69415,69424,69445,69488,69505,69552,69572,69600, - 69622,69635,69687,69745,69746,69749,69749,69763,69807,69840,69864,69891, - 69926,69956,69956,69959,69959,69968,70002,70006,70006,70019,70066,70081, - 70084,70106,70106,70108,70108,70144,70161,70163,70187,70207,70208,70272, - 70278,70280,70280,70282,70285,70287,70301,70303,70312,70320,70366,70405, - 70412,70415,70416,70419,70440,70442,70448,70450,70451,70453,70457,70461, - 70461,70480,70480,70493,70497,70656,70708,70727,70730,70751,70753,70784, - 70831,70852,70853,70855,70855,71040,71086,71128,71131,71168,71215,71236, - 71236,71296,71338,71352,71352,71424,71450,71488,71494,71680,71723,71840, - 71903,71935,71942,71945,71945,71948,71955,71957,71958,71960,71983,71999, - 71999,72001,72001,72096,72103,72106,72144,72161,72161,72163,72163,72192, - 72192,72203,72242,72250,72250,72272,72272,72284,72329,72349,72349,72368, - 72440,72704,72712,72714,72750,72768,72768,72818,72847,72960,72966,72968, - 72969,72971,73008,73030,73030,73056,73061,73063,73064,73066,73097,73112, - 73112,73440,73458,73474,73474,73476,73488,73490,73523,73648,73648,73728, - 74649,74752,74862,74880,75075,77712,77808,77824,78895,78913,78918,82944, - 83526,92160,92728,92736,92766,92784,92862,92880,92909,92928,92975,92992, - 92995,93027,93047,93053,93071,93760,93823,93952,94026,94032,94032,94099, - 94111,94176,94177,94179,94179,94208,100343,100352,101589,101632,101640, - 110576,110579,110581,110587,110589,110590,110592,110882,110898,110898, - 110928,110930,110933,110933,110948,110951,110960,111355,113664,113770, - 113776,113788,113792,113800,113808,113817,119808,119892,119894,119964, - 119966,119967,119970,119970,119973,119974,119977,119980,119982,119993, - 119995,119995,119997,120003,120005,120069,120071,120074,120077,120084, - 120086,120092,120094,120121,120123,120126,120128,120132,120134,120134, - 120138,120144,120146,120485,120488,120512,120514,120538,120540,120570, - 120572,120596,120598,120628,120630,120654,120656,120686,120688,120712, - 120714,120744,120746,120770,120772,120779,122624,122654,122661,122666, - 122928,122989,123136,123180,123191,123197,123214,123214,123536,123565, - 123584,123627,124112,124139,124896,124902,124904,124907,124909,124910, - 124912,124926,124928,125124,125184,125251,125259,125259,126464,126467, - 126469,126495,126497,126498,126500,126500,126503,126503,126505,126514, - 126516,126519,126521,126521,126523,126523,126530,126530,126535,126535, - 126537,126537,126539,126539,126541,126543,126545,126546,126548,126548, - 126551,126551,126553,126553,126555,126555,126557,126557,126559,126559, - 126561,126562,126564,126564,126567,126570,126572,126578,126580,126583, - 126585,126588,126590,126590,126592,126601,126603,126619,126625,126627, - 126629,126633,126635,126651,131072,173791,173824,177977,177984,178205, - 178208,183969,183984,191456,194560,195101,196608,201546,201552,205743, - 1178,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11, - 1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0, - 0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0, - 0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43, - 1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0, - 0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0, - 0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75, - 1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0, - 0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0, - 0,97,1,0,0,0,0,99,1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0, - 107,1,0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0, - 117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1,0,0,0,0, - 127,1,0,0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0,0,0,135,1,0,0,0,0, - 137,1,0,0,0,0,139,1,0,0,0,0,141,1,0,0,0,0,143,1,0,0,0,0,145,1,0,0,0,0, - 147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0,155,1,0,0,0,0, - 157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,0,165,1,0,0,0,0, - 167,1,0,0,0,0,169,1,0,0,0,0,171,1,0,0,0,0,173,1,0,0,0,0,175,1,0,0,0,0, - 177,1,0,0,0,0,179,1,0,0,0,0,181,1,0,0,0,0,183,1,0,0,0,0,185,1,0,0,0,0, - 187,1,0,0,0,0,189,1,0,0,0,0,191,1,0,0,0,0,193,1,0,0,0,0,195,1,0,0,0,0, - 197,1,0,0,0,0,199,1,0,0,0,0,201,1,0,0,0,0,203,1,0,0,0,0,205,1,0,0,0,0, - 207,1,0,0,0,0,209,1,0,0,0,0,211,1,0,0,0,0,213,1,0,0,0,0,215,1,0,0,0,0, - 217,1,0,0,0,0,219,1,0,0,0,0,221,1,0,0,0,0,223,1,0,0,0,0,225,1,0,0,0,0, - 227,1,0,0,0,0,229,1,0,0,0,0,231,1,0,0,0,0,233,1,0,0,0,0,235,1,0,0,0,0, - 237,1,0,0,0,0,239,1,0,0,0,0,241,1,0,0,0,0,243,1,0,0,0,0,245,1,0,0,0,0, - 247,1,0,0,0,0,249,1,0,0,0,0,251,1,0,0,0,0,253,1,0,0,0,0,255,1,0,0,0,0, - 257,1,0,0,0,0,259,1,0,0,0,0,261,1,0,0,0,0,263,1,0,0,0,0,265,1,0,0,0,0, - 267,1,0,0,0,0,269,1,0,0,0,0,271,1,0,0,0,0,273,1,0,0,0,0,275,1,0,0,0,0, - 277,1,0,0,0,0,279,1,0,0,0,0,281,1,0,0,0,0,283,1,0,0,0,0,285,1,0,0,0,0, - 287,1,0,0,0,0,289,1,0,0,0,0,291,1,0,0,0,0,293,1,0,0,0,0,295,1,0,0,0,0, - 297,1,0,0,0,0,339,1,0,0,0,1,341,1,0,0,0,3,343,1,0,0,0,5,345,1,0,0,0,7, - 347,1,0,0,0,9,349,1,0,0,0,11,351,1,0,0,0,13,353,1,0,0,0,15,355,1,0,0, - 0,17,357,1,0,0,0,19,359,1,0,0,0,21,361,1,0,0,0,23,364,1,0,0,0,25,367, - 1,0,0,0,27,369,1,0,0,0,29,372,1,0,0,0,31,374,1,0,0,0,33,377,1,0,0,0,35, - 379,1,0,0,0,37,382,1,0,0,0,39,385,1,0,0,0,41,387,1,0,0,0,43,389,1,0,0, - 0,45,391,1,0,0,0,47,393,1,0,0,0,49,396,1,0,0,0,51,398,1,0,0,0,53,400, - 1,0,0,0,55,402,1,0,0,0,57,404,1,0,0,0,59,406,1,0,0,0,61,408,1,0,0,0,63, - 410,1,0,0,0,65,412,1,0,0,0,67,414,1,0,0,0,69,416,1,0,0,0,71,418,1,0,0, - 0,73,420,1,0,0,0,75,422,1,0,0,0,77,424,1,0,0,0,79,426,1,0,0,0,81,428, - 1,0,0,0,83,430,1,0,0,0,85,432,1,0,0,0,87,434,1,0,0,0,89,436,1,0,0,0,91, - 438,1,0,0,0,93,443,1,0,0,0,95,451,1,0,0,0,97,457,1,0,0,0,99,462,1,0,0, - 0,101,467,1,0,0,0,103,472,1,0,0,0,105,479,1,0,0,0,107,486,1,0,0,0,109, - 493,1,0,0,0,111,502,1,0,0,0,113,507,1,0,0,0,115,513,1,0,0,0,117,519,1, - 0,0,0,119,528,1,0,0,0,121,533,1,0,0,0,123,539,1,0,0,0,125,547,1,0,0,0, - 127,554,1,0,0,0,129,558,1,0,0,0,131,566,1,0,0,0,133,570,1,0,0,0,135,574, - 1,0,0,0,137,577,1,0,0,0,139,585,1,0,0,0,141,593,1,0,0,0,143,599,1,0,0, - 0,145,611,1,0,0,0,147,616,1,0,0,0,149,621,1,0,0,0,151,627,1,0,0,0,153, - 634,1,0,0,0,155,657,1,0,0,0,157,666,1,0,0,0,159,691,1,0,0,0,161,699,1, - 0,0,0,163,709,1,0,0,0,165,715,1,0,0,0,167,719,1,0,0,0,169,724,1,0,0,0, - 171,732,1,0,0,0,173,741,1,0,0,0,175,747,1,0,0,0,177,754,1,0,0,0,179,761, - 1,0,0,0,181,767,1,0,0,0,183,770,1,0,0,0,185,774,1,0,0,0,187,781,1,0,0, - 0,189,788,1,0,0,0,191,793,1,0,0,0,193,800,1,0,0,0,195,809,1,0,0,0,197, - 811,1,0,0,0,199,814,1,0,0,0,201,820,1,0,0,0,203,823,1,0,0,0,205,828,1, - 0,0,0,207,834,1,0,0,0,209,844,1,0,0,0,211,848,1,0,0,0,213,859,1,0,0,0, - 215,864,1,0,0,0,217,870,1,0,0,0,219,879,1,0,0,0,221,882,1,0,0,0,223,886, - 1,0,0,0,225,890,1,0,0,0,227,894,1,0,0,0,229,897,1,0,0,0,231,899,1,0,0, - 0,233,901,1,0,0,0,235,903,1,0,0,0,237,906,1,0,0,0,239,913,1,0,0,0,241, - 918,1,0,0,0,243,927,1,0,0,0,245,930,1,0,0,0,247,935,1,0,0,0,249,940,1, - 0,0,0,251,946,1,0,0,0,253,952,1,0,0,0,255,959,1,0,0,0,257,964,1,0,0,0, - 259,969,1,0,0,0,261,973,1,0,0,0,263,978,1,0,0,0,265,1001,1,0,0,0,267, - 1003,1,0,0,0,269,1031,1,0,0,0,271,1034,1,0,0,0,273,1038,1,0,0,0,275,1042, - 1,0,0,0,277,1046,1,0,0,0,279,1048,1,0,0,0,281,1050,1,0,0,0,283,1055,1, - 0,0,0,285,1064,1,0,0,0,287,1073,1,0,0,0,289,1077,1,0,0,0,291,1087,1,0, - 0,0,293,1092,1,0,0,0,295,1108,1,0,0,0,297,1110,1,0,0,0,299,1124,1,0,0, - 0,301,1126,1,0,0,0,303,1128,1,0,0,0,305,1130,1,0,0,0,307,1132,1,0,0,0, - 309,1134,1,0,0,0,311,1136,1,0,0,0,313,1138,1,0,0,0,315,1140,1,0,0,0,317, - 1142,1,0,0,0,319,1144,1,0,0,0,321,1146,1,0,0,0,323,1148,1,0,0,0,325,1150, - 1,0,0,0,327,1152,1,0,0,0,329,1154,1,0,0,0,331,1156,1,0,0,0,333,1158,1, - 0,0,0,335,1160,1,0,0,0,337,1162,1,0,0,0,339,1164,1,0,0,0,341,342,5,59, - 0,0,342,2,1,0,0,0,343,344,5,40,0,0,344,4,1,0,0,0,345,346,5,41,0,0,346, - 6,1,0,0,0,347,348,5,44,0,0,348,8,1,0,0,0,349,350,5,61,0,0,350,10,1,0, - 0,0,351,352,5,91,0,0,352,12,1,0,0,0,353,354,5,93,0,0,354,14,1,0,0,0,355, - 356,5,123,0,0,356,16,1,0,0,0,357,358,5,125,0,0,358,18,1,0,0,0,359,360, - 5,124,0,0,360,20,1,0,0,0,361,362,5,46,0,0,362,363,5,46,0,0,363,22,1,0, - 0,0,364,365,5,60,0,0,365,366,5,62,0,0,366,24,1,0,0,0,367,368,5,60,0,0, - 368,26,1,0,0,0,369,370,5,60,0,0,370,371,5,61,0,0,371,28,1,0,0,0,372,373, - 5,62,0,0,373,30,1,0,0,0,374,375,5,62,0,0,375,376,5,61,0,0,376,32,1,0, - 0,0,377,378,5,38,0,0,378,34,1,0,0,0,379,380,5,62,0,0,380,381,5,62,0,0, - 381,36,1,0,0,0,382,383,5,60,0,0,383,384,5,60,0,0,384,38,1,0,0,0,385,386, - 5,43,0,0,386,40,1,0,0,0,387,388,5,47,0,0,388,42,1,0,0,0,389,390,5,37, - 0,0,390,44,1,0,0,0,391,392,5,94,0,0,392,46,1,0,0,0,393,394,5,61,0,0,394, - 395,5,126,0,0,395,48,1,0,0,0,396,397,5,46,0,0,397,50,1,0,0,0,398,399, - 5,36,0,0,399,52,1,0,0,0,400,401,5,10216,0,0,401,54,1,0,0,0,402,403,5, - 12296,0,0,403,56,1,0,0,0,404,405,5,65124,0,0,405,58,1,0,0,0,406,407,5, - 65308,0,0,407,60,1,0,0,0,408,409,5,10217,0,0,409,62,1,0,0,0,410,411,5, - 12297,0,0,411,64,1,0,0,0,412,413,5,65125,0,0,413,66,1,0,0,0,414,415,5, - 65310,0,0,415,68,1,0,0,0,416,417,5,173,0,0,417,70,1,0,0,0,418,419,5,8208, - 0,0,419,72,1,0,0,0,420,421,5,8209,0,0,421,74,1,0,0,0,422,423,5,8210,0, - 0,423,76,1,0,0,0,424,425,5,8211,0,0,425,78,1,0,0,0,426,427,5,8212,0,0, - 427,80,1,0,0,0,428,429,5,8213,0,0,429,82,1,0,0,0,430,431,5,8722,0,0,431, - 84,1,0,0,0,432,433,5,65112,0,0,433,86,1,0,0,0,434,435,5,65123,0,0,435, - 88,1,0,0,0,436,437,5,65293,0,0,437,90,1,0,0,0,438,439,7,0,0,0,439,440, - 7,1,0,0,440,441,7,2,0,0,441,442,7,2,0,0,442,92,1,0,0,0,443,444,7,0,0, - 0,444,445,7,3,0,0,445,446,7,4,0,0,446,447,7,4,0,0,447,448,7,5,0,0,448, - 449,7,6,0,0,449,450,7,7,0,0,450,94,1,0,0,0,451,452,7,4,0,0,452,453,7, - 1,0,0,453,454,7,0,0,0,454,455,7,8,0,0,455,456,7,3,0,0,456,96,1,0,0,0, - 457,458,7,9,0,0,458,459,7,2,0,0,459,460,7,3,0,0,460,461,7,10,0,0,461, - 98,1,0,0,0,462,463,7,0,0,0,463,464,7,3,0,0,464,465,7,11,0,0,465,466,7, - 12,0,0,466,100,1,0,0,0,467,468,7,13,0,0,468,469,7,8,0,0,469,470,7,3,0, - 0,470,471,7,4,0,0,471,102,1,0,0,0,472,473,7,0,0,0,473,474,7,3,0,0,474, - 475,7,2,0,0,475,476,7,14,0,0,476,477,7,4,0,0,477,478,7,6,0,0,478,104, - 1,0,0,0,479,480,7,5,0,0,480,481,7,15,0,0,481,482,7,11,0,0,482,483,7,3, - 0,0,483,484,7,8,0,0,484,485,7,7,0,0,485,106,1,0,0,0,486,487,7,16,0,0, - 487,488,7,4,0,0,488,489,7,11,0,0,489,490,7,3,0,0,490,491,7,8,0,0,491, - 492,7,7,0,0,492,108,1,0,0,0,493,494,7,17,0,0,494,495,7,1,0,0,495,496, - 7,7,0,0,496,497,7,1,0,0,497,498,7,10,0,0,498,499,7,1,0,0,499,500,7,18, - 0,0,500,501,7,5,0,0,501,110,1,0,0,0,502,503,7,6,0,0,503,504,7,3,0,0,504, - 505,7,17,0,0,505,506,7,5,0,0,506,112,1,0,0,0,507,508,7,7,0,0,508,509, - 7,1,0,0,509,510,7,10,0,0,510,511,7,2,0,0,511,512,7,5,0,0,512,114,1,0, - 0,0,513,514,7,9,0,0,514,515,7,8,0,0,515,516,7,3,0,0,516,517,7,14,0,0, - 517,518,7,11,0,0,518,116,1,0,0,0,519,520,7,8,0,0,520,521,7,17,0,0,521, - 522,7,13,0,0,522,523,7,9,0,0,523,524,7,8,0,0,524,525,7,1,0,0,525,526, - 7,11,0,0,526,527,7,19,0,0,527,118,1,0,0,0,528,529,7,17,0,0,529,530,7, - 8,0,0,530,531,7,3,0,0,531,532,7,11,0,0,532,120,1,0,0,0,533,534,7,1,0, - 0,534,535,7,2,0,0,535,536,7,7,0,0,536,537,7,5,0,0,537,538,7,8,0,0,538, - 122,1,0,0,0,539,540,7,17,0,0,540,541,7,5,0,0,541,542,7,13,0,0,542,543, - 7,1,0,0,543,544,7,14,0,0,544,545,7,2,0,0,545,546,7,7,0,0,546,124,1,0, - 0,0,547,548,7,8,0,0,548,549,7,5,0,0,549,550,7,6,0,0,550,551,7,1,0,0,551, - 552,7,4,0,0,552,553,7,5,0,0,553,126,1,0,0,0,554,555,7,1,0,0,555,556,7, - 17,0,0,556,557,7,17,0,0,557,128,1,0,0,0,558,559,7,11,0,0,559,560,7,8, - 0,0,560,561,7,16,0,0,561,562,7,4,0,0,562,563,7,1,0,0,563,564,7,8,0,0, - 564,565,7,12,0,0,565,130,1,0,0,0,566,567,7,20,0,0,567,568,7,5,0,0,568, - 569,7,12,0,0,569,132,1,0,0,0,570,571,7,8,0,0,571,572,7,5,0,0,572,573, - 7,2,0,0,573,134,1,0,0,0,574,575,7,7,0,0,575,576,7,3,0,0,576,136,1,0,0, - 0,577,578,7,5,0,0,578,579,7,15,0,0,579,580,7,11,0,0,580,581,7,2,0,0,581, - 582,7,1,0,0,582,583,7,16,0,0,583,584,7,6,0,0,584,138,1,0,0,0,585,586, - 7,11,0,0,586,587,7,8,0,0,587,588,7,3,0,0,588,589,7,13,0,0,589,590,7,16, - 0,0,590,591,7,2,0,0,591,592,7,5,0,0,592,140,1,0,0,0,593,594,7,10,0,0, - 594,595,7,5,0,0,595,596,7,9,0,0,596,597,7,16,0,0,597,598,7,6,0,0,598, - 142,1,0,0,0,599,600,7,7,0,0,600,601,7,8,0,0,601,602,7,1,0,0,602,603,7, - 6,0,0,603,604,7,18,0,0,604,605,7,1,0,0,605,606,7,0,0,0,606,607,7,7,0, - 0,607,608,7,16,0,0,608,609,7,3,0,0,609,610,7,6,0,0,610,144,1,0,0,0,611, - 612,7,8,0,0,612,613,7,5,0,0,613,614,7,1,0,0,614,615,7,17,0,0,615,146, - 1,0,0,0,616,617,7,3,0,0,617,618,7,6,0,0,618,619,7,2,0,0,619,620,7,12, - 0,0,620,148,1,0,0,0,621,622,7,21,0,0,622,623,7,8,0,0,623,624,7,16,0,0, - 624,625,7,7,0,0,625,626,7,5,0,0,626,150,1,0,0,0,627,628,7,0,0,0,628,629, - 7,3,0,0,629,630,7,4,0,0,630,631,7,4,0,0,631,632,7,16,0,0,632,633,7,7, - 0,0,633,152,1,0,0,0,634,635,7,0,0,0,635,636,7,3,0,0,636,637,7,4,0,0,637, - 638,7,4,0,0,638,639,7,16,0,0,639,640,7,7,0,0,640,641,5,95,0,0,641,642, - 7,18,0,0,642,643,7,20,0,0,643,644,7,16,0,0,644,645,7,11,0,0,645,646,5, - 95,0,0,646,647,7,0,0,0,647,648,7,19,0,0,648,649,7,5,0,0,649,650,7,0,0, - 0,650,651,7,20,0,0,651,652,7,11,0,0,652,653,7,3,0,0,653,654,7,16,0,0, - 654,655,7,6,0,0,655,656,7,7,0,0,656,154,1,0,0,0,657,658,7,8,0,0,658,659, - 7,3,0,0,659,660,7,2,0,0,660,661,7,2,0,0,661,662,7,10,0,0,662,663,7,1, - 0,0,663,664,7,0,0,0,664,665,7,20,0,0,665,156,1,0,0,0,666,667,7,8,0,0, - 667,668,7,3,0,0,668,669,7,2,0,0,669,670,7,2,0,0,670,671,7,10,0,0,671, - 672,7,1,0,0,672,673,7,0,0,0,673,674,7,20,0,0,674,675,5,95,0,0,675,676, - 7,18,0,0,676,677,7,20,0,0,677,678,7,16,0,0,678,679,7,11,0,0,679,680,5, - 95,0,0,680,681,7,0,0,0,681,682,7,19,0,0,682,683,7,5,0,0,683,684,7,0,0, - 0,684,685,7,20,0,0,685,686,7,11,0,0,686,687,7,3,0,0,687,688,7,16,0,0, - 688,689,7,6,0,0,689,690,7,7,0,0,690,158,1,0,0,0,691,692,7,16,0,0,692, - 693,7,6,0,0,693,694,7,18,0,0,694,695,7,7,0,0,695,696,7,1,0,0,696,697, - 7,2,0,0,697,698,7,2,0,0,698,160,1,0,0,0,699,700,7,5,0,0,700,701,7,15, - 0,0,701,702,7,7,0,0,702,703,7,5,0,0,703,704,7,6,0,0,704,705,7,18,0,0, - 705,706,7,16,0,0,706,707,7,3,0,0,707,708,7,6,0,0,708,162,1,0,0,0,709, - 710,7,14,0,0,710,711,7,6,0,0,711,712,7,16,0,0,712,713,7,3,0,0,713,714, - 7,6,0,0,714,164,1,0,0,0,715,716,7,1,0,0,716,717,7,2,0,0,717,718,7,2,0, - 0,718,166,1,0,0,0,719,720,7,2,0,0,720,721,7,3,0,0,721,722,7,1,0,0,722, - 723,7,17,0,0,723,168,1,0,0,0,724,725,7,19,0,0,725,726,7,5,0,0,726,727, - 7,1,0,0,727,728,7,17,0,0,728,729,7,5,0,0,729,730,7,8,0,0,730,731,7,18, - 0,0,731,170,1,0,0,0,732,733,7,3,0,0,733,734,7,11,0,0,734,735,7,7,0,0, - 735,736,7,16,0,0,736,737,7,3,0,0,737,738,7,6,0,0,738,739,7,1,0,0,739, - 740,7,2,0,0,740,172,1,0,0,0,741,742,7,4,0,0,742,743,7,1,0,0,743,744,7, - 7,0,0,744,745,7,0,0,0,745,746,7,19,0,0,746,174,1,0,0,0,747,748,7,14,0, - 0,748,749,7,6,0,0,749,750,7,21,0,0,750,751,7,16,0,0,751,752,7,6,0,0,752, - 753,7,17,0,0,753,176,1,0,0,0,754,755,7,0,0,0,755,756,7,8,0,0,756,757, - 7,5,0,0,757,758,7,1,0,0,758,759,7,7,0,0,759,760,7,5,0,0,760,178,1,0,0, - 0,761,762,7,4,0,0,762,763,7,5,0,0,763,764,7,8,0,0,764,765,7,9,0,0,765, - 766,7,5,0,0,766,180,1,0,0,0,767,768,7,3,0,0,768,769,7,6,0,0,769,182,1, - 0,0,0,770,771,7,18,0,0,771,772,7,5,0,0,772,773,7,7,0,0,773,184,1,0,0, - 0,774,775,7,17,0,0,775,776,7,5,0,0,776,777,7,7,0,0,777,778,7,1,0,0,778, - 779,7,0,0,0,779,780,7,19,0,0,780,186,1,0,0,0,781,782,7,17,0,0,782,783, - 7,5,0,0,783,784,7,2,0,0,784,785,7,5,0,0,785,786,7,7,0,0,786,787,7,5,0, - 0,787,188,1,0,0,0,788,789,7,21,0,0,789,790,7,16,0,0,790,791,7,7,0,0,791, - 792,7,19,0,0,792,190,1,0,0,0,793,794,7,8,0,0,794,795,7,5,0,0,795,796, - 7,7,0,0,796,797,7,14,0,0,797,798,7,8,0,0,798,799,7,6,0,0,799,192,1,0, - 0,0,800,801,7,17,0,0,801,802,7,16,0,0,802,803,7,18,0,0,803,804,7,7,0, - 0,804,805,7,16,0,0,805,806,7,6,0,0,806,807,7,0,0,0,807,808,7,7,0,0,808, - 194,1,0,0,0,809,810,5,42,0,0,810,196,1,0,0,0,811,812,7,1,0,0,812,813, - 7,18,0,0,813,198,1,0,0,0,814,815,7,3,0,0,815,816,7,8,0,0,816,817,7,17, - 0,0,817,818,7,5,0,0,818,819,7,8,0,0,819,200,1,0,0,0,820,821,7,10,0,0, - 821,822,7,12,0,0,822,202,1,0,0,0,823,824,7,18,0,0,824,825,7,20,0,0,825, - 826,7,16,0,0,826,827,7,11,0,0,827,204,1,0,0,0,828,829,7,2,0,0,829,830, - 7,16,0,0,830,831,7,4,0,0,831,832,7,16,0,0,832,833,7,7,0,0,833,206,1,0, - 0,0,834,835,7,1,0,0,835,836,7,18,0,0,836,837,7,0,0,0,837,838,7,5,0,0, - 838,839,7,6,0,0,839,840,7,17,0,0,840,841,7,16,0,0,841,842,7,6,0,0,842, - 843,7,9,0,0,843,208,1,0,0,0,844,845,7,1,0,0,845,846,7,18,0,0,846,847, - 7,0,0,0,847,210,1,0,0,0,848,849,7,17,0,0,849,850,7,5,0,0,850,851,7,18, - 0,0,851,852,7,0,0,0,852,853,7,5,0,0,853,854,7,6,0,0,854,855,7,17,0,0, - 855,856,7,16,0,0,856,857,7,6,0,0,857,858,7,9,0,0,858,212,1,0,0,0,859, - 860,7,17,0,0,860,861,7,5,0,0,861,862,7,18,0,0,862,863,7,0,0,0,863,214, - 1,0,0,0,864,865,7,21,0,0,865,866,7,19,0,0,866,867,7,5,0,0,867,868,7,8, - 0,0,868,869,7,5,0,0,869,216,1,0,0,0,870,871,7,18,0,0,871,872,7,19,0,0, - 872,873,7,3,0,0,873,874,7,8,0,0,874,875,7,7,0,0,875,876,7,5,0,0,876,877, - 7,18,0,0,877,878,7,7,0,0,878,218,1,0,0,0,879,880,7,3,0,0,880,881,7,8, - 0,0,881,220,1,0,0,0,882,883,7,15,0,0,883,884,7,3,0,0,884,885,7,8,0,0, - 885,222,1,0,0,0,886,887,7,1,0,0,887,888,7,6,0,0,888,889,7,17,0,0,889, - 224,1,0,0,0,890,891,7,6,0,0,891,892,7,3,0,0,892,893,7,7,0,0,893,226,1, - 0,0,0,894,895,5,33,0,0,895,896,5,61,0,0,896,228,1,0,0,0,897,898,5,45, - 0,0,898,230,1,0,0,0,899,900,5,33,0,0,900,232,1,0,0,0,901,902,5,58,0,0, - 902,234,1,0,0,0,903,904,7,16,0,0,904,905,7,6,0,0,905,236,1,0,0,0,906, - 907,7,18,0,0,907,908,7,7,0,0,908,909,7,1,0,0,909,910,7,8,0,0,910,911, - 7,7,0,0,911,912,7,18,0,0,912,238,1,0,0,0,913,914,7,5,0,0,914,915,7,6, - 0,0,915,916,7,17,0,0,916,917,7,18,0,0,917,240,1,0,0,0,918,919,7,0,0,0, - 919,920,7,3,0,0,920,921,7,6,0,0,921,922,7,7,0,0,922,923,7,1,0,0,923,924, - 7,16,0,0,924,925,7,6,0,0,925,926,7,18,0,0,926,242,1,0,0,0,927,928,7,16, - 0,0,928,929,7,18,0,0,929,244,1,0,0,0,930,931,7,6,0,0,931,932,7,14,0,0, - 932,933,7,2,0,0,933,934,7,2,0,0,934,246,1,0,0,0,935,936,7,7,0,0,936,937, - 7,8,0,0,937,938,7,14,0,0,938,939,7,5,0,0,939,248,1,0,0,0,940,941,7,13, - 0,0,941,942,7,1,0,0,942,943,7,2,0,0,943,944,7,18,0,0,944,945,7,5,0,0, - 945,250,1,0,0,0,946,947,7,0,0,0,947,948,7,3,0,0,948,949,7,14,0,0,949, - 950,7,6,0,0,950,951,7,7,0,0,951,252,1,0,0,0,952,953,7,5,0,0,953,954,7, - 15,0,0,954,955,7,16,0,0,955,956,7,18,0,0,956,957,7,7,0,0,957,958,7,18, - 0,0,958,254,1,0,0,0,959,960,7,0,0,0,960,961,7,1,0,0,961,962,7,18,0,0, - 962,963,7,5,0,0,963,256,1,0,0,0,964,965,7,5,0,0,965,966,7,2,0,0,966,967, - 7,18,0,0,967,968,7,5,0,0,968,258,1,0,0,0,969,970,7,5,0,0,970,971,7,6, - 0,0,971,972,7,17,0,0,972,260,1,0,0,0,973,974,7,21,0,0,974,975,7,19,0, - 0,975,976,7,5,0,0,976,977,7,6,0,0,977,262,1,0,0,0,978,979,7,7,0,0,979, - 980,7,19,0,0,980,981,7,5,0,0,981,982,7,6,0,0,982,264,1,0,0,0,983,988, - 5,34,0,0,984,987,3,329,164,0,985,987,3,267,133,0,986,984,1,0,0,0,986, - 985,1,0,0,0,987,990,1,0,0,0,988,986,1,0,0,0,988,989,1,0,0,0,989,991,1, - 0,0,0,990,988,1,0,0,0,991,1002,5,34,0,0,992,997,5,39,0,0,993,996,3,309, - 154,0,994,996,3,267,133,0,995,993,1,0,0,0,995,994,1,0,0,0,996,999,1,0, - 0,0,997,995,1,0,0,0,997,998,1,0,0,0,998,1000,1,0,0,0,999,997,1,0,0,0, - 1000,1002,5,39,0,0,1001,983,1,0,0,0,1001,992,1,0,0,0,1002,266,1,0,0,0, - 1003,1021,5,92,0,0,1004,1022,7,22,0,0,1005,1006,7,14,0,0,1006,1007,3, - 273,136,0,1007,1008,3,273,136,0,1008,1009,3,273,136,0,1009,1010,3,273, - 136,0,1010,1022,1,0,0,0,1011,1012,7,14,0,0,1012,1013,3,273,136,0,1013, - 1014,3,273,136,0,1014,1015,3,273,136,0,1015,1016,3,273,136,0,1016,1017, - 3,273,136,0,1017,1018,3,273,136,0,1018,1019,3,273,136,0,1019,1020,3,273, - 136,0,1020,1022,1,0,0,0,1021,1004,1,0,0,0,1021,1005,1,0,0,0,1021,1011, - 1,0,0,0,1022,268,1,0,0,0,1023,1032,3,281,140,0,1024,1028,3,277,138,0, - 1025,1027,3,275,137,0,1026,1025,1,0,0,0,1027,1030,1,0,0,0,1028,1026,1, - 0,0,0,1028,1029,1,0,0,0,1029,1032,1,0,0,0,1030,1028,1,0,0,0,1031,1023, - 1,0,0,0,1031,1024,1,0,0,0,1032,270,1,0,0,0,1033,1035,7,23,0,0,1034,1033, - 1,0,0,0,1035,272,1,0,0,0,1036,1039,3,275,137,0,1037,1039,3,271,135,0, - 1038,1036,1,0,0,0,1038,1037,1,0,0,0,1039,274,1,0,0,0,1040,1043,3,281, - 140,0,1041,1043,3,277,138,0,1042,1040,1,0,0,0,1042,1041,1,0,0,0,1043, - 276,1,0,0,0,1044,1047,3,279,139,0,1045,1047,2,56,57,0,1046,1044,1,0,0, - 0,1046,1045,1,0,0,0,1047,278,1,0,0,0,1048,1049,2,49,55,0,1049,280,1,0, - 0,0,1050,1051,5,48,0,0,1051,282,1,0,0,0,1052,1054,3,275,137,0,1053,1052, - 1,0,0,0,1054,1057,1,0,0,0,1055,1053,1,0,0,0,1055,1056,1,0,0,0,1056,1058, - 1,0,0,0,1057,1055,1,0,0,0,1058,1060,5,46,0,0,1059,1061,3,275,137,0,1060, - 1059,1,0,0,0,1061,1062,1,0,0,0,1062,1060,1,0,0,0,1062,1063,1,0,0,0,1063, - 284,1,0,0,0,1064,1068,3,287,143,0,1065,1067,3,289,144,0,1066,1065,1,0, - 0,0,1067,1070,1,0,0,0,1068,1066,1,0,0,0,1068,1069,1,0,0,0,1069,286,1, - 0,0,0,1070,1068,1,0,0,0,1071,1074,3,337,168,0,1072,1074,3,325,162,0,1073, - 1071,1,0,0,0,1073,1072,1,0,0,0,1074,288,1,0,0,0,1075,1078,3,305,152,0, - 1076,1078,3,321,160,0,1077,1075,1,0,0,0,1077,1076,1,0,0,0,1078,290,1, - 0,0,0,1079,1083,5,96,0,0,1080,1082,3,301,150,0,1081,1080,1,0,0,0,1082, - 1085,1,0,0,0,1083,1081,1,0,0,0,1083,1084,1,0,0,0,1084,1086,1,0,0,0,1085, - 1083,1,0,0,0,1086,1088,5,96,0,0,1087,1079,1,0,0,0,1088,1089,1,0,0,0,1089, - 1087,1,0,0,0,1089,1090,1,0,0,0,1090,292,1,0,0,0,1091,1093,3,295,147,0, - 1092,1091,1,0,0,0,1093,1094,1,0,0,0,1094,1092,1,0,0,0,1094,1095,1,0,0, - 0,1095,294,1,0,0,0,1096,1109,3,323,161,0,1097,1109,3,327,163,0,1098,1109, - 3,331,165,0,1099,1109,3,333,166,0,1100,1109,3,299,149,0,1101,1109,3,319, - 159,0,1102,1109,3,317,158,0,1103,1109,3,315,157,0,1104,1109,3,303,151, - 0,1105,1109,3,335,167,0,1106,1109,7,24,0,0,1107,1109,3,297,148,0,1108, - 1096,1,0,0,0,1108,1097,1,0,0,0,1108,1098,1,0,0,0,1108,1099,1,0,0,0,1108, - 1100,1,0,0,0,1108,1101,1,0,0,0,1108,1102,1,0,0,0,1108,1103,1,0,0,0,1108, - 1104,1,0,0,0,1108,1105,1,0,0,0,1108,1106,1,0,0,0,1108,1107,1,0,0,0,1109, - 296,1,0,0,0,1110,1111,5,47,0,0,1111,1112,5,42,0,0,1112,1118,1,0,0,0,1113, - 1117,3,307,153,0,1114,1115,5,42,0,0,1115,1117,3,313,156,0,1116,1113,1, - 0,0,0,1116,1114,1,0,0,0,1117,1120,1,0,0,0,1118,1116,1,0,0,0,1118,1119, - 1,0,0,0,1119,1121,1,0,0,0,1120,1118,1,0,0,0,1121,1122,5,42,0,0,1122,1123, - 5,47,0,0,1123,298,1,0,0,0,1124,1125,7,25,0,0,1125,300,1,0,0,0,1126,1127, - 8,26,0,0,1127,302,1,0,0,0,1128,1129,7,27,0,0,1129,304,1,0,0,0,1130,1131, - 7,28,0,0,1131,306,1,0,0,0,1132,1133,8,29,0,0,1133,308,1,0,0,0,1134,1135, - 8,30,0,0,1135,310,1,0,0,0,1136,1137,8,31,0,0,1137,312,1,0,0,0,1138,1139, - 8,32,0,0,1139,314,1,0,0,0,1140,1141,7,33,0,0,1141,316,1,0,0,0,1142,1143, - 7,34,0,0,1143,318,1,0,0,0,1144,1145,7,35,0,0,1145,320,1,0,0,0,1146,1147, - 7,36,0,0,1147,322,1,0,0,0,1148,1149,7,37,0,0,1149,324,1,0,0,0,1150,1151, - 7,38,0,0,1151,326,1,0,0,0,1152,1153,7,39,0,0,1153,328,1,0,0,0,1154,1155, - 8,40,0,0,1155,330,1,0,0,0,1156,1157,7,41,0,0,1157,332,1,0,0,0,1158,1159, - 7,42,0,0,1159,334,1,0,0,0,1160,1161,7,43,0,0,1161,336,1,0,0,0,1162,1163, - 7,44,0,0,1163,338,1,0,0,0,1164,1165,9,0,0,0,1165,340,1,0,0,0,24,0,986, - 988,995,997,1001,1021,1028,1031,1034,1038,1042,1046,1055,1062,1068,1073, - 1077,1083,1089,1094,1108,1116,1118,0 + 12799,13312,19903,19968,42124,42192,42237,42240,42508,42512,42539,42560, + 42607,42612,42621,42623,42737,42775,42783,42786,42888,42891,42954,42960, + 42961,42963,42963,42965,42969,42994,43047,43052,43052,43072,43123,43136, + 43205,43216,43225,43232,43255,43259,43259,43261,43309,43312,43347,43360, + 43388,43392,43456,43471,43481,43488,43518,43520,43574,43584,43597,43600, + 43609,43616,43638,43642,43714,43739,43741,43744,43759,43762,43766,43777, + 43782,43785,43790,43793,43798,43808,43814,43816,43822,43824,43866,43868, + 43881,43888,44010,44012,44013,44016,44025,44032,55203,55216,55238,55243, + 55291,63744,64109,64112,64217,64256,64262,64275,64279,64285,64296,64298, + 64310,64312,64316,64318,64318,64320,64321,64323,64324,64326,64433,64467, + 64829,64848,64911,64914,64967,65008,65019,65024,65039,65056,65071,65075, + 65076,65101,65103,65136,65140,65142,65276,65296,65305,65313,65338,65343, + 65343,65345,65370,65382,65470,65474,65479,65482,65487,65490,65495,65498, + 65500,65536,65547,65549,65574,65576,65594,65596,65597,65599,65613,65616, + 65629,65664,65786,65856,65908,66045,66045,66176,66204,66208,66256,66272, + 66272,66304,66335,66349,66378,66384,66426,66432,66461,66464,66499,66504, + 66511,66513,66517,66560,66717,66720,66729,66736,66771,66776,66811,66816, + 66855,66864,66915,66928,66938,66940,66954,66956,66962,66964,66965,66967, + 66977,66979,66993,66995,67001,67003,67004,67072,67382,67392,67413,67424, + 67431,67456,67461,67463,67504,67506,67514,67584,67589,67592,67592,67594, + 67637,67639,67640,67644,67644,67647,67669,67680,67702,67712,67742,67808, + 67826,67828,67829,67840,67861,67872,67897,67968,68023,68030,68031,68096, + 68099,68101,68102,68108,68115,68117,68119,68121,68149,68152,68154,68159, + 68159,68192,68220,68224,68252,68288,68295,68297,68326,68352,68405,68416, + 68437,68448,68466,68480,68497,68608,68680,68736,68786,68800,68850,68864, + 68903,68912,68921,69248,69289,69291,69292,69296,69297,69373,69404,69415, + 69415,69424,69456,69488,69509,69552,69572,69600,69622,69632,69702,69734, + 69749,69759,69818,69826,69826,69840,69864,69872,69881,69888,69940,69942, + 69951,69956,69959,69968,70003,70006,70006,70016,70084,70089,70092,70094, + 70106,70108,70108,70144,70161,70163,70199,70206,70209,70272,70278,70280, + 70280,70282,70285,70287,70301,70303,70312,70320,70378,70384,70393,70400, + 70403,70405,70412,70415,70416,70419,70440,70442,70448,70450,70451,70453, + 70457,70459,70468,70471,70472,70475,70477,70480,70480,70487,70487,70493, + 70499,70502,70508,70512,70516,70656,70730,70736,70745,70750,70753,70784, + 70853,70855,70855,70864,70873,71040,71093,71096,71104,71128,71133,71168, + 71232,71236,71236,71248,71257,71296,71352,71360,71369,71424,71450,71453, + 71467,71472,71481,71488,71494,71680,71738,71840,71913,71935,71942,71945, + 71945,71948,71955,71957,71958,71960,71989,71991,71992,71995,72003,72016, + 72025,72096,72103,72106,72151,72154,72161,72163,72164,72192,72254,72263, + 72263,72272,72345,72349,72349,72368,72440,72704,72712,72714,72758,72760, + 72768,72784,72793,72818,72847,72850,72871,72873,72886,72960,72966,72968, + 72969,72971,73014,73018,73018,73020,73021,73023,73031,73040,73049,73056, + 73061,73063,73064,73066,73102,73104,73105,73107,73112,73120,73129,73440, + 73462,73472,73488,73490,73530,73534,73538,73552,73561,73648,73648,73728, + 74649,74752,74862,74880,75075,77712,77808,77824,78895,78912,78933,82944, + 83526,92160,92728,92736,92766,92768,92777,92784,92862,92864,92873,92880, + 92909,92912,92916,92928,92982,92992,92995,93008,93017,93027,93047,93053, + 93071,93760,93823,93952,94026,94031,94087,94095,94111,94176,94177,94179, + 94180,94192,94193,94208,100343,100352,101589,101632,101640,110576,110579, + 110581,110587,110589,110590,110592,110882,110898,110898,110928,110930, + 110933,110933,110948,110951,110960,111355,113664,113770,113776,113788, + 113792,113800,113808,113817,113821,113822,118528,118573,118576,118598, + 119141,119145,119149,119154,119163,119170,119173,119179,119210,119213, + 119362,119364,119808,119892,119894,119964,119966,119967,119970,119970, + 119973,119974,119977,119980,119982,119993,119995,119995,119997,120003, + 120005,120069,120071,120074,120077,120084,120086,120092,120094,120121, + 120123,120126,120128,120132,120134,120134,120138,120144,120146,120485, + 120488,120512,120514,120538,120540,120570,120572,120596,120598,120628, + 120630,120654,120656,120686,120688,120712,120714,120744,120746,120770, + 120772,120779,120782,120831,121344,121398,121403,121452,121461,121461, + 121476,121476,121499,121503,121505,121519,122624,122654,122661,122666, + 122880,122886,122888,122904,122907,122913,122915,122916,122918,122922, + 122928,122989,123023,123023,123136,123180,123184,123197,123200,123209, + 123214,123214,123536,123566,123584,123641,124112,124153,124896,124902, + 124904,124907,124909,124910,124912,124926,124928,125124,125136,125142, + 125184,125259,125264,125273,126464,126467,126469,126495,126497,126498, + 126500,126500,126503,126503,126505,126514,126516,126519,126521,126521, + 126523,126523,126530,126530,126535,126535,126537,126537,126539,126539, + 126541,126543,126545,126546,126548,126548,126551,126551,126553,126553, + 126555,126555,126557,126557,126559,126559,126561,126562,126564,126564, + 126567,126570,126572,126578,126580,126583,126585,126588,126590,126590, + 126592,126601,126603,126619,126625,126627,126629,126633,126635,126651, + 130032,130041,131072,173791,173824,177977,177984,178205,178208,183969, + 183984,191456,194560,195101,196608,201546,201552,205743,917760,917999, + 1,0,42,42,2,0,39,39,92,92,2,0,10,10,13,13,1,0,47,47,1,0,29,29,1,0,28, + 28,1,0,13,13,21,0,36,36,162,165,1423,1423,1547,1547,2046,2047,2546,2547, + 2555,2555,2801,2801,3065,3065,3647,3647,6107,6107,8352,8384,43064,43064, + 65020,65020,65129,65129,65284,65284,65504,65505,65509,65510,73693,73696, + 123647,123647,126128,126128,1,0,32,32,6,0,95,95,8255,8256,8276,8276,65075, + 65076,65101,65103,65343,65343,1,0,9,9,2,0,34,34,92,92,1,0,10,10,1,0,11, + 11,1,0,31,31,659,0,65,90,97,122,170,170,181,181,186,186,192,214,216,246, + 248,705,710,721,736,740,748,748,750,750,880,884,886,887,890,893,895,895, + 902,902,904,906,908,908,910,929,931,1013,1015,1153,1162,1327,1329,1366, + 1369,1369,1376,1416,1488,1514,1519,1522,1568,1610,1646,1647,1649,1747, + 1749,1749,1765,1766,1774,1775,1786,1788,1791,1791,1808,1808,1810,1839, + 1869,1957,1969,1969,1994,2026,2036,2037,2042,2042,2048,2069,2074,2074, + 2084,2084,2088,2088,2112,2136,2144,2154,2160,2183,2185,2190,2208,2249, + 2308,2361,2365,2365,2384,2384,2392,2401,2417,2432,2437,2444,2447,2448, + 2451,2472,2474,2480,2482,2482,2486,2489,2493,2493,2510,2510,2524,2525, + 2527,2529,2544,2545,2556,2556,2565,2570,2575,2576,2579,2600,2602,2608, + 2610,2611,2613,2614,2616,2617,2649,2652,2654,2654,2674,2676,2693,2701, + 2703,2705,2707,2728,2730,2736,2738,2739,2741,2745,2749,2749,2768,2768, + 2784,2785,2809,2809,2821,2828,2831,2832,2835,2856,2858,2864,2866,2867, + 2869,2873,2877,2877,2908,2909,2911,2913,2929,2929,2947,2947,2949,2954, + 2958,2960,2962,2965,2969,2970,2972,2972,2974,2975,2979,2980,2984,2986, + 2990,3001,3024,3024,3077,3084,3086,3088,3090,3112,3114,3129,3133,3133, + 3160,3162,3165,3165,3168,3169,3200,3200,3205,3212,3214,3216,3218,3240, + 3242,3251,3253,3257,3261,3261,3293,3294,3296,3297,3313,3314,3332,3340, + 3342,3344,3346,3386,3389,3389,3406,3406,3412,3414,3423,3425,3450,3455, + 3461,3478,3482,3505,3507,3515,3517,3517,3520,3526,3585,3632,3634,3635, + 3648,3654,3713,3714,3716,3716,3718,3722,3724,3747,3749,3749,3751,3760, + 3762,3763,3773,3773,3776,3780,3782,3782,3804,3807,3840,3840,3904,3911, + 3913,3948,3976,3980,4096,4138,4159,4159,4176,4181,4186,4189,4193,4193, + 4197,4198,4206,4208,4213,4225,4238,4238,4256,4293,4295,4295,4301,4301, + 4304,4346,4348,4680,4682,4685,4688,4694,4696,4696,4698,4701,4704,4744, + 4746,4749,4752,4784,4786,4789,4792,4798,4800,4800,4802,4805,4808,4822, + 4824,4880,4882,4885,4888,4954,4992,5007,5024,5109,5112,5117,5121,5740, + 5743,5759,5761,5786,5792,5866,5870,5880,5888,5905,5919,5937,5952,5969, + 5984,5996,5998,6000,6016,6067,6103,6103,6108,6108,6176,6264,6272,6312, + 6314,6314,6320,6389,6400,6430,6480,6509,6512,6516,6528,6571,6576,6601, + 6656,6678,6688,6740,6823,6823,6917,6963,6981,6988,7043,7072,7086,7087, + 7098,7141,7168,7203,7245,7247,7258,7293,7296,7304,7312,7354,7357,7359, + 7401,7404,7406,7411,7413,7414,7418,7418,7424,7615,7680,7957,7960,7965, + 7968,8005,8008,8013,8016,8023,8025,8025,8027,8027,8029,8029,8031,8061, + 8064,8116,8118,8124,8126,8126,8130,8132,8134,8140,8144,8147,8150,8155, + 8160,8172,8178,8180,8182,8188,8305,8305,8319,8319,8336,8348,8450,8450, + 8455,8455,8458,8467,8469,8469,8472,8477,8484,8484,8486,8486,8488,8488, + 8490,8505,8508,8511,8517,8521,8526,8526,8544,8584,11264,11492,11499,11502, + 11506,11507,11520,11557,11559,11559,11565,11565,11568,11623,11631,11631, + 11648,11670,11680,11686,11688,11694,11696,11702,11704,11710,11712,11718, + 11720,11726,11728,11734,11736,11742,12293,12295,12321,12329,12337,12341, + 12344,12348,12353,12438,12443,12447,12449,12538,12540,12543,12549,12591, + 12593,12686,12704,12735,12784,12799,13312,19903,19968,42124,42192,42237, + 42240,42508,42512,42527,42538,42539,42560,42606,42623,42653,42656,42735, + 42775,42783,42786,42888,42891,42954,42960,42961,42963,42963,42965,42969, + 42994,43009,43011,43013,43015,43018,43020,43042,43072,43123,43138,43187, + 43250,43255,43259,43259,43261,43262,43274,43301,43312,43334,43360,43388, + 43396,43442,43471,43471,43488,43492,43494,43503,43514,43518,43520,43560, + 43584,43586,43588,43595,43616,43638,43642,43642,43646,43695,43697,43697, + 43701,43702,43705,43709,43712,43712,43714,43714,43739,43741,43744,43754, + 43762,43764,43777,43782,43785,43790,43793,43798,43808,43814,43816,43822, + 43824,43866,43868,43881,43888,44002,44032,55203,55216,55238,55243,55291, + 63744,64109,64112,64217,64256,64262,64275,64279,64285,64285,64287,64296, + 64298,64310,64312,64316,64318,64318,64320,64321,64323,64324,64326,64433, + 64467,64829,64848,64911,64914,64967,65008,65019,65136,65140,65142,65276, + 65313,65338,65345,65370,65382,65470,65474,65479,65482,65487,65490,65495, + 65498,65500,65536,65547,65549,65574,65576,65594,65596,65597,65599,65613, + 65616,65629,65664,65786,65856,65908,66176,66204,66208,66256,66304,66335, + 66349,66378,66384,66421,66432,66461,66464,66499,66504,66511,66513,66517, + 66560,66717,66736,66771,66776,66811,66816,66855,66864,66915,66928,66938, + 66940,66954,66956,66962,66964,66965,66967,66977,66979,66993,66995,67001, + 67003,67004,67072,67382,67392,67413,67424,67431,67456,67461,67463,67504, + 67506,67514,67584,67589,67592,67592,67594,67637,67639,67640,67644,67644, + 67647,67669,67680,67702,67712,67742,67808,67826,67828,67829,67840,67861, + 67872,67897,67968,68023,68030,68031,68096,68096,68112,68115,68117,68119, + 68121,68149,68192,68220,68224,68252,68288,68295,68297,68324,68352,68405, + 68416,68437,68448,68466,68480,68497,68608,68680,68736,68786,68800,68850, + 68864,68899,69248,69289,69296,69297,69376,69404,69415,69415,69424,69445, + 69488,69505,69552,69572,69600,69622,69635,69687,69745,69746,69749,69749, + 69763,69807,69840,69864,69891,69926,69956,69956,69959,69959,69968,70002, + 70006,70006,70019,70066,70081,70084,70106,70106,70108,70108,70144,70161, + 70163,70187,70207,70208,70272,70278,70280,70280,70282,70285,70287,70301, + 70303,70312,70320,70366,70405,70412,70415,70416,70419,70440,70442,70448, + 70450,70451,70453,70457,70461,70461,70480,70480,70493,70497,70656,70708, + 70727,70730,70751,70753,70784,70831,70852,70853,70855,70855,71040,71086, + 71128,71131,71168,71215,71236,71236,71296,71338,71352,71352,71424,71450, + 71488,71494,71680,71723,71840,71903,71935,71942,71945,71945,71948,71955, + 71957,71958,71960,71983,71999,71999,72001,72001,72096,72103,72106,72144, + 72161,72161,72163,72163,72192,72192,72203,72242,72250,72250,72272,72272, + 72284,72329,72349,72349,72368,72440,72704,72712,72714,72750,72768,72768, + 72818,72847,72960,72966,72968,72969,72971,73008,73030,73030,73056,73061, + 73063,73064,73066,73097,73112,73112,73440,73458,73474,73474,73476,73488, + 73490,73523,73648,73648,73728,74649,74752,74862,74880,75075,77712,77808, + 77824,78895,78913,78918,82944,83526,92160,92728,92736,92766,92784,92862, + 92880,92909,92928,92975,92992,92995,93027,93047,93053,93071,93760,93823, + 93952,94026,94032,94032,94099,94111,94176,94177,94179,94179,94208,100343, + 100352,101589,101632,101640,110576,110579,110581,110587,110589,110590, + 110592,110882,110898,110898,110928,110930,110933,110933,110948,110951, + 110960,111355,113664,113770,113776,113788,113792,113800,113808,113817, + 119808,119892,119894,119964,119966,119967,119970,119970,119973,119974, + 119977,119980,119982,119993,119995,119995,119997,120003,120005,120069, + 120071,120074,120077,120084,120086,120092,120094,120121,120123,120126, + 120128,120132,120134,120134,120138,120144,120146,120485,120488,120512, + 120514,120538,120540,120570,120572,120596,120598,120628,120630,120654, + 120656,120686,120688,120712,120714,120744,120746,120770,120772,120779, + 122624,122654,122661,122666,122928,122989,123136,123180,123191,123197, + 123214,123214,123536,123565,123584,123627,124112,124139,124896,124902, + 124904,124907,124909,124910,124912,124926,124928,125124,125184,125251, + 125259,125259,126464,126467,126469,126495,126497,126498,126500,126500, + 126503,126503,126505,126514,126516,126519,126521,126521,126523,126523, + 126530,126530,126535,126535,126537,126537,126539,126539,126541,126543, + 126545,126546,126548,126548,126551,126551,126553,126553,126555,126555, + 126557,126557,126559,126559,126561,126562,126564,126564,126567,126570, + 126572,126578,126580,126583,126585,126588,126590,126590,126592,126601, + 126603,126619,126625,126627,126629,126633,126635,126651,131072,173791, + 173824,177977,177984,178205,178208,183969,183984,191456,194560,195101, + 196608,201546,201552,205743,1217,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0, + 0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1, + 0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0, + 0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0, + 39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1, + 0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0, + 0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0, + 71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1, + 0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0, + 0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0,0,0,99,1,0,0,0,0,101,1,0,0,0,0, + 103,1,0,0,0,0,105,1,0,0,0,0,107,1,0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0, + 113,1,0,0,0,0,115,1,0,0,0,0,117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0, + 123,1,0,0,0,0,125,1,0,0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,131,1,0,0,0,0, + 133,1,0,0,0,0,135,1,0,0,0,0,137,1,0,0,0,0,139,1,0,0,0,0,141,1,0,0,0,0, + 143,1,0,0,0,0,145,1,0,0,0,0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0, + 153,1,0,0,0,0,155,1,0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0, + 163,1,0,0,0,0,165,1,0,0,0,0,167,1,0,0,0,0,169,1,0,0,0,0,171,1,0,0,0,0, + 173,1,0,0,0,0,175,1,0,0,0,0,177,1,0,0,0,0,179,1,0,0,0,0,181,1,0,0,0,0, + 183,1,0,0,0,0,185,1,0,0,0,0,187,1,0,0,0,0,189,1,0,0,0,0,191,1,0,0,0,0, + 193,1,0,0,0,0,195,1,0,0,0,0,197,1,0,0,0,0,199,1,0,0,0,0,201,1,0,0,0,0, + 203,1,0,0,0,0,205,1,0,0,0,0,207,1,0,0,0,0,209,1,0,0,0,0,211,1,0,0,0,0, + 213,1,0,0,0,0,215,1,0,0,0,0,217,1,0,0,0,0,219,1,0,0,0,0,221,1,0,0,0,0, + 223,1,0,0,0,0,225,1,0,0,0,0,227,1,0,0,0,0,229,1,0,0,0,0,231,1,0,0,0,0, + 233,1,0,0,0,0,235,1,0,0,0,0,237,1,0,0,0,0,239,1,0,0,0,0,241,1,0,0,0,0, + 243,1,0,0,0,0,245,1,0,0,0,0,247,1,0,0,0,0,249,1,0,0,0,0,251,1,0,0,0,0, + 253,1,0,0,0,0,255,1,0,0,0,0,257,1,0,0,0,0,259,1,0,0,0,0,261,1,0,0,0,0, + 263,1,0,0,0,0,265,1,0,0,0,0,267,1,0,0,0,0,269,1,0,0,0,0,271,1,0,0,0,0, + 273,1,0,0,0,0,275,1,0,0,0,0,277,1,0,0,0,0,279,1,0,0,0,0,281,1,0,0,0,0, + 283,1,0,0,0,0,285,1,0,0,0,0,287,1,0,0,0,0,289,1,0,0,0,0,291,1,0,0,0,0, + 293,1,0,0,0,0,295,1,0,0,0,0,297,1,0,0,0,0,299,1,0,0,0,0,301,1,0,0,0,0, + 343,1,0,0,0,1,345,1,0,0,0,3,347,1,0,0,0,5,349,1,0,0,0,7,351,1,0,0,0,9, + 353,1,0,0,0,11,355,1,0,0,0,13,357,1,0,0,0,15,359,1,0,0,0,17,361,1,0,0, + 0,19,363,1,0,0,0,21,365,1,0,0,0,23,368,1,0,0,0,25,371,1,0,0,0,27,373, + 1,0,0,0,29,376,1,0,0,0,31,378,1,0,0,0,33,381,1,0,0,0,35,383,1,0,0,0,37, + 386,1,0,0,0,39,389,1,0,0,0,41,391,1,0,0,0,43,393,1,0,0,0,45,395,1,0,0, + 0,47,397,1,0,0,0,49,400,1,0,0,0,51,402,1,0,0,0,53,404,1,0,0,0,55,406, + 1,0,0,0,57,408,1,0,0,0,59,410,1,0,0,0,61,412,1,0,0,0,63,414,1,0,0,0,65, + 416,1,0,0,0,67,418,1,0,0,0,69,420,1,0,0,0,71,422,1,0,0,0,73,424,1,0,0, + 0,75,426,1,0,0,0,77,428,1,0,0,0,79,430,1,0,0,0,81,432,1,0,0,0,83,434, + 1,0,0,0,85,436,1,0,0,0,87,438,1,0,0,0,89,440,1,0,0,0,91,442,1,0,0,0,93, + 449,1,0,0,0,95,456,1,0,0,0,97,461,1,0,0,0,99,469,1,0,0,0,101,475,1,0, + 0,0,103,480,1,0,0,0,105,485,1,0,0,0,107,490,1,0,0,0,109,497,1,0,0,0,111, + 504,1,0,0,0,113,511,1,0,0,0,115,520,1,0,0,0,117,525,1,0,0,0,119,531,1, + 0,0,0,121,537,1,0,0,0,123,546,1,0,0,0,125,551,1,0,0,0,127,557,1,0,0,0, + 129,565,1,0,0,0,131,572,1,0,0,0,133,576,1,0,0,0,135,584,1,0,0,0,137,588, + 1,0,0,0,139,592,1,0,0,0,141,595,1,0,0,0,143,603,1,0,0,0,145,611,1,0,0, + 0,147,617,1,0,0,0,149,629,1,0,0,0,151,634,1,0,0,0,153,639,1,0,0,0,155, + 645,1,0,0,0,157,652,1,0,0,0,159,675,1,0,0,0,161,684,1,0,0,0,163,709,1, + 0,0,0,165,717,1,0,0,0,167,727,1,0,0,0,169,733,1,0,0,0,171,737,1,0,0,0, + 173,742,1,0,0,0,175,750,1,0,0,0,177,759,1,0,0,0,179,765,1,0,0,0,181,772, + 1,0,0,0,183,779,1,0,0,0,185,785,1,0,0,0,187,788,1,0,0,0,189,792,1,0,0, + 0,191,799,1,0,0,0,193,806,1,0,0,0,195,811,1,0,0,0,197,818,1,0,0,0,199, + 827,1,0,0,0,201,829,1,0,0,0,203,832,1,0,0,0,205,838,1,0,0,0,207,841,1, + 0,0,0,209,846,1,0,0,0,211,852,1,0,0,0,213,862,1,0,0,0,215,866,1,0,0,0, + 217,877,1,0,0,0,219,882,1,0,0,0,221,888,1,0,0,0,223,897,1,0,0,0,225,900, + 1,0,0,0,227,904,1,0,0,0,229,908,1,0,0,0,231,912,1,0,0,0,233,915,1,0,0, + 0,235,917,1,0,0,0,237,919,1,0,0,0,239,921,1,0,0,0,241,924,1,0,0,0,243, + 931,1,0,0,0,245,936,1,0,0,0,247,945,1,0,0,0,249,948,1,0,0,0,251,953,1, + 0,0,0,253,958,1,0,0,0,255,964,1,0,0,0,257,970,1,0,0,0,259,977,1,0,0,0, + 261,982,1,0,0,0,263,987,1,0,0,0,265,991,1,0,0,0,267,996,1,0,0,0,269,1019, + 1,0,0,0,271,1021,1,0,0,0,273,1049,1,0,0,0,275,1052,1,0,0,0,277,1056,1, + 0,0,0,279,1060,1,0,0,0,281,1064,1,0,0,0,283,1066,1,0,0,0,285,1068,1,0, + 0,0,287,1073,1,0,0,0,289,1082,1,0,0,0,291,1091,1,0,0,0,293,1095,1,0,0, + 0,295,1105,1,0,0,0,297,1110,1,0,0,0,299,1126,1,0,0,0,301,1157,1,0,0,0, + 303,1159,1,0,0,0,305,1161,1,0,0,0,307,1163,1,0,0,0,309,1165,1,0,0,0,311, + 1167,1,0,0,0,313,1169,1,0,0,0,315,1171,1,0,0,0,317,1173,1,0,0,0,319,1175, + 1,0,0,0,321,1177,1,0,0,0,323,1179,1,0,0,0,325,1181,1,0,0,0,327,1183,1, + 0,0,0,329,1185,1,0,0,0,331,1187,1,0,0,0,333,1189,1,0,0,0,335,1191,1,0, + 0,0,337,1193,1,0,0,0,339,1195,1,0,0,0,341,1197,1,0,0,0,343,1199,1,0,0, + 0,345,346,5,59,0,0,346,2,1,0,0,0,347,348,5,40,0,0,348,4,1,0,0,0,349,350, + 5,44,0,0,350,6,1,0,0,0,351,352,5,41,0,0,352,8,1,0,0,0,353,354,5,61,0, + 0,354,10,1,0,0,0,355,356,5,91,0,0,356,12,1,0,0,0,357,358,5,93,0,0,358, + 14,1,0,0,0,359,360,5,123,0,0,360,16,1,0,0,0,361,362,5,125,0,0,362,18, + 1,0,0,0,363,364,5,124,0,0,364,20,1,0,0,0,365,366,5,46,0,0,366,367,5,46, + 0,0,367,22,1,0,0,0,368,369,5,60,0,0,369,370,5,62,0,0,370,24,1,0,0,0,371, + 372,5,60,0,0,372,26,1,0,0,0,373,374,5,60,0,0,374,375,5,61,0,0,375,28, + 1,0,0,0,376,377,5,62,0,0,377,30,1,0,0,0,378,379,5,62,0,0,379,380,5,61, + 0,0,380,32,1,0,0,0,381,382,5,38,0,0,382,34,1,0,0,0,383,384,5,62,0,0,384, + 385,5,62,0,0,385,36,1,0,0,0,386,387,5,60,0,0,387,388,5,60,0,0,388,38, + 1,0,0,0,389,390,5,43,0,0,390,40,1,0,0,0,391,392,5,47,0,0,392,42,1,0,0, + 0,393,394,5,37,0,0,394,44,1,0,0,0,395,396,5,94,0,0,396,46,1,0,0,0,397, + 398,5,61,0,0,398,399,5,126,0,0,399,48,1,0,0,0,400,401,5,46,0,0,401,50, + 1,0,0,0,402,403,5,36,0,0,403,52,1,0,0,0,404,405,5,10216,0,0,405,54,1, + 0,0,0,406,407,5,12296,0,0,407,56,1,0,0,0,408,409,5,65124,0,0,409,58,1, + 0,0,0,410,411,5,65308,0,0,411,60,1,0,0,0,412,413,5,10217,0,0,413,62,1, + 0,0,0,414,415,5,12297,0,0,415,64,1,0,0,0,416,417,5,65125,0,0,417,66,1, + 0,0,0,418,419,5,65310,0,0,419,68,1,0,0,0,420,421,5,173,0,0,421,70,1,0, + 0,0,422,423,5,8208,0,0,423,72,1,0,0,0,424,425,5,8209,0,0,425,74,1,0,0, + 0,426,427,5,8210,0,0,427,76,1,0,0,0,428,429,5,8211,0,0,429,78,1,0,0,0, + 430,431,5,8212,0,0,431,80,1,0,0,0,432,433,5,8213,0,0,433,82,1,0,0,0,434, + 435,5,8722,0,0,435,84,1,0,0,0,436,437,5,65112,0,0,437,86,1,0,0,0,438, + 439,5,65123,0,0,439,88,1,0,0,0,440,441,5,65293,0,0,441,90,1,0,0,0,442, + 443,7,0,0,0,443,444,7,1,0,0,444,445,7,1,0,0,445,446,7,0,0,0,446,447,7, + 2,0,0,447,448,7,3,0,0,448,92,1,0,0,0,449,450,7,4,0,0,450,451,7,5,0,0, + 451,452,7,1,0,0,452,453,7,6,0,0,453,454,7,7,0,0,454,455,7,8,0,0,455,94, + 1,0,0,0,456,457,7,2,0,0,457,458,7,0,0,0,458,459,7,9,0,0,459,460,7,9,0, + 0,460,96,1,0,0,0,461,462,7,2,0,0,462,463,7,10,0,0,463,464,7,11,0,0,464, + 465,7,11,0,0,465,466,7,8,0,0,466,467,7,12,0,0,467,468,7,1,0,0,468,98, + 1,0,0,0,469,470,7,11,0,0,470,471,7,0,0,0,471,472,7,2,0,0,472,473,7,13, + 0,0,473,474,7,10,0,0,474,100,1,0,0,0,475,476,7,14,0,0,476,477,7,9,0,0, + 477,478,7,10,0,0,478,479,7,5,0,0,479,102,1,0,0,0,480,481,7,2,0,0,481, + 482,7,10,0,0,482,483,7,7,0,0,483,484,7,6,0,0,484,104,1,0,0,0,485,486, + 7,15,0,0,486,487,7,13,0,0,487,488,7,10,0,0,488,489,7,11,0,0,489,106,1, + 0,0,0,490,491,7,2,0,0,491,492,7,10,0,0,492,493,7,9,0,0,493,494,7,16,0, + 0,494,495,7,11,0,0,495,496,7,12,0,0,496,108,1,0,0,0,497,498,7,8,0,0,498, + 499,7,17,0,0,499,500,7,7,0,0,500,501,7,10,0,0,501,502,7,13,0,0,502,503, + 7,1,0,0,503,110,1,0,0,0,504,505,7,18,0,0,505,506,7,11,0,0,506,507,7,7, + 0,0,507,508,7,10,0,0,508,509,7,13,0,0,509,510,7,1,0,0,510,112,1,0,0,0, + 511,512,7,4,0,0,512,513,7,0,0,0,513,514,7,1,0,0,514,515,7,0,0,0,515,516, + 7,5,0,0,516,517,7,0,0,0,517,518,7,19,0,0,518,519,7,8,0,0,519,114,1,0, + 0,0,520,521,7,12,0,0,521,522,7,10,0,0,522,523,7,4,0,0,523,524,7,8,0,0, + 524,116,1,0,0,0,525,526,7,1,0,0,526,527,7,0,0,0,527,528,7,5,0,0,528,529, + 7,9,0,0,529,530,7,8,0,0,530,118,1,0,0,0,531,532,7,14,0,0,532,533,7,13, + 0,0,533,534,7,10,0,0,534,535,7,16,0,0,535,536,7,7,0,0,536,120,1,0,0,0, + 537,538,7,13,0,0,538,539,7,4,0,0,539,540,7,15,0,0,540,541,7,14,0,0,541, + 542,7,13,0,0,542,543,7,0,0,0,543,544,7,7,0,0,544,545,7,3,0,0,545,122, + 1,0,0,0,546,547,7,4,0,0,547,548,7,13,0,0,548,549,7,10,0,0,549,550,7,7, + 0,0,550,124,1,0,0,0,551,552,7,0,0,0,552,553,7,9,0,0,553,554,7,1,0,0,554, + 555,7,8,0,0,555,556,7,13,0,0,556,126,1,0,0,0,557,558,7,4,0,0,558,559, + 7,8,0,0,559,560,7,15,0,0,560,561,7,0,0,0,561,562,7,16,0,0,562,563,7,9, + 0,0,563,564,7,1,0,0,564,128,1,0,0,0,565,566,7,13,0,0,566,567,7,8,0,0, + 567,568,7,12,0,0,568,569,7,0,0,0,569,570,7,11,0,0,570,571,7,8,0,0,571, + 130,1,0,0,0,572,573,7,0,0,0,573,574,7,4,0,0,574,575,7,4,0,0,575,132,1, + 0,0,0,576,577,7,7,0,0,577,578,7,13,0,0,578,579,7,18,0,0,579,580,7,11, + 0,0,580,581,7,0,0,0,581,582,7,13,0,0,582,583,7,6,0,0,583,134,1,0,0,0, + 584,585,7,20,0,0,585,586,7,8,0,0,586,587,7,6,0,0,587,136,1,0,0,0,588, + 589,7,13,0,0,589,590,7,8,0,0,590,591,7,9,0,0,591,138,1,0,0,0,592,593, + 7,1,0,0,593,594,7,10,0,0,594,140,1,0,0,0,595,596,7,8,0,0,596,597,7,17, + 0,0,597,598,7,7,0,0,598,599,7,9,0,0,599,600,7,0,0,0,600,601,7,18,0,0, + 601,602,7,12,0,0,602,142,1,0,0,0,603,604,7,7,0,0,604,605,7,13,0,0,605, + 606,7,10,0,0,606,607,7,15,0,0,607,608,7,18,0,0,608,609,7,9,0,0,609,610, + 7,8,0,0,610,144,1,0,0,0,611,612,7,5,0,0,612,613,7,8,0,0,613,614,7,14, + 0,0,614,615,7,18,0,0,615,616,7,12,0,0,616,146,1,0,0,0,617,618,7,1,0,0, + 618,619,7,13,0,0,619,620,7,0,0,0,620,621,7,12,0,0,621,622,7,19,0,0,622, + 623,7,0,0,0,623,624,7,2,0,0,624,625,7,1,0,0,625,626,7,18,0,0,626,627, + 7,10,0,0,627,628,7,12,0,0,628,148,1,0,0,0,629,630,7,13,0,0,630,631,7, + 8,0,0,631,632,7,0,0,0,632,633,7,4,0,0,633,150,1,0,0,0,634,635,7,10,0, + 0,635,636,7,12,0,0,636,637,7,9,0,0,637,638,7,6,0,0,638,152,1,0,0,0,639, + 640,7,21,0,0,640,641,7,13,0,0,641,642,7,18,0,0,642,643,7,1,0,0,643,644, + 7,8,0,0,644,154,1,0,0,0,645,646,7,2,0,0,646,647,7,10,0,0,647,648,7,11, + 0,0,648,649,7,11,0,0,649,650,7,18,0,0,650,651,7,1,0,0,651,156,1,0,0,0, + 652,653,7,2,0,0,653,654,7,10,0,0,654,655,7,11,0,0,655,656,7,11,0,0,656, + 657,7,18,0,0,657,658,7,1,0,0,658,659,5,95,0,0,659,660,7,19,0,0,660,661, + 7,20,0,0,661,662,7,18,0,0,662,663,7,7,0,0,663,664,5,95,0,0,664,665,7, + 2,0,0,665,666,7,3,0,0,666,667,7,8,0,0,667,668,7,2,0,0,668,669,7,20,0, + 0,669,670,7,7,0,0,670,671,7,10,0,0,671,672,7,18,0,0,672,673,7,12,0,0, + 673,674,7,1,0,0,674,158,1,0,0,0,675,676,7,13,0,0,676,677,7,10,0,0,677, + 678,7,9,0,0,678,679,7,9,0,0,679,680,7,5,0,0,680,681,7,0,0,0,681,682,7, + 2,0,0,682,683,7,20,0,0,683,160,1,0,0,0,684,685,7,13,0,0,685,686,7,10, + 0,0,686,687,7,9,0,0,687,688,7,9,0,0,688,689,7,5,0,0,689,690,7,0,0,0,690, + 691,7,2,0,0,691,692,7,20,0,0,692,693,5,95,0,0,693,694,7,19,0,0,694,695, + 7,20,0,0,695,696,7,18,0,0,696,697,7,7,0,0,697,698,5,95,0,0,698,699,7, + 2,0,0,699,700,7,3,0,0,700,701,7,8,0,0,701,702,7,2,0,0,702,703,7,20,0, + 0,703,704,7,7,0,0,704,705,7,10,0,0,705,706,7,18,0,0,706,707,7,12,0,0, + 707,708,7,1,0,0,708,162,1,0,0,0,709,710,7,18,0,0,710,711,7,12,0,0,711, + 712,7,19,0,0,712,713,7,1,0,0,713,714,7,0,0,0,714,715,7,9,0,0,715,716, + 7,9,0,0,716,164,1,0,0,0,717,718,7,8,0,0,718,719,7,17,0,0,719,720,7,1, + 0,0,720,721,7,8,0,0,721,722,7,12,0,0,722,723,7,19,0,0,723,724,7,18,0, + 0,724,725,7,10,0,0,725,726,7,12,0,0,726,166,1,0,0,0,727,728,7,16,0,0, + 728,729,7,12,0,0,729,730,7,18,0,0,730,731,7,10,0,0,731,732,7,12,0,0,732, + 168,1,0,0,0,733,734,7,0,0,0,734,735,7,9,0,0,735,736,7,9,0,0,736,170,1, + 0,0,0,737,738,7,9,0,0,738,739,7,10,0,0,739,740,7,0,0,0,740,741,7,4,0, + 0,741,172,1,0,0,0,742,743,7,3,0,0,743,744,7,8,0,0,744,745,7,0,0,0,745, + 746,7,4,0,0,746,747,7,8,0,0,747,748,7,13,0,0,748,749,7,19,0,0,749,174, + 1,0,0,0,750,751,7,10,0,0,751,752,7,7,0,0,752,753,7,1,0,0,753,754,7,18, + 0,0,754,755,7,10,0,0,755,756,7,12,0,0,756,757,7,0,0,0,757,758,7,9,0,0, + 758,176,1,0,0,0,759,760,7,11,0,0,760,761,7,0,0,0,761,762,7,1,0,0,762, + 763,7,2,0,0,763,764,7,3,0,0,764,178,1,0,0,0,765,766,7,16,0,0,766,767, + 7,12,0,0,767,768,7,21,0,0,768,769,7,18,0,0,769,770,7,12,0,0,770,771,7, + 4,0,0,771,180,1,0,0,0,772,773,7,2,0,0,773,774,7,13,0,0,774,775,7,8,0, + 0,775,776,7,0,0,0,776,777,7,1,0,0,777,778,7,8,0,0,778,182,1,0,0,0,779, + 780,7,11,0,0,780,781,7,8,0,0,781,782,7,13,0,0,782,783,7,14,0,0,783,784, + 7,8,0,0,784,184,1,0,0,0,785,786,7,10,0,0,786,787,7,12,0,0,787,186,1,0, + 0,0,788,789,7,19,0,0,789,790,7,8,0,0,790,791,7,1,0,0,791,188,1,0,0,0, + 792,793,7,4,0,0,793,794,7,8,0,0,794,795,7,1,0,0,795,796,7,0,0,0,796,797, + 7,2,0,0,797,798,7,3,0,0,798,190,1,0,0,0,799,800,7,4,0,0,800,801,7,8,0, + 0,801,802,7,9,0,0,802,803,7,8,0,0,803,804,7,1,0,0,804,805,7,8,0,0,805, + 192,1,0,0,0,806,807,7,21,0,0,807,808,7,18,0,0,808,809,7,1,0,0,809,810, + 7,3,0,0,810,194,1,0,0,0,811,812,7,13,0,0,812,813,7,8,0,0,813,814,7,1, + 0,0,814,815,7,16,0,0,815,816,7,13,0,0,816,817,7,12,0,0,817,196,1,0,0, + 0,818,819,7,4,0,0,819,820,7,18,0,0,820,821,7,19,0,0,821,822,7,1,0,0,822, + 823,7,18,0,0,823,824,7,12,0,0,824,825,7,2,0,0,825,826,7,1,0,0,826,198, + 1,0,0,0,827,828,5,42,0,0,828,200,1,0,0,0,829,830,7,0,0,0,830,831,7,19, + 0,0,831,202,1,0,0,0,832,833,7,10,0,0,833,834,7,13,0,0,834,835,7,4,0,0, + 835,836,7,8,0,0,836,837,7,13,0,0,837,204,1,0,0,0,838,839,7,5,0,0,839, + 840,7,6,0,0,840,206,1,0,0,0,841,842,7,19,0,0,842,843,7,20,0,0,843,844, + 7,18,0,0,844,845,7,7,0,0,845,208,1,0,0,0,846,847,7,9,0,0,847,848,7,18, + 0,0,848,849,7,11,0,0,849,850,7,18,0,0,850,851,7,1,0,0,851,210,1,0,0,0, + 852,853,7,0,0,0,853,854,7,19,0,0,854,855,7,2,0,0,855,856,7,8,0,0,856, + 857,7,12,0,0,857,858,7,4,0,0,858,859,7,18,0,0,859,860,7,12,0,0,860,861, + 7,14,0,0,861,212,1,0,0,0,862,863,7,0,0,0,863,864,7,19,0,0,864,865,7,2, + 0,0,865,214,1,0,0,0,866,867,7,4,0,0,867,868,7,8,0,0,868,869,7,19,0,0, + 869,870,7,2,0,0,870,871,7,8,0,0,871,872,7,12,0,0,872,873,7,4,0,0,873, + 874,7,18,0,0,874,875,7,12,0,0,875,876,7,14,0,0,876,216,1,0,0,0,877,878, + 7,4,0,0,878,879,7,8,0,0,879,880,7,19,0,0,880,881,7,2,0,0,881,218,1,0, + 0,0,882,883,7,21,0,0,883,884,7,3,0,0,884,885,7,8,0,0,885,886,7,13,0,0, + 886,887,7,8,0,0,887,220,1,0,0,0,888,889,7,19,0,0,889,890,7,3,0,0,890, + 891,7,10,0,0,891,892,7,13,0,0,892,893,7,1,0,0,893,894,7,8,0,0,894,895, + 7,19,0,0,895,896,7,1,0,0,896,222,1,0,0,0,897,898,7,10,0,0,898,899,7,13, + 0,0,899,224,1,0,0,0,900,901,7,17,0,0,901,902,7,10,0,0,902,903,7,13,0, + 0,903,226,1,0,0,0,904,905,7,0,0,0,905,906,7,12,0,0,906,907,7,4,0,0,907, + 228,1,0,0,0,908,909,7,12,0,0,909,910,7,10,0,0,910,911,7,1,0,0,911,230, + 1,0,0,0,912,913,5,33,0,0,913,914,5,61,0,0,914,232,1,0,0,0,915,916,5,45, + 0,0,916,234,1,0,0,0,917,918,5,33,0,0,918,236,1,0,0,0,919,920,5,58,0,0, + 920,238,1,0,0,0,921,922,7,18,0,0,922,923,7,12,0,0,923,240,1,0,0,0,924, + 925,7,19,0,0,925,926,7,1,0,0,926,927,7,0,0,0,927,928,7,13,0,0,928,929, + 7,1,0,0,929,930,7,19,0,0,930,242,1,0,0,0,931,932,7,8,0,0,932,933,7,12, + 0,0,933,934,7,4,0,0,934,935,7,19,0,0,935,244,1,0,0,0,936,937,7,2,0,0, + 937,938,7,10,0,0,938,939,7,12,0,0,939,940,7,1,0,0,940,941,7,0,0,0,941, + 942,7,18,0,0,942,943,7,12,0,0,943,944,7,19,0,0,944,246,1,0,0,0,945,946, + 7,18,0,0,946,947,7,19,0,0,947,248,1,0,0,0,948,949,7,12,0,0,949,950,7, + 16,0,0,950,951,7,9,0,0,951,952,7,9,0,0,952,250,1,0,0,0,953,954,7,1,0, + 0,954,955,7,13,0,0,955,956,7,16,0,0,956,957,7,8,0,0,957,252,1,0,0,0,958, + 959,7,15,0,0,959,960,7,0,0,0,960,961,7,9,0,0,961,962,7,19,0,0,962,963, + 7,8,0,0,963,254,1,0,0,0,964,965,7,2,0,0,965,966,7,10,0,0,966,967,7,16, + 0,0,967,968,7,12,0,0,968,969,7,1,0,0,969,256,1,0,0,0,970,971,7,8,0,0, + 971,972,7,17,0,0,972,973,7,18,0,0,973,974,7,19,0,0,974,975,7,1,0,0,975, + 976,7,19,0,0,976,258,1,0,0,0,977,978,7,2,0,0,978,979,7,0,0,0,979,980, + 7,19,0,0,980,981,7,8,0,0,981,260,1,0,0,0,982,983,7,8,0,0,983,984,7,9, + 0,0,984,985,7,19,0,0,985,986,7,8,0,0,986,262,1,0,0,0,987,988,7,8,0,0, + 988,989,7,12,0,0,989,990,7,4,0,0,990,264,1,0,0,0,991,992,7,21,0,0,992, + 993,7,3,0,0,993,994,7,8,0,0,994,995,7,12,0,0,995,266,1,0,0,0,996,997, + 7,1,0,0,997,998,7,3,0,0,998,999,7,8,0,0,999,1000,7,12,0,0,1000,268,1, + 0,0,0,1001,1006,5,34,0,0,1002,1005,3,333,166,0,1003,1005,3,271,135,0, + 1004,1002,1,0,0,0,1004,1003,1,0,0,0,1005,1008,1,0,0,0,1006,1004,1,0,0, + 0,1006,1007,1,0,0,0,1007,1009,1,0,0,0,1008,1006,1,0,0,0,1009,1020,5,34, + 0,0,1010,1015,5,39,0,0,1011,1014,3,313,156,0,1012,1014,3,271,135,0,1013, + 1011,1,0,0,0,1013,1012,1,0,0,0,1014,1017,1,0,0,0,1015,1013,1,0,0,0,1015, + 1016,1,0,0,0,1016,1018,1,0,0,0,1017,1015,1,0,0,0,1018,1020,5,39,0,0,1019, + 1001,1,0,0,0,1019,1010,1,0,0,0,1020,270,1,0,0,0,1021,1039,5,92,0,0,1022, + 1040,7,22,0,0,1023,1024,7,16,0,0,1024,1025,3,277,138,0,1025,1026,3,277, + 138,0,1026,1027,3,277,138,0,1027,1028,3,277,138,0,1028,1040,1,0,0,0,1029, + 1030,7,16,0,0,1030,1031,3,277,138,0,1031,1032,3,277,138,0,1032,1033,3, + 277,138,0,1033,1034,3,277,138,0,1034,1035,3,277,138,0,1035,1036,3,277, + 138,0,1036,1037,3,277,138,0,1037,1038,3,277,138,0,1038,1040,1,0,0,0,1039, + 1022,1,0,0,0,1039,1023,1,0,0,0,1039,1029,1,0,0,0,1040,272,1,0,0,0,1041, + 1050,3,285,142,0,1042,1046,3,281,140,0,1043,1045,3,279,139,0,1044,1043, + 1,0,0,0,1045,1048,1,0,0,0,1046,1044,1,0,0,0,1046,1047,1,0,0,0,1047,1050, + 1,0,0,0,1048,1046,1,0,0,0,1049,1041,1,0,0,0,1049,1042,1,0,0,0,1050,274, + 1,0,0,0,1051,1053,7,23,0,0,1052,1051,1,0,0,0,1053,276,1,0,0,0,1054,1057, + 3,279,139,0,1055,1057,3,275,137,0,1056,1054,1,0,0,0,1056,1055,1,0,0,0, + 1057,278,1,0,0,0,1058,1061,3,285,142,0,1059,1061,3,281,140,0,1060,1058, + 1,0,0,0,1060,1059,1,0,0,0,1061,280,1,0,0,0,1062,1065,3,283,141,0,1063, + 1065,2,56,57,0,1064,1062,1,0,0,0,1064,1063,1,0,0,0,1065,282,1,0,0,0,1066, + 1067,2,49,55,0,1067,284,1,0,0,0,1068,1069,5,48,0,0,1069,286,1,0,0,0,1070, + 1072,3,279,139,0,1071,1070,1,0,0,0,1072,1075,1,0,0,0,1073,1071,1,0,0, + 0,1073,1074,1,0,0,0,1074,1076,1,0,0,0,1075,1073,1,0,0,0,1076,1078,5,46, + 0,0,1077,1079,3,279,139,0,1078,1077,1,0,0,0,1079,1080,1,0,0,0,1080,1078, + 1,0,0,0,1080,1081,1,0,0,0,1081,288,1,0,0,0,1082,1086,3,291,145,0,1083, + 1085,3,293,146,0,1084,1083,1,0,0,0,1085,1088,1,0,0,0,1086,1084,1,0,0, + 0,1086,1087,1,0,0,0,1087,290,1,0,0,0,1088,1086,1,0,0,0,1089,1092,3,341, + 170,0,1090,1092,3,329,164,0,1091,1089,1,0,0,0,1091,1090,1,0,0,0,1092, + 292,1,0,0,0,1093,1096,3,309,154,0,1094,1096,3,325,162,0,1095,1093,1,0, + 0,0,1095,1094,1,0,0,0,1096,294,1,0,0,0,1097,1101,5,96,0,0,1098,1100,3, + 305,152,0,1099,1098,1,0,0,0,1100,1103,1,0,0,0,1101,1099,1,0,0,0,1101, + 1102,1,0,0,0,1102,1104,1,0,0,0,1103,1101,1,0,0,0,1104,1106,5,96,0,0,1105, + 1097,1,0,0,0,1106,1107,1,0,0,0,1107,1105,1,0,0,0,1107,1108,1,0,0,0,1108, + 296,1,0,0,0,1109,1111,3,299,149,0,1110,1109,1,0,0,0,1111,1112,1,0,0,0, + 1112,1110,1,0,0,0,1112,1113,1,0,0,0,1113,298,1,0,0,0,1114,1127,3,327, + 163,0,1115,1127,3,331,165,0,1116,1127,3,335,167,0,1117,1127,3,337,168, + 0,1118,1127,3,303,151,0,1119,1127,3,323,161,0,1120,1127,3,321,160,0,1121, + 1127,3,319,159,0,1122,1127,3,307,153,0,1123,1127,3,339,169,0,1124,1127, + 7,24,0,0,1125,1127,3,301,150,0,1126,1114,1,0,0,0,1126,1115,1,0,0,0,1126, + 1116,1,0,0,0,1126,1117,1,0,0,0,1126,1118,1,0,0,0,1126,1119,1,0,0,0,1126, + 1120,1,0,0,0,1126,1121,1,0,0,0,1126,1122,1,0,0,0,1126,1123,1,0,0,0,1126, + 1124,1,0,0,0,1126,1125,1,0,0,0,1127,300,1,0,0,0,1128,1129,5,47,0,0,1129, + 1130,5,42,0,0,1130,1136,1,0,0,0,1131,1135,3,311,155,0,1132,1133,5,42, + 0,0,1133,1135,3,317,158,0,1134,1131,1,0,0,0,1134,1132,1,0,0,0,1135,1138, + 1,0,0,0,1136,1134,1,0,0,0,1136,1137,1,0,0,0,1137,1139,1,0,0,0,1138,1136, + 1,0,0,0,1139,1140,5,42,0,0,1140,1158,5,47,0,0,1141,1142,5,47,0,0,1142, + 1143,5,47,0,0,1143,1147,1,0,0,0,1144,1146,3,315,157,0,1145,1144,1,0,0, + 0,1146,1149,1,0,0,0,1147,1145,1,0,0,0,1147,1148,1,0,0,0,1148,1151,1,0, + 0,0,1149,1147,1,0,0,0,1150,1152,3,323,161,0,1151,1150,1,0,0,0,1151,1152, + 1,0,0,0,1152,1155,1,0,0,0,1153,1156,3,335,167,0,1154,1156,5,0,0,1,1155, + 1153,1,0,0,0,1155,1154,1,0,0,0,1156,1158,1,0,0,0,1157,1128,1,0,0,0,1157, + 1141,1,0,0,0,1158,302,1,0,0,0,1159,1160,7,25,0,0,1160,304,1,0,0,0,1161, + 1162,8,26,0,0,1162,306,1,0,0,0,1163,1164,7,27,0,0,1164,308,1,0,0,0,1165, + 1166,7,28,0,0,1166,310,1,0,0,0,1167,1168,8,29,0,0,1168,312,1,0,0,0,1169, + 1170,8,30,0,0,1170,314,1,0,0,0,1171,1172,8,31,0,0,1172,316,1,0,0,0,1173, + 1174,8,32,0,0,1174,318,1,0,0,0,1175,1176,7,33,0,0,1176,320,1,0,0,0,1177, + 1178,7,34,0,0,1178,322,1,0,0,0,1179,1180,7,35,0,0,1180,324,1,0,0,0,1181, + 1182,7,36,0,0,1182,326,1,0,0,0,1183,1184,7,37,0,0,1184,328,1,0,0,0,1185, + 1186,7,38,0,0,1186,330,1,0,0,0,1187,1188,7,39,0,0,1188,332,1,0,0,0,1189, + 1190,8,40,0,0,1190,334,1,0,0,0,1191,1192,7,41,0,0,1192,336,1,0,0,0,1193, + 1194,7,42,0,0,1194,338,1,0,0,0,1195,1196,7,43,0,0,1196,340,1,0,0,0,1197, + 1198,7,44,0,0,1198,342,1,0,0,0,1199,1200,9,0,0,0,1200,344,1,0,0,0,28, + 0,1004,1006,1013,1015,1019,1039,1046,1049,1052,1056,1060,1064,1073,1080, + 1086,1091,1095,1101,1107,1112,1126,1134,1136,1147,1151,1155,1157,0 }; staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0])); diff --git a/third_party/antlr4_cypher/cypher_parser.cpp b/third_party/antlr4_cypher/cypher_parser.cpp index da4f0be3d7f..17cccc8fbc5 100644 --- a/third_party/antlr4_cypher/cypher_parser.cpp +++ b/third_party/antlr4_cypher/cypher_parser.cpp @@ -52,10 +52,11 @@ void cypherParserInitialize() { auto staticData = std::make_unique( std::vector{ "ku_Statements", "oC_Cypher", "oC_Statement", "kU_CopyFrom", "kU_ColumnNames", - "kU_CopyFromByColumn", "kU_CopyTO", "kU_ExportDatabase", "kU_ImportDatabase", - "kU_StandaloneCall", "kU_CommentOn", "kU_CreateMacro", "kU_PositionalArgs", - "kU_DefaultArg", "kU_FilePaths", "kU_ParsingOptions", "kU_ParsingOption", - "kU_DDL", "kU_CreateNodeTable", "kU_CreateRelTable", "kU_CreateRelTableGroup", + "kU_ScanSource", "kU_CopyFromByColumn", "kU_CopyTO", "kU_ExportDatabase", + "kU_ImportDatabase", "kU_AttachDatabase", "kU_DetachDatabase", "kU_StandaloneCall", + "kU_CommentOn", "kU_CreateMacro", "kU_PositionalArgs", "kU_DefaultArg", + "kU_FilePaths", "kU_ParsingOptions", "kU_ParsingOption", "kU_DDL", + "kU_CreateNodeTable", "kU_CreateRelTable", "kU_CreateRelTableGroup", "kU_RelTableConnection", "kU_CreateRdfGraph", "kU_DropTable", "kU_AlterTable", "kU_AlterOptions", "kU_AddProperty", "kU_DropProperty", "kU_RenameTable", "kU_RenameProperty", "kU_PropertyDefinitions", "kU_PropertyDefinition", @@ -93,7 +94,7 @@ void cypherParserInitialize() { "oC_Dash" }, std::vector{ - "", "';'", "'('", "')'", "','", "'='", "'['", "']'", "'{'", "'}'", + "", "';'", "'('", "','", "')'", "'='", "'['", "']'", "'{'", "'}'", "'|'", "'..'", "'<>'", "'<'", "'<='", "'>'", "'>='", "'&'", "'>>'", "'<<'", "'+'", "'/'", "'%'", "'^'", "'=~'", "'.'", "'$'", "'\\u27E8'", "'\\u3008'", "'\\uFE64'", "'\\uFF1C'", "'\\u27E9'", "'\\u3009'", "'\\uFE65'", @@ -102,34 +103,34 @@ void cypherParserInitialize() { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "'*'", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "'!='", "'-'", "'!'", "':'", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", "", "", "", "", "'0'" + "", "", "", "'*'", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "'!='", "'-'", "'!'", "':'", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "'0'" }, std::vector{ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", "", "", "CALL", "COMMENT", - "MACRO", "GLOB", "COPY", "FROM", "COLUMN", "EXPORT", "IMPORT", "DATABASE", - "NODE", "TABLE", "GROUP", "RDFGRAPH", "DROP", "ALTER", "DEFAULT", - "RENAME", "ADD", "PRIMARY", "KEY", "REL", "TO", "EXPLAIN", "PROFILE", - "BEGIN", "TRANSACTION", "READ", "ONLY", "WRITE", "COMMIT", "COMMIT_SKIP_CHECKPOINT", - "ROLLBACK", "ROLLBACK_SKIP_CHECKPOINT", "INSTALL", "EXTENSION", "UNION", - "ALL", "LOAD", "HEADERS", "OPTIONAL", "MATCH", "UNWIND", "CREATE", - "MERGE", "ON", "SET", "DETACH", "DELETE", "WITH", "RETURN", "DISTINCT", - "STAR", "AS", "ORDER", "BY", "L_SKIP", "LIMIT", "ASCENDING", "ASC", - "DESCENDING", "DESC", "WHERE", "SHORTEST", "OR", "XOR", "AND", "NOT", - "INVALID_NOT_EQUAL", "MINUS", "FACTORIAL", "COLON", "IN", "STARTS", - "ENDS", "CONTAINS", "IS", "NULL_", "TRUE", "FALSE", "COUNT", "EXISTS", - "CASE", "ELSE", "END", "WHEN", "THEN", "StringLiteral", "EscapedChar", - "DecimalInteger", "HexLetter", "HexDigit", "Digit", "NonZeroDigit", - "NonZeroOctDigit", "ZeroDigit", "RegularDecimalReal", "UnescapedSymbolicName", - "IdentifierStart", "IdentifierPart", "EscapedSymbolicName", "SP", - "WHITESPACE", "Comment", "Unknown" + "", "", "", "", "", "", "", "", "", "", "", "", "ATTACH", "DBTYPE", + "CALL", "COMMENT_", "MACRO", "GLOB", "COPY", "FROM", "COLUMN", "EXPORT", + "IMPORT", "DATABASE", "NODE", "TABLE", "GROUP", "RDFGRAPH", "DROP", + "ALTER", "DEFAULT", "RENAME", "ADD", "PRIMARY", "KEY", "REL", "TO", + "EXPLAIN", "PROFILE", "BEGIN", "TRANSACTION", "READ", "ONLY", "WRITE", + "COMMIT", "COMMIT_SKIP_CHECKPOINT", "ROLLBACK", "ROLLBACK_SKIP_CHECKPOINT", + "INSTALL", "EXTENSION", "UNION", "ALL", "LOAD", "HEADERS", "OPTIONAL", + "MATCH", "UNWIND", "CREATE", "MERGE", "ON", "SET", "DETACH", "DELETE", + "WITH", "RETURN", "DISTINCT", "STAR", "AS", "ORDER", "BY", "L_SKIP", + "LIMIT", "ASCENDING", "ASC", "DESCENDING", "DESC", "WHERE", "SHORTEST", + "OR", "XOR", "AND", "NOT", "INVALID_NOT_EQUAL", "MINUS", "FACTORIAL", + "COLON", "IN", "STARTS", "ENDS", "CONTAINS", "IS", "NULL_", "TRUE", + "FALSE", "COUNT", "EXISTS", "CASE", "ELSE", "END", "WHEN", "THEN", + "StringLiteral", "EscapedChar", "DecimalInteger", "HexLetter", "HexDigit", + "Digit", "NonZeroDigit", "NonZeroOctDigit", "ZeroDigit", "RegularDecimalReal", + "UnescapedSymbolicName", "IdentifierStart", "IdentifierPart", "EscapedSymbolicName", + "SP", "WHITESPACE", "Comment", "Unknown" } ); static const int32_t serializedATNSegment[] = { - 4,1,150,2310,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6, + 4,1,152,2331,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6, 2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14, 7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21, 7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28, @@ -150,187 +151,190 @@ void cypherParserInitialize() { 7,122,2,123,7,123,2,124,7,124,2,125,7,125,2,126,7,126,2,127,7,127,2,128, 7,128,2,129,7,129,2,130,7,130,2,131,7,131,2,132,7,132,2,133,7,133,2,134, 7,134,2,135,7,135,2,136,7,136,2,137,7,137,2,138,7,138,2,139,7,139,2,140, - 7,140,2,141,7,141,2,142,7,142,2,143,7,143,2,144,7,144,1,0,1,0,3,0,293, - 8,0,1,0,1,0,3,0,297,8,0,1,0,5,0,300,8,0,10,0,12,0,303,9,0,1,0,3,0,306, - 8,0,1,0,1,0,1,1,3,1,311,8,1,1,1,3,1,314,8,1,1,1,1,1,3,1,318,8,1,1,1,3, - 1,321,8,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3,2,335,8,2, - 1,3,1,3,1,3,1,3,3,3,341,8,3,1,3,1,3,3,3,345,8,3,1,3,1,3,3,3,349,8,3,1, - 3,1,3,3,3,353,8,3,1,3,3,3,356,8,3,1,3,1,3,1,3,1,3,3,3,362,8,3,1,3,3,3, - 365,8,3,1,3,1,3,3,3,369,8,3,1,3,1,3,3,3,373,8,3,1,3,1,3,3,3,377,8,3,1, - 4,1,4,3,4,381,8,4,1,4,1,4,3,4,385,8,4,1,4,5,4,388,8,4,10,4,12,4,391,9, - 4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,5,3,5,401,8,5,1,5,1,5,3,5,405,8,5,1,5, - 1,5,3,5,409,8,5,1,5,5,5,412,8,5,10,5,12,5,415,9,5,1,5,1,5,1,5,1,5,1,5, - 1,5,1,6,1,6,1,6,1,6,3,6,427,8,6,1,6,1,6,3,6,431,8,6,1,6,1,6,1,6,1,6,1, - 6,1,6,3,6,439,8,6,1,6,1,6,3,6,443,8,6,1,6,1,6,3,6,447,8,6,1,6,1,6,3,6, - 451,8,6,1,7,1,7,1,7,1,7,1,7,1,7,3,7,459,8,7,1,7,1,7,3,7,463,8,7,1,7,1, - 7,3,7,467,8,7,1,7,1,7,3,7,471,8,7,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9, - 1,9,3,9,483,8,9,1,9,1,9,3,9,487,8,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10, - 1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,11,3,11, - 509,8,11,1,11,1,11,3,11,513,8,11,1,11,3,11,516,8,11,1,11,3,11,519,8,11, - 1,11,3,11,522,8,11,1,11,3,11,525,8,11,1,11,1,11,3,11,529,8,11,1,11,5, - 11,532,8,11,10,11,12,11,535,9,11,1,11,3,11,538,8,11,1,11,1,11,1,11,1, - 11,1,11,1,11,1,12,1,12,3,12,548,8,12,1,12,1,12,3,12,552,8,12,1,12,5,12, - 555,8,12,10,12,12,12,558,9,12,1,13,1,13,3,13,562,8,13,1,13,1,13,1,13, - 3,13,567,8,13,1,13,1,13,1,14,1,14,3,14,573,8,14,1,14,1,14,3,14,577,8, - 14,1,14,1,14,3,14,581,8,14,1,14,5,14,584,8,14,10,14,12,14,587,9,14,1, - 14,1,14,1,14,1,14,3,14,593,8,14,1,14,1,14,3,14,597,8,14,1,14,1,14,3,14, - 601,8,14,1,14,3,14,604,8,14,1,15,1,15,3,15,608,8,15,1,15,1,15,3,15,612, - 8,15,1,15,5,15,615,8,15,10,15,12,15,618,9,15,1,16,1,16,3,16,622,8,16, - 1,16,1,16,3,16,626,8,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,3,17, - 636,8,17,1,18,1,18,1,18,1,18,1,18,1,18,1,18,1,18,3,18,646,8,18,1,18,1, - 18,3,18,650,8,18,1,18,1,18,3,18,654,8,18,1,18,1,18,3,18,658,8,18,1,18, - 1,18,1,18,3,18,663,8,18,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,19,1,19, - 1,19,3,19,675,8,19,1,19,1,19,3,19,679,8,19,1,19,1,19,3,19,683,8,19,1, - 19,1,19,3,19,687,8,19,1,19,1,19,3,19,691,8,19,3,19,693,8,19,1,19,1,19, - 3,19,697,8,19,1,19,1,19,3,19,701,8,19,3,19,703,8,19,1,19,1,19,1,20,1, - 20,1,20,1,20,1,20,1,20,1,20,1,20,1,20,1,20,3,20,717,8,20,1,20,1,20,3, - 20,721,8,20,1,20,1,20,3,20,725,8,20,1,20,1,20,3,20,729,8,20,1,20,4,20, - 732,8,20,11,20,12,20,733,1,20,3,20,737,8,20,1,20,1,20,3,20,741,8,20,1, - 20,1,20,3,20,745,8,20,3,20,747,8,20,1,20,1,20,3,20,751,8,20,1,20,1,20, - 3,20,755,8,20,3,20,757,8,20,1,20,1,20,1,21,1,21,1,21,1,21,1,21,1,21,1, - 21,1,21,1,22,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,1,23,1, - 24,1,24,1,24,1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,25,1,25,3,25,793,8, - 25,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,3,26,804,8,26,1,27,1, - 27,1,27,1,27,1,28,1,28,1,28,1,28,1,28,1,28,1,29,1,29,1,29,1,29,1,29,1, - 29,1,29,1,29,1,30,1,30,3,30,826,8,30,1,30,1,30,3,30,830,8,30,1,30,5,30, - 833,8,30,10,30,12,30,836,9,30,1,31,1,31,1,31,1,31,1,32,1,32,1,32,1,32, - 3,32,846,8,32,1,32,1,32,3,32,850,8,32,1,32,1,32,3,32,854,8,32,1,32,1, - 32,1,33,1,33,1,33,1,33,3,33,862,8,33,1,33,1,33,3,33,866,8,33,1,33,1,33, - 3,33,870,8,33,1,33,1,33,1,33,1,33,3,33,876,8,33,1,33,1,33,3,33,880,8, - 33,1,33,1,33,3,33,884,8,33,1,33,1,33,1,33,1,33,3,33,890,8,33,1,33,1,33, - 3,33,894,8,33,1,33,1,33,3,33,898,8,33,1,33,1,33,3,33,902,8,33,1,33,1, - 33,3,33,906,8,33,1,33,1,33,3,33,910,8,33,1,33,1,33,5,33,914,8,33,10,33, - 12,33,917,9,33,1,34,1,34,5,34,921,8,34,10,34,12,34,924,9,34,1,35,1,35, - 3,35,928,8,35,1,35,1,35,1,36,1,36,3,36,934,8,36,1,37,1,37,1,38,1,38,1, - 39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,3, - 39,954,8,39,1,40,1,40,3,40,958,8,40,1,41,1,41,1,41,1,41,1,41,1,41,3,41, - 966,8,41,1,42,1,42,1,42,1,42,1,43,1,43,1,44,1,44,3,44,976,8,44,1,44,5, - 44,979,8,44,10,44,12,44,982,9,44,1,44,1,44,3,44,986,8,44,4,44,988,8,44, - 11,44,12,44,989,1,44,1,44,1,44,3,44,995,8,44,1,45,1,45,1,45,1,45,3,45, - 1001,8,45,1,45,1,45,1,45,3,45,1006,8,45,1,45,3,45,1009,8,45,1,46,1,46, - 3,46,1013,8,46,1,47,1,47,3,47,1017,8,47,5,47,1019,8,47,10,47,12,47,1022, - 9,47,1,47,1,47,1,47,3,47,1027,8,47,5,47,1029,8,47,10,47,12,47,1032,9, - 47,1,47,1,47,3,47,1036,8,47,1,47,5,47,1039,8,47,10,47,12,47,1042,9,47, - 1,47,3,47,1045,8,47,1,47,3,47,1048,8,47,1,47,1,47,3,47,1052,8,47,4,47, - 1054,8,47,11,47,12,47,1055,1,47,1,47,3,47,1060,8,47,1,48,1,48,3,48,1064, - 8,48,4,48,1066,8,48,11,48,12,48,1067,1,48,1,48,1,49,1,49,3,49,1074,8, - 49,5,49,1076,8,49,10,49,12,49,1079,9,49,1,49,1,49,3,49,1083,8,49,5,49, - 1085,8,49,10,49,12,49,1088,9,49,1,49,1,49,1,50,1,50,1,50,1,50,3,50,1096, - 8,50,1,51,1,51,1,51,1,51,3,51,1102,8,51,1,52,1,52,1,52,1,52,1,52,1,52, - 3,52,1110,8,52,1,52,1,52,3,52,1114,8,52,1,52,1,52,3,52,1118,8,52,1,52, - 1,52,3,52,1122,8,52,1,52,1,52,1,52,1,52,1,52,3,52,1129,8,52,1,52,1,52, - 3,52,1133,8,52,1,52,1,52,3,52,1137,8,52,1,52,1,52,3,52,1141,8,52,1,52, - 3,52,1144,8,52,1,52,3,52,1147,8,52,1,52,3,52,1150,8,52,1,53,1,53,1,53, - 1,53,3,53,1156,8,53,1,53,3,53,1159,8,53,1,54,1,54,3,54,1163,8,54,1,54, - 1,54,3,54,1167,8,54,1,54,1,54,3,54,1171,8,54,1,54,3,54,1174,8,54,1,55, - 1,55,3,55,1178,8,55,1,55,1,55,1,55,1,55,1,55,1,55,1,56,1,56,3,56,1188, - 8,56,1,56,1,56,1,57,1,57,3,57,1194,8,57,1,57,1,57,1,57,5,57,1199,8,57, - 10,57,12,57,1202,9,57,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1, - 58,3,58,1214,8,58,1,59,1,59,3,59,1218,8,59,1,59,1,59,3,59,1222,8,59,1, - 59,1,59,3,59,1226,8,59,1,59,5,59,1229,8,59,10,59,12,59,1232,9,59,1,60, - 1,60,3,60,1236,8,60,1,60,1,60,3,60,1240,8,60,1,60,1,60,1,61,1,61,3,61, - 1246,8,61,1,61,1,61,3,61,1250,8,61,1,61,1,61,3,61,1254,8,61,1,61,1,61, - 3,61,1258,8,61,1,61,5,61,1261,8,61,10,61,12,61,1264,9,61,1,62,1,62,1, - 62,3,62,1269,8,62,1,62,3,62,1272,8,62,1,63,1,63,1,63,1,64,3,64,1278,8, - 64,1,64,3,64,1281,8,64,1,64,1,64,1,64,1,64,3,64,1287,8,64,1,64,1,64,3, - 64,1291,8,64,1,64,1,64,3,64,1295,8,64,1,65,1,65,3,65,1299,8,65,1,65,1, - 65,3,65,1303,8,65,1,65,5,65,1306,8,65,10,65,12,65,1309,9,65,1,65,1,65, - 3,65,1313,8,65,1,65,1,65,3,65,1317,8,65,1,65,5,65,1320,8,65,10,65,12, - 65,1323,9,65,3,65,1325,8,65,1,66,1,66,1,66,1,66,1,66,1,66,1,66,3,66,1334, - 8,66,1,67,1,67,1,67,1,67,1,67,1,67,1,67,3,67,1343,8,67,1,67,5,67,1346, - 8,67,10,67,12,67,1349,9,67,1,68,1,68,1,68,1,68,1,69,1,69,1,69,1,69,1, - 70,1,70,3,70,1361,8,70,1,70,3,70,1364,8,70,1,71,1,71,1,71,1,71,1,72,1, - 72,3,72,1372,8,72,1,72,1,72,3,72,1376,8,72,1,72,5,72,1379,8,72,10,72, - 12,72,1382,9,72,1,73,1,73,3,73,1386,8,73,1,73,1,73,3,73,1390,8,73,1,73, - 1,73,1,73,3,73,1395,8,73,1,74,1,74,1,75,1,75,3,75,1401,8,75,1,75,5,75, - 1404,8,75,10,75,12,75,1407,9,75,1,75,1,75,1,75,1,75,3,75,1413,8,75,1, - 76,1,76,3,76,1417,8,76,1,76,1,76,3,76,1421,8,76,3,76,1423,8,76,1,76,1, - 76,3,76,1427,8,76,3,76,1429,8,76,1,76,1,76,3,76,1433,8,76,3,76,1435,8, - 76,1,76,1,76,1,77,1,77,3,77,1441,8,77,1,77,1,77,1,78,1,78,3,78,1447,8, - 78,1,78,1,78,3,78,1451,8,78,1,78,3,78,1454,8,78,1,78,3,78,1457,8,78,1, - 78,1,78,1,78,1,78,3,78,1463,8,78,1,78,3,78,1466,8,78,1,78,3,78,1469,8, - 78,1,78,1,78,3,78,1473,8,78,1,78,1,78,1,78,1,78,3,78,1479,8,78,1,78,3, - 78,1482,8,78,1,78,3,78,1485,8,78,1,78,1,78,3,78,1489,8,78,1,79,1,79,3, - 79,1493,8,79,1,79,1,79,3,79,1497,8,79,3,79,1499,8,79,1,79,1,79,3,79,1503, - 8,79,3,79,1505,8,79,1,79,1,79,3,79,1509,8,79,3,79,1511,8,79,1,79,1,79, - 3,79,1515,8,79,3,79,1517,8,79,1,79,1,79,1,80,1,80,3,80,1523,8,80,1,80, - 1,80,3,80,1527,8,80,1,80,1,80,3,80,1531,8,80,1,80,1,80,3,80,1535,8,80, - 1,80,1,80,3,80,1539,8,80,1,80,1,80,3,80,1543,8,80,1,80,1,80,3,80,1547, - 8,80,1,80,1,80,3,80,1551,8,80,5,80,1553,8,80,10,80,12,80,1556,9,80,3, - 80,1558,8,80,1,80,1,80,1,81,1,81,3,81,1564,8,81,1,81,1,81,3,81,1568,8, - 81,1,81,1,81,3,81,1572,8,81,1,81,3,81,1575,8,81,1,81,5,81,1578,8,81,10, - 81,12,81,1581,9,81,1,82,1,82,3,82,1585,8,82,1,82,5,82,1588,8,82,10,82, - 12,82,1591,9,82,1,83,1,83,3,83,1595,8,83,1,83,1,83,1,84,1,84,3,84,1601, - 8,84,1,84,1,84,1,84,1,84,3,84,1607,8,84,1,84,3,84,1610,8,84,1,84,3,84, - 1613,8,84,1,84,3,84,1616,8,84,1,84,1,84,3,84,1620,8,84,1,84,3,84,1623, - 8,84,1,84,3,84,1626,8,84,1,84,3,84,1629,8,84,1,84,3,84,1632,8,84,1,85, - 1,85,3,85,1636,8,85,1,85,1,85,3,85,1640,8,85,1,85,1,85,3,85,1644,8,85, - 1,85,1,85,3,85,1648,8,85,1,85,1,85,3,85,1652,8,85,1,85,3,85,1655,8,85, - 1,85,3,85,1658,8,85,1,85,1,85,3,85,1662,8,85,1,85,1,85,3,85,1666,8,85, - 1,85,1,85,3,85,1670,8,85,1,85,1,85,3,85,1674,8,85,3,85,1676,8,85,1,85, - 1,85,1,86,1,86,3,86,1682,8,86,1,86,3,86,1685,8,86,1,86,3,86,1688,8,86, - 1,86,1,86,1,87,1,87,3,87,1694,8,87,1,87,3,87,1697,8,87,1,87,3,87,1700, - 8,87,1,87,1,87,1,88,1,88,1,89,1,89,1,90,1,90,1,91,1,91,1,92,1,92,1,93, - 1,93,1,93,1,93,1,93,5,93,1719,8,93,10,93,12,93,1722,9,93,1,94,1,94,1, - 94,1,94,1,94,5,94,1729,8,94,10,94,12,94,1732,9,94,1,95,1,95,1,95,1,95, - 1,95,5,95,1739,8,95,10,95,12,95,1742,9,95,1,96,1,96,3,96,1746,8,96,5, - 96,1748,8,96,10,96,12,96,1751,9,96,1,96,1,96,1,97,1,97,3,97,1757,8,97, - 1,97,1,97,3,97,1761,8,97,1,97,1,97,3,97,1765,8,97,1,97,1,97,3,97,1769, - 8,97,1,97,1,97,3,97,1773,8,97,1,97,1,97,1,97,1,97,1,97,1,97,3,97,1781, - 8,97,1,97,1,97,3,97,1785,8,97,1,97,1,97,3,97,1789,8,97,1,97,1,97,3,97, - 1793,8,97,1,97,1,97,4,97,1797,8,97,11,97,12,97,1798,1,97,1,97,3,97,1803, - 8,97,1,98,1,98,1,99,1,99,3,99,1809,8,99,1,99,1,99,3,99,1813,8,99,1,99, - 5,99,1816,8,99,10,99,12,99,1819,9,99,1,100,1,100,3,100,1823,8,100,1,100, - 1,100,3,100,1827,8,100,1,100,5,100,1830,8,100,10,100,12,100,1833,9,100, - 1,101,1,101,3,101,1837,8,101,1,101,1,101,3,101,1841,8,101,1,101,1,101, - 5,101,1845,8,101,10,101,12,101,1848,9,101,1,102,1,102,1,103,1,103,3,103, - 1854,8,103,1,103,1,103,3,103,1858,8,103,1,103,1,103,5,103,1862,8,103, - 10,103,12,103,1865,9,103,1,104,1,104,1,105,1,105,3,105,1871,8,105,1,105, - 1,105,3,105,1875,8,105,1,105,1,105,5,105,1879,8,105,10,105,12,105,1882, - 9,105,1,106,1,106,1,107,1,107,3,107,1888,8,107,1,107,1,107,3,107,1892, - 8,107,1,107,5,107,1895,8,107,10,107,12,107,1898,9,107,1,108,1,108,3,108, - 1902,8,108,5,108,1904,8,108,10,108,12,108,1907,9,108,1,108,1,108,3,108, - 1911,8,108,1,108,3,108,1914,8,108,1,109,1,109,1,109,4,109,1919,8,109, - 11,109,12,109,1920,1,109,3,109,1924,8,109,1,110,1,110,1,110,3,110,1929, - 8,110,1,110,1,110,1,110,1,110,1,110,1,110,1,110,3,110,1938,8,110,1,110, - 1,110,3,110,1942,8,110,1,110,3,110,1945,8,110,1,111,1,111,1,111,1,111, - 1,111,1,111,1,111,1,111,1,111,1,111,1,111,3,111,1958,8,111,1,111,3,111, - 1961,8,111,1,111,1,111,1,112,3,112,1966,8,112,1,112,1,112,1,113,1,113, - 1,113,1,113,1,113,1,113,1,113,1,113,1,113,1,113,3,113,1980,8,113,1,114, - 1,114,3,114,1984,8,114,1,114,5,114,1987,8,114,10,114,12,114,1990,9,114, - 1,115,1,115,1,115,1,115,1,115,1,115,1,115,1,115,1,115,3,115,2001,8,115, - 1,116,1,116,1,116,1,116,1,116,1,116,3,116,2009,8,116,1,117,1,117,1,118, - 1,118,3,118,2015,8,118,1,118,1,118,3,118,2019,8,118,1,118,1,118,3,118, - 2023,8,118,5,118,2025,8,118,10,118,12,118,2028,9,118,3,118,2030,8,118, - 1,118,1,118,1,119,1,119,3,119,2036,8,119,1,119,3,119,2039,8,119,1,120, - 1,120,3,120,2043,8,120,1,120,1,120,3,120,2047,8,120,1,120,1,120,3,120, - 2051,8,120,1,120,1,120,3,120,2055,8,120,5,120,2057,8,120,10,120,12,120, - 2060,9,120,1,120,1,120,1,121,1,121,3,121,2066,8,121,1,121,3,121,2069, - 8,121,1,121,1,121,3,121,2073,8,121,1,121,1,121,1,122,1,122,3,122,2079, - 8,122,1,122,1,122,3,122,2083,8,122,1,122,1,122,1,123,1,123,3,123,2089, - 8,123,1,123,1,123,3,123,2093,8,123,1,123,1,123,3,123,2097,8,123,1,123, - 1,123,1,123,3,123,2102,8,123,1,123,1,123,3,123,2106,8,123,1,123,1,123, - 3,123,2110,8,123,3,123,2112,8,123,1,123,1,123,3,123,2116,8,123,1,123, - 1,123,3,123,2120,8,123,1,123,1,123,3,123,2124,8,123,5,123,2126,8,123, - 10,123,12,123,2129,9,123,3,123,2131,8,123,1,123,1,123,3,123,2135,8,123, - 1,124,1,124,1,125,1,125,3,125,2141,8,125,1,125,1,125,1,125,3,125,2146, - 8,125,3,125,2148,8,125,1,125,1,125,1,126,1,126,3,126,2154,8,126,1,126, - 4,126,2157,8,126,11,126,12,126,2158,1,127,1,127,3,127,2163,8,127,1,127, - 1,127,3,127,2167,8,127,1,127,1,127,3,127,2171,8,127,1,127,1,127,3,127, - 2175,8,127,1,127,3,127,2178,8,127,1,127,3,127,2181,8,127,1,127,1,127, - 1,128,1,128,3,128,2187,8,128,1,128,1,128,3,128,2191,8,128,1,128,1,128, - 3,128,2195,8,128,1,128,1,128,3,128,2199,8,128,1,128,3,128,2202,8,128, - 1,128,3,128,2205,8,128,1,128,1,128,1,129,1,129,3,129,2211,8,129,1,129, - 1,129,3,129,2215,8,129,1,130,1,130,3,130,2219,8,130,1,130,4,130,2222, - 8,130,11,130,12,130,2223,1,130,1,130,3,130,2228,8,130,1,130,1,130,3,130, - 2232,8,130,1,130,4,130,2235,8,130,11,130,12,130,2236,3,130,2239,8,130, - 1,130,3,130,2242,8,130,1,130,1,130,3,130,2246,8,130,1,130,3,130,2249, - 8,130,1,130,3,130,2252,8,130,1,130,1,130,1,131,1,131,3,131,2258,8,131, - 1,131,1,131,3,131,2262,8,131,1,131,1,131,3,131,2266,8,131,1,131,1,131, - 1,132,1,132,1,133,1,133,3,133,2274,8,133,1,134,1,134,1,134,3,134,2279, - 8,134,1,135,1,135,3,135,2283,8,135,1,135,1,135,1,136,1,136,1,137,1,137, - 1,138,1,138,1,139,1,139,1,140,1,140,1,140,1,140,1,140,3,140,2300,8,140, - 1,141,1,141,1,142,1,142,1,143,1,143,1,144,1,144,1,144,0,1,66,145,0,2, + 7,140,2,141,7,141,2,142,7,142,2,143,7,143,2,144,7,144,2,145,7,145,2,146, + 7,146,2,147,7,147,1,0,1,0,3,0,299,8,0,1,0,1,0,3,0,303,8,0,1,0,5,0,306, + 8,0,10,0,12,0,309,9,0,1,0,3,0,312,8,0,1,0,1,0,1,1,3,1,317,8,1,1,1,3,1, + 320,8,1,1,1,1,1,3,1,324,8,1,1,1,3,1,327,8,1,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3,2,343,8,2,1,3,1,3,1,3,1,3,3,3,349,8,3, + 1,3,1,3,3,3,353,8,3,1,3,3,3,356,8,3,1,3,1,3,1,3,1,3,3,3,362,8,3,1,3,3, + 3,365,8,3,1,4,1,4,3,4,369,8,4,1,4,1,4,3,4,373,8,4,1,4,1,4,3,4,377,8,4, + 1,4,5,4,380,8,4,10,4,12,4,383,9,4,1,4,3,4,386,8,4,1,4,1,4,1,5,1,5,1,5, + 3,5,393,8,5,1,5,1,5,3,5,397,8,5,1,5,1,5,1,5,3,5,402,8,5,1,6,1,6,1,6,1, + 6,1,6,1,6,1,6,1,6,3,6,412,8,6,1,6,1,6,3,6,416,8,6,1,6,1,6,3,6,420,8,6, + 1,6,5,6,423,8,6,10,6,12,6,426,9,6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7, + 1,7,3,7,438,8,7,1,7,1,7,3,7,442,8,7,1,7,1,7,1,7,1,7,1,7,1,7,3,7,450,8, + 7,1,7,3,7,453,8,7,1,8,1,8,1,8,1,8,1,8,1,8,3,8,461,8,8,1,8,3,8,464,8,8, + 1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10, + 3,10,481,8,10,1,10,3,10,484,8,10,1,10,1,10,3,10,488,8,10,1,10,1,10,1, + 10,1,10,3,10,494,8,10,1,10,3,10,497,8,10,1,11,1,11,1,11,1,11,1,12,1,12, + 1,12,1,12,3,12,507,8,12,1,12,1,12,3,12,511,8,12,1,12,1,12,1,13,1,13,1, + 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1, + 14,1,14,3,14,533,8,14,1,14,1,14,3,14,537,8,14,1,14,3,14,540,8,14,1,14, + 3,14,543,8,14,1,14,3,14,546,8,14,1,14,3,14,549,8,14,1,14,1,14,3,14,553, + 8,14,1,14,5,14,556,8,14,10,14,12,14,559,9,14,1,14,3,14,562,8,14,1,14, + 1,14,1,14,1,14,1,14,1,14,1,15,1,15,3,15,572,8,15,1,15,1,15,3,15,576,8, + 15,1,15,5,15,579,8,15,10,15,12,15,582,9,15,1,16,1,16,3,16,586,8,16,1, + 16,1,16,1,16,3,16,591,8,16,1,16,1,16,1,17,1,17,3,17,597,8,17,1,17,1,17, + 3,17,601,8,17,1,17,1,17,3,17,605,8,17,1,17,5,17,608,8,17,10,17,12,17, + 611,9,17,1,17,1,17,1,17,1,17,3,17,617,8,17,1,17,1,17,3,17,621,8,17,1, + 17,1,17,3,17,625,8,17,1,17,3,17,628,8,17,1,18,1,18,3,18,632,8,18,1,18, + 1,18,3,18,636,8,18,1,18,1,18,3,18,640,8,18,1,18,5,18,643,8,18,10,18,12, + 18,646,9,18,1,18,3,18,649,8,18,1,18,1,18,1,19,1,19,3,19,655,8,19,1,19, + 1,19,3,19,659,8,19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,1,20,3,20,669,8, + 20,1,21,1,21,1,21,1,21,1,21,1,21,1,21,1,21,3,21,679,8,21,1,21,1,21,3, + 21,683,8,21,1,21,1,21,3,21,687,8,21,1,21,1,21,3,21,691,8,21,1,21,1,21, + 1,21,3,21,696,8,21,1,21,1,21,1,22,1,22,1,22,1,22,1,22,1,22,1,22,1,22, + 3,22,708,8,22,1,22,1,22,3,22,712,8,22,1,22,1,22,3,22,716,8,22,1,22,1, + 22,3,22,720,8,22,1,22,1,22,3,22,724,8,22,3,22,726,8,22,1,22,1,22,3,22, + 730,8,22,1,22,1,22,3,22,734,8,22,3,22,736,8,22,1,22,1,22,1,23,1,23,1, + 23,1,23,1,23,1,23,1,23,1,23,1,23,1,23,3,23,750,8,23,1,23,1,23,3,23,754, + 8,23,1,23,1,23,3,23,758,8,23,1,23,1,23,3,23,762,8,23,1,23,4,23,765,8, + 23,11,23,12,23,766,1,23,3,23,770,8,23,1,23,1,23,3,23,774,8,23,1,23,1, + 23,3,23,778,8,23,3,23,780,8,23,1,23,1,23,3,23,784,8,23,1,23,1,23,3,23, + 788,8,23,3,23,790,8,23,1,23,1,23,1,24,1,24,1,24,1,24,1,24,1,24,1,24,1, + 24,1,25,1,25,1,25,1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,26,1,27,1, + 27,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,3,28,826,8,28,1, + 29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,3,29,837,8,29,1,30,1,30,1, + 30,1,30,1,31,1,31,1,31,1,31,1,31,1,31,1,32,1,32,1,32,1,32,1,32,1,32,1, + 32,1,32,1,33,1,33,3,33,859,8,33,1,33,1,33,3,33,863,8,33,1,33,5,33,866, + 8,33,10,33,12,33,869,9,33,1,34,1,34,1,34,1,34,1,35,1,35,1,35,1,35,3,35, + 879,8,35,1,35,1,35,3,35,883,8,35,1,35,1,35,3,35,887,8,35,1,35,1,35,1, + 36,1,36,1,36,1,36,3,36,895,8,36,1,36,1,36,3,36,899,8,36,1,36,1,36,3,36, + 903,8,36,1,36,1,36,1,36,1,36,3,36,909,8,36,1,36,1,36,3,36,913,8,36,1, + 36,1,36,3,36,917,8,36,1,36,1,36,1,36,1,36,3,36,923,8,36,1,36,1,36,3,36, + 927,8,36,1,36,1,36,3,36,931,8,36,1,36,1,36,3,36,935,8,36,1,36,1,36,3, + 36,939,8,36,1,36,1,36,3,36,943,8,36,1,36,1,36,5,36,947,8,36,10,36,12, + 36,950,9,36,1,37,1,37,5,37,954,8,37,10,37,12,37,957,9,37,1,38,1,38,3, + 38,961,8,38,1,38,1,38,1,39,1,39,3,39,967,8,39,1,40,1,40,1,41,1,41,1,42, + 1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,3,42, + 987,8,42,1,43,1,43,3,43,991,8,43,1,44,1,44,1,44,1,44,1,44,1,44,3,44,999, + 8,44,1,45,1,45,1,45,1,45,1,46,1,46,1,47,1,47,3,47,1009,8,47,1,47,5,47, + 1012,8,47,10,47,12,47,1015,9,47,1,47,1,47,3,47,1019,8,47,4,47,1021,8, + 47,11,47,12,47,1022,1,47,1,47,1,47,3,47,1028,8,47,1,48,1,48,1,48,1,48, + 3,48,1034,8,48,1,48,1,48,1,48,3,48,1039,8,48,1,48,3,48,1042,8,48,1,49, + 1,49,3,49,1046,8,49,1,50,1,50,3,50,1050,8,50,5,50,1052,8,50,10,50,12, + 50,1055,9,50,1,50,1,50,1,50,3,50,1060,8,50,5,50,1062,8,50,10,50,12,50, + 1065,9,50,1,50,1,50,3,50,1069,8,50,1,50,5,50,1072,8,50,10,50,12,50,1075, + 9,50,1,50,3,50,1078,8,50,1,50,3,50,1081,8,50,1,50,1,50,3,50,1085,8,50, + 4,50,1087,8,50,11,50,12,50,1088,1,50,1,50,3,50,1093,8,50,1,51,1,51,3, + 51,1097,8,51,4,51,1099,8,51,11,51,12,51,1100,1,51,1,51,1,52,1,52,3,52, + 1107,8,52,5,52,1109,8,52,10,52,12,52,1112,9,52,1,52,1,52,3,52,1116,8, + 52,5,52,1118,8,52,10,52,12,52,1121,9,52,1,52,1,52,1,53,1,53,1,53,1,53, + 3,53,1129,8,53,1,54,1,54,1,54,1,54,3,54,1135,8,54,1,55,1,55,1,55,1,55, + 1,55,1,55,3,55,1143,8,55,1,55,1,55,3,55,1147,8,55,1,55,1,55,3,55,1151, + 8,55,1,55,1,55,3,55,1155,8,55,1,55,1,55,1,55,1,55,1,55,3,55,1162,8,55, + 1,55,3,55,1165,8,55,1,55,3,55,1168,8,55,1,55,3,55,1171,8,55,1,56,1,56, + 1,56,1,56,3,56,1177,8,56,1,56,3,56,1180,8,56,1,57,1,57,3,57,1184,8,57, + 1,57,1,57,3,57,1188,8,57,1,57,1,57,3,57,1192,8,57,1,57,3,57,1195,8,57, + 1,58,1,58,3,58,1199,8,58,1,58,1,58,1,58,1,58,1,58,1,58,1,59,1,59,3,59, + 1209,8,59,1,59,1,59,1,60,1,60,3,60,1215,8,60,1,60,1,60,1,60,5,60,1220, + 8,60,10,60,12,60,1223,9,60,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1, + 61,1,61,3,61,1235,8,61,1,62,1,62,3,62,1239,8,62,1,62,1,62,3,62,1243,8, + 62,1,62,1,62,3,62,1247,8,62,1,62,5,62,1250,8,62,10,62,12,62,1253,9,62, + 1,63,1,63,3,63,1257,8,63,1,63,1,63,3,63,1261,8,63,1,63,1,63,1,64,1,64, + 3,64,1267,8,64,1,64,1,64,3,64,1271,8,64,1,64,1,64,3,64,1275,8,64,1,64, + 1,64,3,64,1279,8,64,1,64,5,64,1282,8,64,10,64,12,64,1285,9,64,1,65,1, + 65,1,65,3,65,1290,8,65,1,65,3,65,1293,8,65,1,66,1,66,1,66,1,67,3,67,1299, + 8,67,1,67,3,67,1302,8,67,1,67,1,67,1,67,1,67,3,67,1308,8,67,1,67,1,67, + 3,67,1312,8,67,1,67,1,67,3,67,1316,8,67,1,68,1,68,3,68,1320,8,68,1,68, + 1,68,3,68,1324,8,68,1,68,5,68,1327,8,68,10,68,12,68,1330,9,68,1,68,1, + 68,3,68,1334,8,68,1,68,1,68,3,68,1338,8,68,1,68,5,68,1341,8,68,10,68, + 12,68,1344,9,68,3,68,1346,8,68,1,69,1,69,1,69,1,69,1,69,1,69,1,69,3,69, + 1355,8,69,1,70,1,70,1,70,1,70,1,70,1,70,1,70,3,70,1364,8,70,1,70,5,70, + 1367,8,70,10,70,12,70,1370,9,70,1,71,1,71,1,71,1,71,1,72,1,72,1,72,1, + 72,1,73,1,73,3,73,1382,8,73,1,73,3,73,1385,8,73,1,74,1,74,1,74,1,74,1, + 75,1,75,3,75,1393,8,75,1,75,1,75,3,75,1397,8,75,1,75,5,75,1400,8,75,10, + 75,12,75,1403,9,75,1,76,1,76,3,76,1407,8,76,1,76,1,76,3,76,1411,8,76, + 1,76,1,76,1,76,3,76,1416,8,76,1,77,1,77,1,78,1,78,3,78,1422,8,78,1,78, + 5,78,1425,8,78,10,78,12,78,1428,9,78,1,78,1,78,1,78,1,78,3,78,1434,8, + 78,1,79,1,79,3,79,1438,8,79,1,79,1,79,3,79,1442,8,79,3,79,1444,8,79,1, + 79,1,79,3,79,1448,8,79,3,79,1450,8,79,1,79,1,79,3,79,1454,8,79,3,79,1456, + 8,79,1,79,1,79,1,80,1,80,3,80,1462,8,80,1,80,1,80,1,81,1,81,3,81,1468, + 8,81,1,81,1,81,3,81,1472,8,81,1,81,3,81,1475,8,81,1,81,3,81,1478,8,81, + 1,81,1,81,1,81,1,81,3,81,1484,8,81,1,81,3,81,1487,8,81,1,81,3,81,1490, + 8,81,1,81,1,81,3,81,1494,8,81,1,81,1,81,1,81,1,81,3,81,1500,8,81,1,81, + 3,81,1503,8,81,1,81,3,81,1506,8,81,1,81,1,81,3,81,1510,8,81,1,82,1,82, + 3,82,1514,8,82,1,82,1,82,3,82,1518,8,82,3,82,1520,8,82,1,82,1,82,3,82, + 1524,8,82,3,82,1526,8,82,1,82,1,82,3,82,1530,8,82,3,82,1532,8,82,1,82, + 1,82,3,82,1536,8,82,3,82,1538,8,82,1,82,1,82,1,83,1,83,3,83,1544,8,83, + 1,83,1,83,3,83,1548,8,83,1,83,1,83,3,83,1552,8,83,1,83,1,83,3,83,1556, + 8,83,1,83,1,83,3,83,1560,8,83,1,83,1,83,3,83,1564,8,83,1,83,1,83,3,83, + 1568,8,83,1,83,1,83,3,83,1572,8,83,5,83,1574,8,83,10,83,12,83,1577,9, + 83,3,83,1579,8,83,1,83,1,83,1,84,1,84,3,84,1585,8,84,1,84,1,84,3,84,1589, + 8,84,1,84,1,84,3,84,1593,8,84,1,84,3,84,1596,8,84,1,84,5,84,1599,8,84, + 10,84,12,84,1602,9,84,1,85,1,85,3,85,1606,8,85,1,85,5,85,1609,8,85,10, + 85,12,85,1612,9,85,1,86,1,86,3,86,1616,8,86,1,86,1,86,1,87,1,87,3,87, + 1622,8,87,1,87,1,87,1,87,1,87,3,87,1628,8,87,1,87,3,87,1631,8,87,1,87, + 3,87,1634,8,87,1,87,3,87,1637,8,87,1,87,1,87,3,87,1641,8,87,1,87,3,87, + 1644,8,87,1,87,3,87,1647,8,87,1,87,3,87,1650,8,87,1,87,3,87,1653,8,87, + 1,88,1,88,3,88,1657,8,88,1,88,1,88,3,88,1661,8,88,1,88,1,88,3,88,1665, + 8,88,1,88,1,88,3,88,1669,8,88,1,88,1,88,3,88,1673,8,88,1,88,3,88,1676, + 8,88,1,88,3,88,1679,8,88,1,88,1,88,3,88,1683,8,88,1,88,1,88,3,88,1687, + 8,88,1,88,1,88,3,88,1691,8,88,1,88,1,88,3,88,1695,8,88,3,88,1697,8,88, + 1,88,1,88,1,89,1,89,3,89,1703,8,89,1,89,3,89,1706,8,89,1,89,3,89,1709, + 8,89,1,89,1,89,1,90,1,90,3,90,1715,8,90,1,90,3,90,1718,8,90,1,90,3,90, + 1721,8,90,1,90,1,90,1,91,1,91,1,92,1,92,1,93,1,93,1,94,1,94,1,95,1,95, + 1,96,1,96,1,96,1,96,1,96,5,96,1740,8,96,10,96,12,96,1743,9,96,1,97,1, + 97,1,97,1,97,1,97,5,97,1750,8,97,10,97,12,97,1753,9,97,1,98,1,98,1,98, + 1,98,1,98,5,98,1760,8,98,10,98,12,98,1763,9,98,1,99,1,99,3,99,1767,8, + 99,5,99,1769,8,99,10,99,12,99,1772,9,99,1,99,1,99,1,100,1,100,3,100,1778, + 8,100,1,100,1,100,3,100,1782,8,100,1,100,1,100,3,100,1786,8,100,1,100, + 1,100,3,100,1790,8,100,1,100,1,100,3,100,1794,8,100,1,100,1,100,1,100, + 1,100,1,100,1,100,3,100,1802,8,100,1,100,1,100,3,100,1806,8,100,1,100, + 1,100,3,100,1810,8,100,1,100,1,100,3,100,1814,8,100,1,100,1,100,4,100, + 1818,8,100,11,100,12,100,1819,1,100,1,100,3,100,1824,8,100,1,101,1,101, + 1,102,1,102,3,102,1830,8,102,1,102,1,102,3,102,1834,8,102,1,102,5,102, + 1837,8,102,10,102,12,102,1840,9,102,1,103,1,103,3,103,1844,8,103,1,103, + 1,103,3,103,1848,8,103,1,103,5,103,1851,8,103,10,103,12,103,1854,9,103, + 1,104,1,104,3,104,1858,8,104,1,104,1,104,3,104,1862,8,104,1,104,1,104, + 5,104,1866,8,104,10,104,12,104,1869,9,104,1,105,1,105,1,106,1,106,3,106, + 1875,8,106,1,106,1,106,3,106,1879,8,106,1,106,1,106,5,106,1883,8,106, + 10,106,12,106,1886,9,106,1,107,1,107,1,108,1,108,3,108,1892,8,108,1,108, + 1,108,3,108,1896,8,108,1,108,1,108,5,108,1900,8,108,10,108,12,108,1903, + 9,108,1,109,1,109,1,110,1,110,3,110,1909,8,110,1,110,1,110,3,110,1913, + 8,110,1,110,5,110,1916,8,110,10,110,12,110,1919,9,110,1,111,1,111,3,111, + 1923,8,111,5,111,1925,8,111,10,111,12,111,1928,9,111,1,111,1,111,3,111, + 1932,8,111,1,111,3,111,1935,8,111,1,112,1,112,1,112,4,112,1940,8,112, + 11,112,12,112,1941,1,112,3,112,1945,8,112,1,113,1,113,1,113,3,113,1950, + 8,113,1,113,1,113,1,113,1,113,1,113,1,113,1,113,3,113,1959,8,113,1,113, + 1,113,3,113,1963,8,113,1,113,3,113,1966,8,113,1,114,1,114,1,114,1,114, + 1,114,1,114,1,114,1,114,1,114,1,114,1,114,3,114,1979,8,114,1,114,3,114, + 1982,8,114,1,114,1,114,1,115,3,115,1987,8,115,1,115,1,115,1,116,1,116, + 1,116,1,116,1,116,1,116,1,116,1,116,1,116,1,116,3,116,2001,8,116,1,117, + 1,117,3,117,2005,8,117,1,117,5,117,2008,8,117,10,117,12,117,2011,9,117, + 1,118,1,118,1,118,1,118,1,118,1,118,1,118,1,118,1,118,3,118,2022,8,118, + 1,119,1,119,1,119,1,119,1,119,1,119,3,119,2030,8,119,1,120,1,120,1,121, + 1,121,3,121,2036,8,121,1,121,1,121,3,121,2040,8,121,1,121,1,121,3,121, + 2044,8,121,5,121,2046,8,121,10,121,12,121,2049,9,121,3,121,2051,8,121, + 1,121,1,121,1,122,1,122,3,122,2057,8,122,1,122,3,122,2060,8,122,1,123, + 1,123,3,123,2064,8,123,1,123,1,123,3,123,2068,8,123,1,123,1,123,3,123, + 2072,8,123,1,123,1,123,3,123,2076,8,123,5,123,2078,8,123,10,123,12,123, + 2081,9,123,1,123,1,123,1,124,1,124,3,124,2087,8,124,1,124,3,124,2090, + 8,124,1,124,1,124,3,124,2094,8,124,1,124,1,124,1,125,1,125,3,125,2100, + 8,125,1,125,1,125,3,125,2104,8,125,1,125,1,125,1,126,1,126,3,126,2110, + 8,126,1,126,1,126,3,126,2114,8,126,1,126,1,126,3,126,2118,8,126,1,126, + 1,126,1,126,3,126,2123,8,126,1,126,1,126,3,126,2127,8,126,1,126,1,126, + 3,126,2131,8,126,3,126,2133,8,126,1,126,1,126,3,126,2137,8,126,1,126, + 1,126,3,126,2141,8,126,1,126,1,126,3,126,2145,8,126,5,126,2147,8,126, + 10,126,12,126,2150,9,126,3,126,2152,8,126,1,126,1,126,3,126,2156,8,126, + 1,127,1,127,1,128,1,128,3,128,2162,8,128,1,128,1,128,1,128,3,128,2167, + 8,128,3,128,2169,8,128,1,128,1,128,1,129,1,129,3,129,2175,8,129,1,129, + 4,129,2178,8,129,11,129,12,129,2179,1,130,1,130,3,130,2184,8,130,1,130, + 1,130,3,130,2188,8,130,1,130,1,130,3,130,2192,8,130,1,130,1,130,3,130, + 2196,8,130,1,130,3,130,2199,8,130,1,130,3,130,2202,8,130,1,130,1,130, + 1,131,1,131,3,131,2208,8,131,1,131,1,131,3,131,2212,8,131,1,131,1,131, + 3,131,2216,8,131,1,131,1,131,3,131,2220,8,131,1,131,3,131,2223,8,131, + 1,131,3,131,2226,8,131,1,131,1,131,1,132,1,132,3,132,2232,8,132,1,132, + 1,132,3,132,2236,8,132,1,133,1,133,3,133,2240,8,133,1,133,4,133,2243, + 8,133,11,133,12,133,2244,1,133,1,133,3,133,2249,8,133,1,133,1,133,3,133, + 2253,8,133,1,133,4,133,2256,8,133,11,133,12,133,2257,3,133,2260,8,133, + 1,133,3,133,2263,8,133,1,133,1,133,3,133,2267,8,133,1,133,3,133,2270, + 8,133,1,133,3,133,2273,8,133,1,133,1,133,1,134,1,134,3,134,2279,8,134, + 1,134,1,134,3,134,2283,8,134,1,134,1,134,3,134,2287,8,134,1,134,1,134, + 1,135,1,135,1,136,1,136,3,136,2295,8,136,1,137,1,137,1,137,3,137,2300, + 8,137,1,138,1,138,3,138,2304,8,138,1,138,1,138,1,139,1,139,1,140,1,140, + 1,141,1,141,1,142,1,142,1,143,1,143,1,143,1,143,1,143,3,143,2321,8,143, + 1,144,1,144,1,145,1,145,1,146,1,146,1,147,1,147,1,147,0,1,72,148,0,2, 4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50, 52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96, 98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132, @@ -338,703 +342,710 @@ void cypherParserInitialize() { 170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204, 206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240, 242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276, - 278,280,282,284,286,288,0,11,2,0,57,57,59,59,1,0,104,107,2,0,5,5,12,16, - 1,0,18,19,2,0,20,20,115,115,2,0,21,22,98,98,1,0,124,125,7,0,47,47,53, - 56,67,67,71,71,118,118,126,126,130,130,2,0,13,13,27,30,2,0,15,15,31,34, - 2,0,35,45,115,115,2615,0,290,1,0,0,0,2,310,1,0,0,0,4,334,1,0,0,0,6,336, - 1,0,0,0,8,378,1,0,0,0,10,392,1,0,0,0,12,422,1,0,0,0,14,452,1,0,0,0,16, - 472,1,0,0,0,18,478,1,0,0,0,20,490,1,0,0,0,22,502,1,0,0,0,24,545,1,0,0, - 0,26,559,1,0,0,0,28,603,1,0,0,0,30,605,1,0,0,0,32,619,1,0,0,0,34,635, - 1,0,0,0,36,637,1,0,0,0,38,666,1,0,0,0,40,706,1,0,0,0,42,760,1,0,0,0,44, - 768,1,0,0,0,46,774,1,0,0,0,48,780,1,0,0,0,50,792,1,0,0,0,52,794,1,0,0, - 0,54,805,1,0,0,0,56,809,1,0,0,0,58,815,1,0,0,0,60,823,1,0,0,0,62,837, - 1,0,0,0,64,841,1,0,0,0,66,909,1,0,0,0,68,918,1,0,0,0,70,925,1,0,0,0,72, - 933,1,0,0,0,74,935,1,0,0,0,76,937,1,0,0,0,78,953,1,0,0,0,80,957,1,0,0, - 0,82,959,1,0,0,0,84,967,1,0,0,0,86,971,1,0,0,0,88,994,1,0,0,0,90,1008, - 1,0,0,0,92,1012,1,0,0,0,94,1059,1,0,0,0,96,1065,1,0,0,0,98,1077,1,0,0, - 0,100,1095,1,0,0,0,102,1101,1,0,0,0,104,1103,1,0,0,0,106,1151,1,0,0,0, - 108,1162,1,0,0,0,110,1175,1,0,0,0,112,1185,1,0,0,0,114,1191,1,0,0,0,116, - 1213,1,0,0,0,118,1215,1,0,0,0,120,1233,1,0,0,0,122,1245,1,0,0,0,124,1265, - 1,0,0,0,126,1273,1,0,0,0,128,1280,1,0,0,0,130,1324,1,0,0,0,132,1333,1, - 0,0,0,134,1335,1,0,0,0,136,1350,1,0,0,0,138,1354,1,0,0,0,140,1358,1,0, - 0,0,142,1365,1,0,0,0,144,1369,1,0,0,0,146,1394,1,0,0,0,148,1396,1,0,0, - 0,150,1412,1,0,0,0,152,1414,1,0,0,0,154,1438,1,0,0,0,156,1488,1,0,0,0, - 158,1490,1,0,0,0,160,1520,1,0,0,0,162,1561,1,0,0,0,164,1582,1,0,0,0,166, - 1592,1,0,0,0,168,1598,1,0,0,0,170,1633,1,0,0,0,172,1679,1,0,0,0,174,1691, - 1,0,0,0,176,1703,1,0,0,0,178,1705,1,0,0,0,180,1707,1,0,0,0,182,1709,1, - 0,0,0,184,1711,1,0,0,0,186,1713,1,0,0,0,188,1723,1,0,0,0,190,1733,1,0, - 0,0,192,1749,1,0,0,0,194,1802,1,0,0,0,196,1804,1,0,0,0,198,1806,1,0,0, - 0,200,1820,1,0,0,0,202,1834,1,0,0,0,204,1849,1,0,0,0,206,1851,1,0,0,0, - 208,1866,1,0,0,0,210,1868,1,0,0,0,212,1883,1,0,0,0,214,1885,1,0,0,0,216, - 1905,1,0,0,0,218,1915,1,0,0,0,220,1944,1,0,0,0,222,1957,1,0,0,0,224,1965, - 1,0,0,0,226,1979,1,0,0,0,228,1981,1,0,0,0,230,2000,1,0,0,0,232,2008,1, - 0,0,0,234,2010,1,0,0,0,236,2012,1,0,0,0,238,2033,1,0,0,0,240,2040,1,0, - 0,0,242,2065,1,0,0,0,244,2076,1,0,0,0,246,2134,1,0,0,0,248,2136,1,0,0, - 0,250,2147,1,0,0,0,252,2151,1,0,0,0,254,2160,1,0,0,0,256,2184,1,0,0,0, - 258,2208,1,0,0,0,260,2238,1,0,0,0,262,2255,1,0,0,0,264,2269,1,0,0,0,266, - 2273,1,0,0,0,268,2275,1,0,0,0,270,2280,1,0,0,0,272,2286,1,0,0,0,274,2288, - 1,0,0,0,276,2290,1,0,0,0,278,2292,1,0,0,0,280,2299,1,0,0,0,282,2301,1, - 0,0,0,284,2303,1,0,0,0,286,2305,1,0,0,0,288,2307,1,0,0,0,290,301,3,2, - 1,0,291,293,5,147,0,0,292,291,1,0,0,0,292,293,1,0,0,0,293,294,1,0,0,0, - 294,296,5,1,0,0,295,297,5,147,0,0,296,295,1,0,0,0,296,297,1,0,0,0,297, - 298,1,0,0,0,298,300,3,2,1,0,299,292,1,0,0,0,300,303,1,0,0,0,301,299,1, - 0,0,0,301,302,1,0,0,0,302,305,1,0,0,0,303,301,1,0,0,0,304,306,5,147,0, - 0,305,304,1,0,0,0,305,306,1,0,0,0,306,307,1,0,0,0,307,308,5,0,0,1,308, - 1,1,0,0,0,309,311,3,72,36,0,310,309,1,0,0,0,310,311,1,0,0,0,311,313,1, - 0,0,0,312,314,5,147,0,0,313,312,1,0,0,0,313,314,1,0,0,0,314,315,1,0,0, - 0,315,320,3,4,2,0,316,318,5,147,0,0,317,316,1,0,0,0,317,318,1,0,0,0,318, - 319,1,0,0,0,319,321,5,1,0,0,320,317,1,0,0,0,320,321,1,0,0,0,321,3,1,0, - 0,0,322,335,3,86,43,0,323,335,3,34,17,0,324,335,3,6,3,0,325,335,3,10, - 5,0,326,335,3,12,6,0,327,335,3,18,9,0,328,335,3,22,11,0,329,335,3,20, - 10,0,330,335,3,78,39,0,331,335,3,80,40,0,332,335,3,14,7,0,333,335,3,16, - 8,0,334,322,1,0,0,0,334,323,1,0,0,0,334,324,1,0,0,0,334,325,1,0,0,0,334, - 326,1,0,0,0,334,327,1,0,0,0,334,328,1,0,0,0,334,329,1,0,0,0,334,330,1, - 0,0,0,334,331,1,0,0,0,334,332,1,0,0,0,334,333,1,0,0,0,335,5,1,0,0,0,336, - 337,5,50,0,0,337,338,5,147,0,0,338,355,3,278,139,0,339,341,5,147,0,0, - 340,339,1,0,0,0,340,341,1,0,0,0,341,342,1,0,0,0,342,344,5,2,0,0,343,345, - 5,147,0,0,344,343,1,0,0,0,344,345,1,0,0,0,345,346,1,0,0,0,346,348,3,8, - 4,0,347,349,5,147,0,0,348,347,1,0,0,0,348,349,1,0,0,0,349,350,1,0,0,0, - 350,352,5,3,0,0,351,353,5,147,0,0,352,351,1,0,0,0,352,353,1,0,0,0,353, - 356,1,0,0,0,354,356,5,147,0,0,355,340,1,0,0,0,355,354,1,0,0,0,356,357, - 1,0,0,0,357,358,5,51,0,0,358,361,5,147,0,0,359,362,3,28,14,0,360,362, - 3,264,132,0,361,359,1,0,0,0,361,360,1,0,0,0,362,376,1,0,0,0,363,365,5, - 147,0,0,364,363,1,0,0,0,364,365,1,0,0,0,365,366,1,0,0,0,366,368,5,2,0, - 0,367,369,5,147,0,0,368,367,1,0,0,0,368,369,1,0,0,0,369,370,1,0,0,0,370, - 372,3,30,15,0,371,373,5,147,0,0,372,371,1,0,0,0,372,373,1,0,0,0,373,374, - 1,0,0,0,374,375,5,3,0,0,375,377,1,0,0,0,376,364,1,0,0,0,376,377,1,0,0, - 0,377,7,1,0,0,0,378,389,3,278,139,0,379,381,5,147,0,0,380,379,1,0,0,0, - 380,381,1,0,0,0,381,382,1,0,0,0,382,384,5,4,0,0,383,385,5,147,0,0,384, - 383,1,0,0,0,384,385,1,0,0,0,385,386,1,0,0,0,386,388,3,278,139,0,387,380, - 1,0,0,0,388,391,1,0,0,0,389,387,1,0,0,0,389,390,1,0,0,0,390,9,1,0,0,0, - 391,389,1,0,0,0,392,393,5,50,0,0,393,394,5,147,0,0,394,395,3,278,139, - 0,395,396,5,147,0,0,396,397,5,51,0,0,397,398,5,147,0,0,398,400,5,2,0, - 0,399,401,5,147,0,0,400,399,1,0,0,0,400,401,1,0,0,0,401,402,1,0,0,0,402, - 413,5,133,0,0,403,405,5,147,0,0,404,403,1,0,0,0,404,405,1,0,0,0,405,406, - 1,0,0,0,406,408,5,4,0,0,407,409,5,147,0,0,408,407,1,0,0,0,408,409,1,0, - 0,0,409,410,1,0,0,0,410,412,5,133,0,0,411,404,1,0,0,0,412,415,1,0,0,0, - 413,411,1,0,0,0,413,414,1,0,0,0,414,416,1,0,0,0,415,413,1,0,0,0,416,417, - 5,3,0,0,417,418,5,147,0,0,418,419,5,101,0,0,419,420,5,147,0,0,420,421, - 5,52,0,0,421,11,1,0,0,0,422,423,5,50,0,0,423,424,5,147,0,0,424,426,5, - 2,0,0,425,427,5,147,0,0,426,425,1,0,0,0,426,427,1,0,0,0,427,428,1,0,0, - 0,428,430,3,86,43,0,429,431,5,147,0,0,430,429,1,0,0,0,430,431,1,0,0,0, - 431,432,1,0,0,0,432,433,5,3,0,0,433,434,5,147,0,0,434,435,5,68,0,0,435, - 436,5,147,0,0,436,450,5,133,0,0,437,439,5,147,0,0,438,437,1,0,0,0,438, - 439,1,0,0,0,439,440,1,0,0,0,440,442,5,2,0,0,441,443,5,147,0,0,442,441, - 1,0,0,0,442,443,1,0,0,0,443,444,1,0,0,0,444,446,3,30,15,0,445,447,5,147, - 0,0,446,445,1,0,0,0,446,447,1,0,0,0,447,448,1,0,0,0,448,449,5,3,0,0,449, - 451,1,0,0,0,450,438,1,0,0,0,450,451,1,0,0,0,451,13,1,0,0,0,452,453,5, - 53,0,0,453,454,5,147,0,0,454,455,5,55,0,0,455,456,5,147,0,0,456,470,5, - 133,0,0,457,459,5,147,0,0,458,457,1,0,0,0,458,459,1,0,0,0,459,460,1,0, - 0,0,460,462,5,2,0,0,461,463,5,147,0,0,462,461,1,0,0,0,462,463,1,0,0,0, - 463,464,1,0,0,0,464,466,3,30,15,0,465,467,5,147,0,0,466,465,1,0,0,0,466, - 467,1,0,0,0,467,468,1,0,0,0,468,469,5,3,0,0,469,471,1,0,0,0,470,458,1, - 0,0,0,470,471,1,0,0,0,471,15,1,0,0,0,472,473,5,54,0,0,473,474,5,147,0, - 0,474,475,5,55,0,0,475,476,5,147,0,0,476,477,5,133,0,0,477,17,1,0,0,0, - 478,479,5,46,0,0,479,480,5,147,0,0,480,482,3,280,140,0,481,483,5,147, - 0,0,482,481,1,0,0,0,482,483,1,0,0,0,483,484,1,0,0,0,484,486,5,5,0,0,485, - 487,5,147,0,0,486,485,1,0,0,0,486,487,1,0,0,0,487,488,1,0,0,0,488,489, - 3,232,116,0,489,19,1,0,0,0,490,491,5,47,0,0,491,492,5,147,0,0,492,493, - 5,91,0,0,493,494,5,147,0,0,494,495,5,57,0,0,495,496,5,147,0,0,496,497, - 3,278,139,0,497,498,5,147,0,0,498,499,5,122,0,0,499,500,5,147,0,0,500, - 501,5,133,0,0,501,21,1,0,0,0,502,503,5,89,0,0,503,504,5,147,0,0,504,505, - 5,48,0,0,505,506,5,147,0,0,506,508,3,248,124,0,507,509,5,147,0,0,508, - 507,1,0,0,0,508,509,1,0,0,0,509,510,1,0,0,0,510,512,5,2,0,0,511,513,5, - 147,0,0,512,511,1,0,0,0,512,513,1,0,0,0,513,515,1,0,0,0,514,516,3,24, - 12,0,515,514,1,0,0,0,515,516,1,0,0,0,516,518,1,0,0,0,517,519,5,147,0, - 0,518,517,1,0,0,0,518,519,1,0,0,0,519,521,1,0,0,0,520,522,3,26,13,0,521, - 520,1,0,0,0,521,522,1,0,0,0,522,533,1,0,0,0,523,525,5,147,0,0,524,523, - 1,0,0,0,524,525,1,0,0,0,525,526,1,0,0,0,526,528,5,4,0,0,527,529,5,147, - 0,0,528,527,1,0,0,0,528,529,1,0,0,0,529,530,1,0,0,0,530,532,3,26,13,0, - 531,524,1,0,0,0,532,535,1,0,0,0,533,531,1,0,0,0,533,534,1,0,0,0,534,537, - 1,0,0,0,535,533,1,0,0,0,536,538,5,147,0,0,537,536,1,0,0,0,537,538,1,0, - 0,0,538,539,1,0,0,0,539,540,5,3,0,0,540,541,5,147,0,0,541,542,5,99,0, - 0,542,543,5,147,0,0,543,544,3,184,92,0,544,23,1,0,0,0,545,556,3,280,140, - 0,546,548,5,147,0,0,547,546,1,0,0,0,547,548,1,0,0,0,548,549,1,0,0,0,549, - 551,5,4,0,0,550,552,5,147,0,0,551,550,1,0,0,0,551,552,1,0,0,0,552,553, - 1,0,0,0,553,555,3,280,140,0,554,547,1,0,0,0,555,558,1,0,0,0,556,554,1, - 0,0,0,556,557,1,0,0,0,557,25,1,0,0,0,558,556,1,0,0,0,559,561,3,280,140, - 0,560,562,5,147,0,0,561,560,1,0,0,0,561,562,1,0,0,0,562,563,1,0,0,0,563, - 564,5,117,0,0,564,566,5,5,0,0,565,567,5,147,0,0,566,565,1,0,0,0,566,567, - 1,0,0,0,567,568,1,0,0,0,568,569,3,232,116,0,569,27,1,0,0,0,570,572,5, - 6,0,0,571,573,5,147,0,0,572,571,1,0,0,0,572,573,1,0,0,0,573,574,1,0,0, - 0,574,585,5,133,0,0,575,577,5,147,0,0,576,575,1,0,0,0,576,577,1,0,0,0, - 577,578,1,0,0,0,578,580,5,4,0,0,579,581,5,147,0,0,580,579,1,0,0,0,580, - 581,1,0,0,0,581,582,1,0,0,0,582,584,5,133,0,0,583,576,1,0,0,0,584,587, - 1,0,0,0,585,583,1,0,0,0,585,586,1,0,0,0,586,588,1,0,0,0,587,585,1,0,0, - 0,588,604,5,7,0,0,589,604,5,133,0,0,590,592,5,49,0,0,591,593,5,147,0, - 0,592,591,1,0,0,0,592,593,1,0,0,0,593,594,1,0,0,0,594,596,5,2,0,0,595, - 597,5,147,0,0,596,595,1,0,0,0,596,597,1,0,0,0,597,598,1,0,0,0,598,600, - 5,133,0,0,599,601,5,147,0,0,600,599,1,0,0,0,600,601,1,0,0,0,601,602,1, - 0,0,0,602,604,5,3,0,0,603,570,1,0,0,0,603,589,1,0,0,0,603,590,1,0,0,0, - 604,29,1,0,0,0,605,616,3,32,16,0,606,608,5,147,0,0,607,606,1,0,0,0,607, - 608,1,0,0,0,608,609,1,0,0,0,609,611,5,4,0,0,610,612,5,147,0,0,611,610, - 1,0,0,0,611,612,1,0,0,0,612,613,1,0,0,0,613,615,3,32,16,0,614,607,1,0, - 0,0,615,618,1,0,0,0,616,614,1,0,0,0,616,617,1,0,0,0,617,31,1,0,0,0,618, - 616,1,0,0,0,619,621,3,280,140,0,620,622,5,147,0,0,621,620,1,0,0,0,621, - 622,1,0,0,0,622,623,1,0,0,0,623,625,5,5,0,0,624,626,5,147,0,0,625,624, - 1,0,0,0,625,626,1,0,0,0,626,627,1,0,0,0,627,628,3,232,116,0,628,33,1, - 0,0,0,629,636,3,36,18,0,630,636,3,38,19,0,631,636,3,40,20,0,632,636,3, - 44,22,0,633,636,3,46,23,0,634,636,3,48,24,0,635,629,1,0,0,0,635,630,1, - 0,0,0,635,631,1,0,0,0,635,632,1,0,0,0,635,633,1,0,0,0,635,634,1,0,0,0, - 636,35,1,0,0,0,637,638,5,89,0,0,638,639,5,147,0,0,639,640,5,56,0,0,640, - 641,5,147,0,0,641,642,5,57,0,0,642,643,5,147,0,0,643,645,3,278,139,0, - 644,646,5,147,0,0,645,644,1,0,0,0,645,646,1,0,0,0,646,647,1,0,0,0,647, - 649,5,2,0,0,648,650,5,147,0,0,649,648,1,0,0,0,649,650,1,0,0,0,650,651, - 1,0,0,0,651,653,3,60,30,0,652,654,5,147,0,0,653,652,1,0,0,0,653,654,1, - 0,0,0,654,655,1,0,0,0,655,657,5,4,0,0,656,658,5,147,0,0,657,656,1,0,0, - 0,657,658,1,0,0,0,658,659,1,0,0,0,659,660,3,64,32,0,660,662,1,0,0,0,661, - 663,5,147,0,0,662,661,1,0,0,0,662,663,1,0,0,0,663,664,1,0,0,0,664,665, - 5,3,0,0,665,37,1,0,0,0,666,667,5,89,0,0,667,668,5,147,0,0,668,669,5,67, - 0,0,669,670,5,147,0,0,670,671,5,57,0,0,671,672,5,147,0,0,672,674,3,278, - 139,0,673,675,5,147,0,0,674,673,1,0,0,0,674,675,1,0,0,0,675,676,1,0,0, - 0,676,678,5,2,0,0,677,679,5,147,0,0,678,677,1,0,0,0,678,679,1,0,0,0,679, - 680,1,0,0,0,680,682,3,42,21,0,681,683,5,147,0,0,682,681,1,0,0,0,682,683, - 1,0,0,0,683,692,1,0,0,0,684,686,5,4,0,0,685,687,5,147,0,0,686,685,1,0, - 0,0,686,687,1,0,0,0,687,688,1,0,0,0,688,690,3,60,30,0,689,691,5,147,0, - 0,690,689,1,0,0,0,690,691,1,0,0,0,691,693,1,0,0,0,692,684,1,0,0,0,692, - 693,1,0,0,0,693,702,1,0,0,0,694,696,5,4,0,0,695,697,5,147,0,0,696,695, - 1,0,0,0,696,697,1,0,0,0,697,698,1,0,0,0,698,700,3,280,140,0,699,701,5, - 147,0,0,700,699,1,0,0,0,700,701,1,0,0,0,701,703,1,0,0,0,702,694,1,0,0, - 0,702,703,1,0,0,0,703,704,1,0,0,0,704,705,5,3,0,0,705,39,1,0,0,0,706, - 707,5,89,0,0,707,708,5,147,0,0,708,709,5,67,0,0,709,710,5,147,0,0,710, - 711,5,57,0,0,711,712,5,147,0,0,712,713,5,58,0,0,713,714,5,147,0,0,714, - 716,3,278,139,0,715,717,5,147,0,0,716,715,1,0,0,0,716,717,1,0,0,0,717, - 718,1,0,0,0,718,720,5,2,0,0,719,721,5,147,0,0,720,719,1,0,0,0,720,721, - 1,0,0,0,721,722,1,0,0,0,722,724,3,42,21,0,723,725,5,147,0,0,724,723,1, - 0,0,0,724,725,1,0,0,0,725,731,1,0,0,0,726,728,5,4,0,0,727,729,5,147,0, - 0,728,727,1,0,0,0,728,729,1,0,0,0,729,730,1,0,0,0,730,732,3,42,21,0,731, - 726,1,0,0,0,732,733,1,0,0,0,733,731,1,0,0,0,733,734,1,0,0,0,734,736,1, - 0,0,0,735,737,5,147,0,0,736,735,1,0,0,0,736,737,1,0,0,0,737,746,1,0,0, - 0,738,740,5,4,0,0,739,741,5,147,0,0,740,739,1,0,0,0,740,741,1,0,0,0,741, - 742,1,0,0,0,742,744,3,60,30,0,743,745,5,147,0,0,744,743,1,0,0,0,744,745, - 1,0,0,0,745,747,1,0,0,0,746,738,1,0,0,0,746,747,1,0,0,0,747,756,1,0,0, - 0,748,750,5,4,0,0,749,751,5,147,0,0,750,749,1,0,0,0,750,751,1,0,0,0,751, - 752,1,0,0,0,752,754,3,280,140,0,753,755,5,147,0,0,754,753,1,0,0,0,754, - 755,1,0,0,0,755,757,1,0,0,0,756,748,1,0,0,0,756,757,1,0,0,0,757,758,1, - 0,0,0,758,759,5,3,0,0,759,41,1,0,0,0,760,761,5,51,0,0,761,762,5,147,0, - 0,762,763,3,278,139,0,763,764,5,147,0,0,764,765,5,68,0,0,765,766,5,147, - 0,0,766,767,3,278,139,0,767,43,1,0,0,0,768,769,5,89,0,0,769,770,5,147, - 0,0,770,771,5,59,0,0,771,772,5,147,0,0,772,773,3,278,139,0,773,45,1,0, - 0,0,774,775,5,60,0,0,775,776,5,147,0,0,776,777,7,0,0,0,777,778,5,147, - 0,0,778,779,3,278,139,0,779,47,1,0,0,0,780,781,5,61,0,0,781,782,5,147, - 0,0,782,783,5,57,0,0,783,784,5,147,0,0,784,785,3,278,139,0,785,786,5, - 147,0,0,786,787,3,50,25,0,787,49,1,0,0,0,788,793,3,52,26,0,789,793,3, - 54,27,0,790,793,3,56,28,0,791,793,3,58,29,0,792,788,1,0,0,0,792,789,1, - 0,0,0,792,790,1,0,0,0,792,791,1,0,0,0,793,51,1,0,0,0,794,795,5,64,0,0, - 795,796,5,147,0,0,796,797,3,272,136,0,797,798,5,147,0,0,798,803,3,66, - 33,0,799,800,5,147,0,0,800,801,5,62,0,0,801,802,5,147,0,0,802,804,3,184, - 92,0,803,799,1,0,0,0,803,804,1,0,0,0,804,53,1,0,0,0,805,806,5,60,0,0, - 806,807,5,147,0,0,807,808,3,272,136,0,808,55,1,0,0,0,809,810,5,63,0,0, - 810,811,5,147,0,0,811,812,5,68,0,0,812,813,5,147,0,0,813,814,3,278,139, - 0,814,57,1,0,0,0,815,816,5,63,0,0,816,817,5,147,0,0,817,818,3,272,136, - 0,818,819,5,147,0,0,819,820,5,68,0,0,820,821,5,147,0,0,821,822,3,272, - 136,0,822,59,1,0,0,0,823,834,3,62,31,0,824,826,5,147,0,0,825,824,1,0, - 0,0,825,826,1,0,0,0,826,827,1,0,0,0,827,829,5,4,0,0,828,830,5,147,0,0, - 829,828,1,0,0,0,829,830,1,0,0,0,830,831,1,0,0,0,831,833,3,62,31,0,832, - 825,1,0,0,0,833,836,1,0,0,0,834,832,1,0,0,0,834,835,1,0,0,0,835,61,1, - 0,0,0,836,834,1,0,0,0,837,838,3,272,136,0,838,839,5,147,0,0,839,840,3, - 66,33,0,840,63,1,0,0,0,841,842,5,65,0,0,842,843,5,147,0,0,843,845,5,66, - 0,0,844,846,5,147,0,0,845,844,1,0,0,0,845,846,1,0,0,0,846,847,1,0,0,0, - 847,849,5,2,0,0,848,850,5,147,0,0,849,848,1,0,0,0,849,850,1,0,0,0,850, - 851,1,0,0,0,851,853,3,272,136,0,852,854,5,147,0,0,853,852,1,0,0,0,853, - 854,1,0,0,0,854,855,1,0,0,0,855,856,5,3,0,0,856,65,1,0,0,0,857,858,6, - 33,-1,0,858,910,3,280,140,0,859,861,5,82,0,0,860,862,5,147,0,0,861,860, - 1,0,0,0,861,862,1,0,0,0,862,863,1,0,0,0,863,865,5,2,0,0,864,866,5,147, - 0,0,865,864,1,0,0,0,865,866,1,0,0,0,866,867,1,0,0,0,867,869,3,60,30,0, - 868,870,5,147,0,0,869,868,1,0,0,0,869,870,1,0,0,0,870,871,1,0,0,0,871, - 872,5,3,0,0,872,910,1,0,0,0,873,875,3,280,140,0,874,876,5,147,0,0,875, - 874,1,0,0,0,875,876,1,0,0,0,876,877,1,0,0,0,877,879,5,2,0,0,878,880,5, - 147,0,0,879,878,1,0,0,0,879,880,1,0,0,0,880,881,1,0,0,0,881,883,3,60, - 30,0,882,884,5,147,0,0,883,882,1,0,0,0,883,884,1,0,0,0,884,885,1,0,0, - 0,885,886,5,3,0,0,886,910,1,0,0,0,887,889,3,280,140,0,888,890,5,147,0, - 0,889,888,1,0,0,0,889,890,1,0,0,0,890,891,1,0,0,0,891,893,5,2,0,0,892, - 894,5,147,0,0,893,892,1,0,0,0,893,894,1,0,0,0,894,895,1,0,0,0,895,897, - 3,66,33,0,896,898,5,147,0,0,897,896,1,0,0,0,897,898,1,0,0,0,898,899,1, - 0,0,0,899,901,5,4,0,0,900,902,5,147,0,0,901,900,1,0,0,0,901,902,1,0,0, - 0,902,903,1,0,0,0,903,905,3,66,33,0,904,906,5,147,0,0,905,904,1,0,0,0, - 905,906,1,0,0,0,906,907,1,0,0,0,907,908,5,3,0,0,908,910,1,0,0,0,909,857, - 1,0,0,0,909,859,1,0,0,0,909,873,1,0,0,0,909,887,1,0,0,0,910,915,1,0,0, - 0,911,912,10,4,0,0,912,914,3,68,34,0,913,911,1,0,0,0,914,917,1,0,0,0, - 915,913,1,0,0,0,915,916,1,0,0,0,916,67,1,0,0,0,917,915,1,0,0,0,918,922, - 3,70,35,0,919,921,3,70,35,0,920,919,1,0,0,0,921,924,1,0,0,0,922,920,1, - 0,0,0,922,923,1,0,0,0,923,69,1,0,0,0,924,922,1,0,0,0,925,927,5,6,0,0, - 926,928,3,274,137,0,927,926,1,0,0,0,927,928,1,0,0,0,928,929,1,0,0,0,929, - 930,5,7,0,0,930,71,1,0,0,0,931,934,3,74,37,0,932,934,3,76,38,0,933,931, - 1,0,0,0,933,932,1,0,0,0,934,73,1,0,0,0,935,936,5,69,0,0,936,75,1,0,0, - 0,937,938,5,70,0,0,938,77,1,0,0,0,939,940,5,71,0,0,940,941,5,147,0,0, - 941,954,5,72,0,0,942,943,5,71,0,0,943,944,5,147,0,0,944,945,5,72,0,0, - 945,946,5,147,0,0,946,947,5,73,0,0,947,948,5,147,0,0,948,954,5,74,0,0, - 949,954,5,76,0,0,950,954,5,77,0,0,951,954,5,78,0,0,952,954,5,79,0,0,953, - 939,1,0,0,0,953,942,1,0,0,0,953,949,1,0,0,0,953,950,1,0,0,0,953,951,1, - 0,0,0,953,952,1,0,0,0,954,79,1,0,0,0,955,958,3,82,41,0,956,958,3,84,42, - 0,957,955,1,0,0,0,957,956,1,0,0,0,958,81,1,0,0,0,959,960,5,84,0,0,960, - 961,5,147,0,0,961,962,5,81,0,0,962,965,5,147,0,0,963,966,5,133,0,0,964, - 966,3,264,132,0,965,963,1,0,0,0,965,964,1,0,0,0,966,83,1,0,0,0,967,968, - 5,80,0,0,968,969,5,147,0,0,969,970,3,264,132,0,970,85,1,0,0,0,971,972, - 3,88,44,0,972,87,1,0,0,0,973,980,3,92,46,0,974,976,5,147,0,0,975,974, - 1,0,0,0,975,976,1,0,0,0,976,977,1,0,0,0,977,979,3,90,45,0,978,975,1,0, - 0,0,979,982,1,0,0,0,980,978,1,0,0,0,980,981,1,0,0,0,981,995,1,0,0,0,982, - 980,1,0,0,0,983,985,3,126,63,0,984,986,5,147,0,0,985,984,1,0,0,0,985, - 986,1,0,0,0,986,988,1,0,0,0,987,983,1,0,0,0,988,989,1,0,0,0,989,987,1, - 0,0,0,989,990,1,0,0,0,990,991,1,0,0,0,991,992,3,92,46,0,992,993,6,44, - -1,0,993,995,1,0,0,0,994,973,1,0,0,0,994,987,1,0,0,0,995,89,1,0,0,0,996, - 997,5,82,0,0,997,998,5,147,0,0,998,1000,5,83,0,0,999,1001,5,147,0,0,1000, - 999,1,0,0,0,1000,1001,1,0,0,0,1001,1002,1,0,0,0,1002,1009,3,92,46,0,1003, - 1005,5,82,0,0,1004,1006,5,147,0,0,1005,1004,1,0,0,0,1005,1006,1,0,0,0, - 1006,1007,1,0,0,0,1007,1009,3,92,46,0,1008,996,1,0,0,0,1008,1003,1,0, - 0,0,1009,91,1,0,0,0,1010,1013,3,94,47,0,1011,1013,3,96,48,0,1012,1010, - 1,0,0,0,1012,1011,1,0,0,0,1013,93,1,0,0,0,1014,1016,3,102,51,0,1015,1017, - 5,147,0,0,1016,1015,1,0,0,0,1016,1017,1,0,0,0,1017,1019,1,0,0,0,1018, - 1014,1,0,0,0,1019,1022,1,0,0,0,1020,1018,1,0,0,0,1020,1021,1,0,0,0,1021, - 1023,1,0,0,0,1022,1020,1,0,0,0,1023,1060,3,126,63,0,1024,1026,3,102,51, - 0,1025,1027,5,147,0,0,1026,1025,1,0,0,0,1026,1027,1,0,0,0,1027,1029,1, - 0,0,0,1028,1024,1,0,0,0,1029,1032,1,0,0,0,1030,1028,1,0,0,0,1030,1031, - 1,0,0,0,1031,1033,1,0,0,0,1032,1030,1,0,0,0,1033,1040,3,100,50,0,1034, - 1036,5,147,0,0,1035,1034,1,0,0,0,1035,1036,1,0,0,0,1036,1037,1,0,0,0, - 1037,1039,3,100,50,0,1038,1035,1,0,0,0,1039,1042,1,0,0,0,1040,1038,1, - 0,0,0,1040,1041,1,0,0,0,1041,1047,1,0,0,0,1042,1040,1,0,0,0,1043,1045, - 5,147,0,0,1044,1043,1,0,0,0,1044,1045,1,0,0,0,1045,1046,1,0,0,0,1046, - 1048,3,126,63,0,1047,1044,1,0,0,0,1047,1048,1,0,0,0,1048,1060,1,0,0,0, - 1049,1051,3,102,51,0,1050,1052,5,147,0,0,1051,1050,1,0,0,0,1051,1052, - 1,0,0,0,1052,1054,1,0,0,0,1053,1049,1,0,0,0,1054,1055,1,0,0,0,1055,1053, - 1,0,0,0,1055,1056,1,0,0,0,1056,1057,1,0,0,0,1057,1058,6,47,-1,0,1058, - 1060,1,0,0,0,1059,1020,1,0,0,0,1059,1030,1,0,0,0,1059,1053,1,0,0,0,1060, - 95,1,0,0,0,1061,1063,3,98,49,0,1062,1064,5,147,0,0,1063,1062,1,0,0,0, - 1063,1064,1,0,0,0,1064,1066,1,0,0,0,1065,1061,1,0,0,0,1066,1067,1,0,0, - 0,1067,1065,1,0,0,0,1067,1068,1,0,0,0,1068,1069,1,0,0,0,1069,1070,3,94, - 47,0,1070,97,1,0,0,0,1071,1073,3,102,51,0,1072,1074,5,147,0,0,1073,1072, - 1,0,0,0,1073,1074,1,0,0,0,1074,1076,1,0,0,0,1075,1071,1,0,0,0,1076,1079, - 1,0,0,0,1077,1075,1,0,0,0,1077,1078,1,0,0,0,1078,1086,1,0,0,0,1079,1077, - 1,0,0,0,1080,1082,3,100,50,0,1081,1083,5,147,0,0,1082,1081,1,0,0,0,1082, - 1083,1,0,0,0,1083,1085,1,0,0,0,1084,1080,1,0,0,0,1085,1088,1,0,0,0,1086, - 1084,1,0,0,0,1086,1087,1,0,0,0,1087,1089,1,0,0,0,1088,1086,1,0,0,0,1089, - 1090,3,124,62,0,1090,99,1,0,0,0,1091,1096,3,112,56,0,1092,1096,3,114, - 57,0,1093,1096,3,118,59,0,1094,1096,3,122,61,0,1095,1091,1,0,0,0,1095, - 1092,1,0,0,0,1095,1093,1,0,0,0,1095,1094,1,0,0,0,1096,101,1,0,0,0,1097, - 1102,3,108,54,0,1098,1102,3,110,55,0,1099,1102,3,106,53,0,1100,1102,3, - 104,52,0,1101,1097,1,0,0,0,1101,1098,1,0,0,0,1101,1099,1,0,0,0,1101,1100, - 1,0,0,0,1102,103,1,0,0,0,1103,1121,5,84,0,0,1104,1105,5,147,0,0,1105, - 1106,5,95,0,0,1106,1107,5,147,0,0,1107,1109,5,85,0,0,1108,1110,5,147, - 0,0,1109,1108,1,0,0,0,1109,1110,1,0,0,0,1110,1111,1,0,0,0,1111,1113,5, - 2,0,0,1112,1114,5,147,0,0,1113,1112,1,0,0,0,1113,1114,1,0,0,0,1114,1115, - 1,0,0,0,1115,1117,3,60,30,0,1116,1118,5,147,0,0,1117,1116,1,0,0,0,1117, - 1118,1,0,0,0,1118,1119,1,0,0,0,1119,1120,5,3,0,0,1120,1122,1,0,0,0,1121, - 1104,1,0,0,0,1121,1122,1,0,0,0,1122,1123,1,0,0,0,1123,1124,5,147,0,0, - 1124,1125,5,51,0,0,1125,1143,5,147,0,0,1126,1140,3,28,14,0,1127,1129, - 5,147,0,0,1128,1127,1,0,0,0,1128,1129,1,0,0,0,1129,1130,1,0,0,0,1130, - 1132,5,2,0,0,1131,1133,5,147,0,0,1132,1131,1,0,0,0,1132,1133,1,0,0,0, - 1133,1134,1,0,0,0,1134,1136,3,30,15,0,1135,1137,5,147,0,0,1136,1135,1, - 0,0,0,1136,1137,1,0,0,0,1137,1138,1,0,0,0,1138,1139,5,3,0,0,1139,1141, - 1,0,0,0,1140,1128,1,0,0,0,1140,1141,1,0,0,0,1141,1144,1,0,0,0,1142,1144, - 3,264,132,0,1143,1126,1,0,0,0,1143,1142,1,0,0,0,1144,1149,1,0,0,0,1145, - 1147,5,147,0,0,1146,1145,1,0,0,0,1146,1147,1,0,0,0,1147,1148,1,0,0,0, - 1148,1150,3,142,71,0,1149,1146,1,0,0,0,1149,1150,1,0,0,0,1150,105,1,0, - 0,0,1151,1152,5,46,0,0,1152,1153,5,147,0,0,1153,1158,3,246,123,0,1154, - 1156,5,147,0,0,1155,1154,1,0,0,0,1155,1156,1,0,0,0,1156,1157,1,0,0,0, - 1157,1159,3,142,71,0,1158,1155,1,0,0,0,1158,1159,1,0,0,0,1159,107,1,0, - 0,0,1160,1161,5,86,0,0,1161,1163,5,147,0,0,1162,1160,1,0,0,0,1162,1163, - 1,0,0,0,1163,1164,1,0,0,0,1164,1166,5,87,0,0,1165,1167,5,147,0,0,1166, - 1165,1,0,0,0,1166,1167,1,0,0,0,1167,1168,1,0,0,0,1168,1173,3,144,72,0, - 1169,1171,5,147,0,0,1170,1169,1,0,0,0,1170,1171,1,0,0,0,1171,1172,1,0, - 0,0,1172,1174,3,142,71,0,1173,1170,1,0,0,0,1173,1174,1,0,0,0,1174,109, - 1,0,0,0,1175,1177,5,88,0,0,1176,1178,5,147,0,0,1177,1176,1,0,0,0,1177, - 1178,1,0,0,0,1178,1179,1,0,0,0,1179,1180,3,184,92,0,1180,1181,5,147,0, - 0,1181,1182,5,99,0,0,1182,1183,5,147,0,0,1183,1184,3,264,132,0,1184,111, - 1,0,0,0,1185,1187,5,89,0,0,1186,1188,5,147,0,0,1187,1186,1,0,0,0,1187, - 1188,1,0,0,0,1188,1189,1,0,0,0,1189,1190,3,144,72,0,1190,113,1,0,0,0, - 1191,1193,5,90,0,0,1192,1194,5,147,0,0,1193,1192,1,0,0,0,1193,1194,1, - 0,0,0,1194,1195,1,0,0,0,1195,1200,3,144,72,0,1196,1197,5,147,0,0,1197, - 1199,3,116,58,0,1198,1196,1,0,0,0,1199,1202,1,0,0,0,1200,1198,1,0,0,0, - 1200,1201,1,0,0,0,1201,115,1,0,0,0,1202,1200,1,0,0,0,1203,1204,5,91,0, - 0,1204,1205,5,147,0,0,1205,1206,5,87,0,0,1206,1207,5,147,0,0,1207,1214, - 3,118,59,0,1208,1209,5,91,0,0,1209,1210,5,147,0,0,1210,1211,5,89,0,0, - 1211,1212,5,147,0,0,1212,1214,3,118,59,0,1213,1203,1,0,0,0,1213,1208, - 1,0,0,0,1214,117,1,0,0,0,1215,1217,5,92,0,0,1216,1218,5,147,0,0,1217, - 1216,1,0,0,0,1217,1218,1,0,0,0,1218,1219,1,0,0,0,1219,1230,3,120,60,0, - 1220,1222,5,147,0,0,1221,1220,1,0,0,0,1221,1222,1,0,0,0,1222,1223,1,0, - 0,0,1223,1225,5,4,0,0,1224,1226,5,147,0,0,1225,1224,1,0,0,0,1225,1226, - 1,0,0,0,1226,1227,1,0,0,0,1227,1229,3,120,60,0,1228,1221,1,0,0,0,1229, - 1232,1,0,0,0,1230,1228,1,0,0,0,1230,1231,1,0,0,0,1231,119,1,0,0,0,1232, - 1230,1,0,0,0,1233,1235,3,270,135,0,1234,1236,5,147,0,0,1235,1234,1,0, - 0,0,1235,1236,1,0,0,0,1236,1237,1,0,0,0,1237,1239,5,5,0,0,1238,1240,5, - 147,0,0,1239,1238,1,0,0,0,1239,1240,1,0,0,0,1240,1241,1,0,0,0,1241,1242, - 3,184,92,0,1242,121,1,0,0,0,1243,1244,5,93,0,0,1244,1246,5,147,0,0,1245, - 1243,1,0,0,0,1245,1246,1,0,0,0,1246,1247,1,0,0,0,1247,1249,5,94,0,0,1248, - 1250,5,147,0,0,1249,1248,1,0,0,0,1249,1250,1,0,0,0,1250,1251,1,0,0,0, - 1251,1262,3,184,92,0,1252,1254,5,147,0,0,1253,1252,1,0,0,0,1253,1254, - 1,0,0,0,1254,1255,1,0,0,0,1255,1257,5,4,0,0,1256,1258,5,147,0,0,1257, - 1256,1,0,0,0,1257,1258,1,0,0,0,1258,1259,1,0,0,0,1259,1261,3,184,92,0, - 1260,1253,1,0,0,0,1261,1264,1,0,0,0,1262,1260,1,0,0,0,1262,1263,1,0,0, - 0,1263,123,1,0,0,0,1264,1262,1,0,0,0,1265,1266,5,95,0,0,1266,1271,3,128, - 64,0,1267,1269,5,147,0,0,1268,1267,1,0,0,0,1268,1269,1,0,0,0,1269,1270, - 1,0,0,0,1270,1272,3,142,71,0,1271,1268,1,0,0,0,1271,1272,1,0,0,0,1272, - 125,1,0,0,0,1273,1274,5,96,0,0,1274,1275,3,128,64,0,1275,127,1,0,0,0, - 1276,1278,5,147,0,0,1277,1276,1,0,0,0,1277,1278,1,0,0,0,1278,1279,1,0, - 0,0,1279,1281,5,97,0,0,1280,1277,1,0,0,0,1280,1281,1,0,0,0,1281,1282, - 1,0,0,0,1282,1283,5,147,0,0,1283,1286,3,130,65,0,1284,1285,5,147,0,0, - 1285,1287,3,134,67,0,1286,1284,1,0,0,0,1286,1287,1,0,0,0,1287,1290,1, - 0,0,0,1288,1289,5,147,0,0,1289,1291,3,136,68,0,1290,1288,1,0,0,0,1290, - 1291,1,0,0,0,1291,1294,1,0,0,0,1292,1293,5,147,0,0,1293,1295,3,138,69, - 0,1294,1292,1,0,0,0,1294,1295,1,0,0,0,1295,129,1,0,0,0,1296,1307,5,98, - 0,0,1297,1299,5,147,0,0,1298,1297,1,0,0,0,1298,1299,1,0,0,0,1299,1300, - 1,0,0,0,1300,1302,5,4,0,0,1301,1303,5,147,0,0,1302,1301,1,0,0,0,1302, - 1303,1,0,0,0,1303,1304,1,0,0,0,1304,1306,3,132,66,0,1305,1298,1,0,0,0, - 1306,1309,1,0,0,0,1307,1305,1,0,0,0,1307,1308,1,0,0,0,1308,1325,1,0,0, - 0,1309,1307,1,0,0,0,1310,1321,3,132,66,0,1311,1313,5,147,0,0,1312,1311, - 1,0,0,0,1312,1313,1,0,0,0,1313,1314,1,0,0,0,1314,1316,5,4,0,0,1315,1317, - 5,147,0,0,1316,1315,1,0,0,0,1316,1317,1,0,0,0,1317,1318,1,0,0,0,1318, - 1320,3,132,66,0,1319,1312,1,0,0,0,1320,1323,1,0,0,0,1321,1319,1,0,0,0, - 1321,1322,1,0,0,0,1322,1325,1,0,0,0,1323,1321,1,0,0,0,1324,1296,1,0,0, - 0,1324,1310,1,0,0,0,1325,131,1,0,0,0,1326,1327,3,184,92,0,1327,1328,5, - 147,0,0,1328,1329,5,99,0,0,1329,1330,5,147,0,0,1330,1331,3,264,132,0, - 1331,1334,1,0,0,0,1332,1334,3,184,92,0,1333,1326,1,0,0,0,1333,1332,1, - 0,0,0,1334,133,1,0,0,0,1335,1336,5,100,0,0,1336,1337,5,147,0,0,1337,1338, - 5,101,0,0,1338,1339,5,147,0,0,1339,1347,3,140,70,0,1340,1342,5,4,0,0, - 1341,1343,5,147,0,0,1342,1341,1,0,0,0,1342,1343,1,0,0,0,1343,1344,1,0, - 0,0,1344,1346,3,140,70,0,1345,1340,1,0,0,0,1346,1349,1,0,0,0,1347,1345, - 1,0,0,0,1347,1348,1,0,0,0,1348,135,1,0,0,0,1349,1347,1,0,0,0,1350,1351, - 5,102,0,0,1351,1352,5,147,0,0,1352,1353,3,184,92,0,1353,137,1,0,0,0,1354, - 1355,5,103,0,0,1355,1356,5,147,0,0,1356,1357,3,184,92,0,1357,139,1,0, - 0,0,1358,1363,3,184,92,0,1359,1361,5,147,0,0,1360,1359,1,0,0,0,1360,1361, - 1,0,0,0,1361,1362,1,0,0,0,1362,1364,7,1,0,0,1363,1360,1,0,0,0,1363,1364, - 1,0,0,0,1364,141,1,0,0,0,1365,1366,5,108,0,0,1366,1367,5,147,0,0,1367, - 1368,3,184,92,0,1368,143,1,0,0,0,1369,1380,3,146,73,0,1370,1372,5,147, - 0,0,1371,1370,1,0,0,0,1371,1372,1,0,0,0,1372,1373,1,0,0,0,1373,1375,5, - 4,0,0,1374,1376,5,147,0,0,1375,1374,1,0,0,0,1375,1376,1,0,0,0,1376,1377, - 1,0,0,0,1377,1379,3,146,73,0,1378,1371,1,0,0,0,1379,1382,1,0,0,0,1380, - 1378,1,0,0,0,1380,1381,1,0,0,0,1381,145,1,0,0,0,1382,1380,1,0,0,0,1383, - 1385,3,264,132,0,1384,1386,5,147,0,0,1385,1384,1,0,0,0,1385,1386,1,0, - 0,0,1386,1387,1,0,0,0,1387,1389,5,5,0,0,1388,1390,5,147,0,0,1389,1388, - 1,0,0,0,1389,1390,1,0,0,0,1390,1391,1,0,0,0,1391,1392,3,148,74,0,1392, - 1395,1,0,0,0,1393,1395,3,148,74,0,1394,1383,1,0,0,0,1394,1393,1,0,0,0, - 1395,147,1,0,0,0,1396,1397,3,150,75,0,1397,149,1,0,0,0,1398,1405,3,152, - 76,0,1399,1401,5,147,0,0,1400,1399,1,0,0,0,1400,1401,1,0,0,0,1401,1402, - 1,0,0,0,1402,1404,3,154,77,0,1403,1400,1,0,0,0,1404,1407,1,0,0,0,1405, - 1403,1,0,0,0,1405,1406,1,0,0,0,1406,1413,1,0,0,0,1407,1405,1,0,0,0,1408, - 1409,5,2,0,0,1409,1410,3,150,75,0,1410,1411,5,3,0,0,1411,1413,1,0,0,0, - 1412,1398,1,0,0,0,1412,1408,1,0,0,0,1413,151,1,0,0,0,1414,1416,5,2,0, - 0,1415,1417,5,147,0,0,1416,1415,1,0,0,0,1416,1417,1,0,0,0,1417,1422,1, - 0,0,0,1418,1420,3,264,132,0,1419,1421,5,147,0,0,1420,1419,1,0,0,0,1420, - 1421,1,0,0,0,1421,1423,1,0,0,0,1422,1418,1,0,0,0,1422,1423,1,0,0,0,1423, - 1428,1,0,0,0,1424,1426,3,164,82,0,1425,1427,5,147,0,0,1426,1425,1,0,0, - 0,1426,1427,1,0,0,0,1427,1429,1,0,0,0,1428,1424,1,0,0,0,1428,1429,1,0, - 0,0,1429,1434,1,0,0,0,1430,1432,3,160,80,0,1431,1433,5,147,0,0,1432,1431, - 1,0,0,0,1432,1433,1,0,0,0,1433,1435,1,0,0,0,1434,1430,1,0,0,0,1434,1435, - 1,0,0,0,1435,1436,1,0,0,0,1436,1437,5,3,0,0,1437,153,1,0,0,0,1438,1440, - 3,156,78,0,1439,1441,5,147,0,0,1440,1439,1,0,0,0,1440,1441,1,0,0,0,1441, - 1442,1,0,0,0,1442,1443,3,152,76,0,1443,155,1,0,0,0,1444,1446,3,284,142, - 0,1445,1447,5,147,0,0,1446,1445,1,0,0,0,1446,1447,1,0,0,0,1447,1448,1, - 0,0,0,1448,1450,3,288,144,0,1449,1451,5,147,0,0,1450,1449,1,0,0,0,1450, - 1451,1,0,0,0,1451,1453,1,0,0,0,1452,1454,3,158,79,0,1453,1452,1,0,0,0, - 1453,1454,1,0,0,0,1454,1456,1,0,0,0,1455,1457,5,147,0,0,1456,1455,1,0, - 0,0,1456,1457,1,0,0,0,1457,1458,1,0,0,0,1458,1459,3,288,144,0,1459,1489, - 1,0,0,0,1460,1462,3,288,144,0,1461,1463,5,147,0,0,1462,1461,1,0,0,0,1462, - 1463,1,0,0,0,1463,1465,1,0,0,0,1464,1466,3,158,79,0,1465,1464,1,0,0,0, - 1465,1466,1,0,0,0,1466,1468,1,0,0,0,1467,1469,5,147,0,0,1468,1467,1,0, - 0,0,1468,1469,1,0,0,0,1469,1470,1,0,0,0,1470,1472,3,288,144,0,1471,1473, - 5,147,0,0,1472,1471,1,0,0,0,1472,1473,1,0,0,0,1473,1474,1,0,0,0,1474, - 1475,3,286,143,0,1475,1489,1,0,0,0,1476,1478,3,288,144,0,1477,1479,5, - 147,0,0,1478,1477,1,0,0,0,1478,1479,1,0,0,0,1479,1481,1,0,0,0,1480,1482, - 3,158,79,0,1481,1480,1,0,0,0,1481,1482,1,0,0,0,1482,1484,1,0,0,0,1483, - 1485,5,147,0,0,1484,1483,1,0,0,0,1484,1485,1,0,0,0,1485,1486,1,0,0,0, - 1486,1487,3,288,144,0,1487,1489,1,0,0,0,1488,1444,1,0,0,0,1488,1460,1, - 0,0,0,1488,1476,1,0,0,0,1489,157,1,0,0,0,1490,1492,5,6,0,0,1491,1493, - 5,147,0,0,1492,1491,1,0,0,0,1492,1493,1,0,0,0,1493,1498,1,0,0,0,1494, - 1496,3,264,132,0,1495,1497,5,147,0,0,1496,1495,1,0,0,0,1496,1497,1,0, - 0,0,1497,1499,1,0,0,0,1498,1494,1,0,0,0,1498,1499,1,0,0,0,1499,1504,1, - 0,0,0,1500,1502,3,162,81,0,1501,1503,5,147,0,0,1502,1501,1,0,0,0,1502, - 1503,1,0,0,0,1503,1505,1,0,0,0,1504,1500,1,0,0,0,1504,1505,1,0,0,0,1505, - 1510,1,0,0,0,1506,1508,3,168,84,0,1507,1509,5,147,0,0,1508,1507,1,0,0, - 0,1508,1509,1,0,0,0,1509,1511,1,0,0,0,1510,1506,1,0,0,0,1510,1511,1,0, - 0,0,1511,1516,1,0,0,0,1512,1514,3,160,80,0,1513,1515,5,147,0,0,1514,1513, - 1,0,0,0,1514,1515,1,0,0,0,1515,1517,1,0,0,0,1516,1512,1,0,0,0,1516,1517, - 1,0,0,0,1517,1518,1,0,0,0,1518,1519,5,7,0,0,1519,159,1,0,0,0,1520,1522, - 5,8,0,0,1521,1523,5,147,0,0,1522,1521,1,0,0,0,1522,1523,1,0,0,0,1523, - 1557,1,0,0,0,1524,1526,3,272,136,0,1525,1527,5,147,0,0,1526,1525,1,0, - 0,0,1526,1527,1,0,0,0,1527,1528,1,0,0,0,1528,1530,5,117,0,0,1529,1531, - 5,147,0,0,1530,1529,1,0,0,0,1530,1531,1,0,0,0,1531,1532,1,0,0,0,1532, - 1534,3,184,92,0,1533,1535,5,147,0,0,1534,1533,1,0,0,0,1534,1535,1,0,0, - 0,1535,1554,1,0,0,0,1536,1538,5,4,0,0,1537,1539,5,147,0,0,1538,1537,1, - 0,0,0,1538,1539,1,0,0,0,1539,1540,1,0,0,0,1540,1542,3,272,136,0,1541, - 1543,5,147,0,0,1542,1541,1,0,0,0,1542,1543,1,0,0,0,1543,1544,1,0,0,0, - 1544,1546,5,117,0,0,1545,1547,5,147,0,0,1546,1545,1,0,0,0,1546,1547,1, - 0,0,0,1547,1548,1,0,0,0,1548,1550,3,184,92,0,1549,1551,5,147,0,0,1550, - 1549,1,0,0,0,1550,1551,1,0,0,0,1551,1553,1,0,0,0,1552,1536,1,0,0,0,1553, - 1556,1,0,0,0,1554,1552,1,0,0,0,1554,1555,1,0,0,0,1555,1558,1,0,0,0,1556, - 1554,1,0,0,0,1557,1524,1,0,0,0,1557,1558,1,0,0,0,1558,1559,1,0,0,0,1559, - 1560,5,9,0,0,1560,161,1,0,0,0,1561,1563,5,117,0,0,1562,1564,5,147,0,0, - 1563,1562,1,0,0,0,1563,1564,1,0,0,0,1564,1565,1,0,0,0,1565,1579,3,182, - 91,0,1566,1568,5,147,0,0,1567,1566,1,0,0,0,1567,1568,1,0,0,0,1568,1569, - 1,0,0,0,1569,1571,5,10,0,0,1570,1572,5,117,0,0,1571,1570,1,0,0,0,1571, - 1572,1,0,0,0,1572,1574,1,0,0,0,1573,1575,5,147,0,0,1574,1573,1,0,0,0, - 1574,1575,1,0,0,0,1575,1576,1,0,0,0,1576,1578,3,182,91,0,1577,1567,1, - 0,0,0,1578,1581,1,0,0,0,1579,1577,1,0,0,0,1579,1580,1,0,0,0,1580,163, - 1,0,0,0,1581,1579,1,0,0,0,1582,1589,3,166,83,0,1583,1585,5,147,0,0,1584, - 1583,1,0,0,0,1584,1585,1,0,0,0,1585,1586,1,0,0,0,1586,1588,3,166,83,0, - 1587,1584,1,0,0,0,1588,1591,1,0,0,0,1589,1587,1,0,0,0,1589,1590,1,0,0, - 0,1590,165,1,0,0,0,1591,1589,1,0,0,0,1592,1594,5,117,0,0,1593,1595,5, - 147,0,0,1594,1593,1,0,0,0,1594,1595,1,0,0,0,1595,1596,1,0,0,0,1596,1597, - 3,180,90,0,1597,167,1,0,0,0,1598,1600,5,98,0,0,1599,1601,5,147,0,0,1600, - 1599,1,0,0,0,1600,1601,1,0,0,0,1601,1606,1,0,0,0,1602,1607,5,109,0,0, - 1603,1604,5,83,0,0,1604,1605,5,147,0,0,1605,1607,5,109,0,0,1606,1602, - 1,0,0,0,1606,1603,1,0,0,0,1606,1607,1,0,0,0,1607,1609,1,0,0,0,1608,1610, - 5,147,0,0,1609,1608,1,0,0,0,1609,1610,1,0,0,0,1610,1625,1,0,0,0,1611, - 1613,3,176,88,0,1612,1611,1,0,0,0,1612,1613,1,0,0,0,1613,1615,1,0,0,0, - 1614,1616,5,147,0,0,1615,1614,1,0,0,0,1615,1616,1,0,0,0,1616,1617,1,0, - 0,0,1617,1619,5,11,0,0,1618,1620,5,147,0,0,1619,1618,1,0,0,0,1619,1620, - 1,0,0,0,1620,1622,1,0,0,0,1621,1623,3,178,89,0,1622,1621,1,0,0,0,1622, - 1623,1,0,0,0,1623,1626,1,0,0,0,1624,1626,3,274,137,0,1625,1612,1,0,0, - 0,1625,1624,1,0,0,0,1625,1626,1,0,0,0,1626,1631,1,0,0,0,1627,1629,5,147, - 0,0,1628,1627,1,0,0,0,1628,1629,1,0,0,0,1629,1630,1,0,0,0,1630,1632,3, - 170,85,0,1631,1628,1,0,0,0,1631,1632,1,0,0,0,1632,169,1,0,0,0,1633,1635, - 5,2,0,0,1634,1636,5,147,0,0,1635,1634,1,0,0,0,1635,1636,1,0,0,0,1636, - 1637,1,0,0,0,1637,1639,3,264,132,0,1638,1640,5,147,0,0,1639,1638,1,0, - 0,0,1639,1640,1,0,0,0,1640,1641,1,0,0,0,1641,1643,5,4,0,0,1642,1644,5, - 147,0,0,1643,1642,1,0,0,0,1643,1644,1,0,0,0,1644,1645,1,0,0,0,1645,1654, - 3,264,132,0,1646,1648,5,147,0,0,1647,1646,1,0,0,0,1647,1648,1,0,0,0,1648, - 1649,1,0,0,0,1649,1651,5,10,0,0,1650,1652,5,147,0,0,1651,1650,1,0,0,0, - 1651,1652,1,0,0,0,1652,1653,1,0,0,0,1653,1655,3,142,71,0,1654,1647,1, - 0,0,0,1654,1655,1,0,0,0,1655,1675,1,0,0,0,1656,1658,5,147,0,0,1657,1656, - 1,0,0,0,1657,1658,1,0,0,0,1658,1659,1,0,0,0,1659,1661,5,10,0,0,1660,1662, - 5,147,0,0,1661,1660,1,0,0,0,1661,1662,1,0,0,0,1662,1663,1,0,0,0,1663, - 1665,3,174,87,0,1664,1666,5,147,0,0,1665,1664,1,0,0,0,1665,1666,1,0,0, - 0,1666,1667,1,0,0,0,1667,1669,5,4,0,0,1668,1670,5,147,0,0,1669,1668,1, - 0,0,0,1669,1670,1,0,0,0,1670,1671,1,0,0,0,1671,1673,3,172,86,0,1672,1674, - 5,147,0,0,1673,1672,1,0,0,0,1673,1674,1,0,0,0,1674,1676,1,0,0,0,1675, - 1657,1,0,0,0,1675,1676,1,0,0,0,1676,1677,1,0,0,0,1677,1678,5,3,0,0,1678, - 171,1,0,0,0,1679,1681,5,8,0,0,1680,1682,5,147,0,0,1681,1680,1,0,0,0,1681, - 1682,1,0,0,0,1682,1684,1,0,0,0,1683,1685,3,130,65,0,1684,1683,1,0,0,0, - 1684,1685,1,0,0,0,1685,1687,1,0,0,0,1686,1688,5,147,0,0,1687,1686,1,0, - 0,0,1687,1688,1,0,0,0,1688,1689,1,0,0,0,1689,1690,5,9,0,0,1690,173,1, - 0,0,0,1691,1693,5,8,0,0,1692,1694,5,147,0,0,1693,1692,1,0,0,0,1693,1694, - 1,0,0,0,1694,1696,1,0,0,0,1695,1697,3,130,65,0,1696,1695,1,0,0,0,1696, - 1697,1,0,0,0,1697,1699,1,0,0,0,1698,1700,5,147,0,0,1699,1698,1,0,0,0, - 1699,1700,1,0,0,0,1700,1701,1,0,0,0,1701,1702,5,9,0,0,1702,175,1,0,0, - 0,1703,1704,5,135,0,0,1704,177,1,0,0,0,1705,1706,5,135,0,0,1706,179,1, - 0,0,0,1707,1708,3,278,139,0,1708,181,1,0,0,0,1709,1710,3,278,139,0,1710, - 183,1,0,0,0,1711,1712,3,186,93,0,1712,185,1,0,0,0,1713,1720,3,188,94, - 0,1714,1715,5,147,0,0,1715,1716,5,110,0,0,1716,1717,5,147,0,0,1717,1719, - 3,188,94,0,1718,1714,1,0,0,0,1719,1722,1,0,0,0,1720,1718,1,0,0,0,1720, - 1721,1,0,0,0,1721,187,1,0,0,0,1722,1720,1,0,0,0,1723,1730,3,190,95,0, - 1724,1725,5,147,0,0,1725,1726,5,111,0,0,1726,1727,5,147,0,0,1727,1729, - 3,190,95,0,1728,1724,1,0,0,0,1729,1732,1,0,0,0,1730,1728,1,0,0,0,1730, - 1731,1,0,0,0,1731,189,1,0,0,0,1732,1730,1,0,0,0,1733,1740,3,192,96,0, - 1734,1735,5,147,0,0,1735,1736,5,112,0,0,1736,1737,5,147,0,0,1737,1739, - 3,192,96,0,1738,1734,1,0,0,0,1739,1742,1,0,0,0,1740,1738,1,0,0,0,1740, - 1741,1,0,0,0,1741,191,1,0,0,0,1742,1740,1,0,0,0,1743,1745,5,113,0,0,1744, - 1746,5,147,0,0,1745,1744,1,0,0,0,1745,1746,1,0,0,0,1746,1748,1,0,0,0, - 1747,1743,1,0,0,0,1748,1751,1,0,0,0,1749,1747,1,0,0,0,1749,1750,1,0,0, - 0,1750,1752,1,0,0,0,1751,1749,1,0,0,0,1752,1753,3,194,97,0,1753,193,1, - 0,0,0,1754,1764,3,198,99,0,1755,1757,5,147,0,0,1756,1755,1,0,0,0,1756, - 1757,1,0,0,0,1757,1758,1,0,0,0,1758,1760,3,196,98,0,1759,1761,5,147,0, - 0,1760,1759,1,0,0,0,1760,1761,1,0,0,0,1761,1762,1,0,0,0,1762,1763,3,198, - 99,0,1763,1765,1,0,0,0,1764,1756,1,0,0,0,1764,1765,1,0,0,0,1765,1803, - 1,0,0,0,1766,1768,3,198,99,0,1767,1769,5,147,0,0,1768,1767,1,0,0,0,1768, - 1769,1,0,0,0,1769,1770,1,0,0,0,1770,1772,5,114,0,0,1771,1773,5,147,0, - 0,1772,1771,1,0,0,0,1772,1773,1,0,0,0,1773,1774,1,0,0,0,1774,1775,3,198, - 99,0,1775,1776,1,0,0,0,1776,1777,6,97,-1,0,1777,1803,1,0,0,0,1778,1780, - 3,198,99,0,1779,1781,5,147,0,0,1780,1779,1,0,0,0,1780,1781,1,0,0,0,1781, - 1782,1,0,0,0,1782,1784,3,196,98,0,1783,1785,5,147,0,0,1784,1783,1,0,0, - 0,1784,1785,1,0,0,0,1785,1786,1,0,0,0,1786,1796,3,198,99,0,1787,1789, - 5,147,0,0,1788,1787,1,0,0,0,1788,1789,1,0,0,0,1789,1790,1,0,0,0,1790, - 1792,3,196,98,0,1791,1793,5,147,0,0,1792,1791,1,0,0,0,1792,1793,1,0,0, - 0,1793,1794,1,0,0,0,1794,1795,3,198,99,0,1795,1797,1,0,0,0,1796,1788, - 1,0,0,0,1797,1798,1,0,0,0,1798,1796,1,0,0,0,1798,1799,1,0,0,0,1799,1800, - 1,0,0,0,1800,1801,6,97,-1,0,1801,1803,1,0,0,0,1802,1754,1,0,0,0,1802, - 1766,1,0,0,0,1802,1778,1,0,0,0,1803,195,1,0,0,0,1804,1805,7,2,0,0,1805, - 197,1,0,0,0,1806,1817,3,200,100,0,1807,1809,5,147,0,0,1808,1807,1,0,0, - 0,1808,1809,1,0,0,0,1809,1810,1,0,0,0,1810,1812,5,10,0,0,1811,1813,5, - 147,0,0,1812,1811,1,0,0,0,1812,1813,1,0,0,0,1813,1814,1,0,0,0,1814,1816, - 3,200,100,0,1815,1808,1,0,0,0,1816,1819,1,0,0,0,1817,1815,1,0,0,0,1817, - 1818,1,0,0,0,1818,199,1,0,0,0,1819,1817,1,0,0,0,1820,1831,3,202,101,0, - 1821,1823,5,147,0,0,1822,1821,1,0,0,0,1822,1823,1,0,0,0,1823,1824,1,0, - 0,0,1824,1826,5,17,0,0,1825,1827,5,147,0,0,1826,1825,1,0,0,0,1826,1827, - 1,0,0,0,1827,1828,1,0,0,0,1828,1830,3,202,101,0,1829,1822,1,0,0,0,1830, - 1833,1,0,0,0,1831,1829,1,0,0,0,1831,1832,1,0,0,0,1832,201,1,0,0,0,1833, - 1831,1,0,0,0,1834,1846,3,206,103,0,1835,1837,5,147,0,0,1836,1835,1,0, - 0,0,1836,1837,1,0,0,0,1837,1838,1,0,0,0,1838,1840,3,204,102,0,1839,1841, - 5,147,0,0,1840,1839,1,0,0,0,1840,1841,1,0,0,0,1841,1842,1,0,0,0,1842, - 1843,3,206,103,0,1843,1845,1,0,0,0,1844,1836,1,0,0,0,1845,1848,1,0,0, - 0,1846,1844,1,0,0,0,1846,1847,1,0,0,0,1847,203,1,0,0,0,1848,1846,1,0, - 0,0,1849,1850,7,3,0,0,1850,205,1,0,0,0,1851,1863,3,210,105,0,1852,1854, - 5,147,0,0,1853,1852,1,0,0,0,1853,1854,1,0,0,0,1854,1855,1,0,0,0,1855, - 1857,3,208,104,0,1856,1858,5,147,0,0,1857,1856,1,0,0,0,1857,1858,1,0, - 0,0,1858,1859,1,0,0,0,1859,1860,3,210,105,0,1860,1862,1,0,0,0,1861,1853, - 1,0,0,0,1862,1865,1,0,0,0,1863,1861,1,0,0,0,1863,1864,1,0,0,0,1864,207, - 1,0,0,0,1865,1863,1,0,0,0,1866,1867,7,4,0,0,1867,209,1,0,0,0,1868,1880, - 3,214,107,0,1869,1871,5,147,0,0,1870,1869,1,0,0,0,1870,1871,1,0,0,0,1871, - 1872,1,0,0,0,1872,1874,3,212,106,0,1873,1875,5,147,0,0,1874,1873,1,0, - 0,0,1874,1875,1,0,0,0,1875,1876,1,0,0,0,1876,1877,3,214,107,0,1877,1879, - 1,0,0,0,1878,1870,1,0,0,0,1879,1882,1,0,0,0,1880,1878,1,0,0,0,1880,1881, - 1,0,0,0,1881,211,1,0,0,0,1882,1880,1,0,0,0,1883,1884,7,5,0,0,1884,213, - 1,0,0,0,1885,1896,3,216,108,0,1886,1888,5,147,0,0,1887,1886,1,0,0,0,1887, - 1888,1,0,0,0,1888,1889,1,0,0,0,1889,1891,5,23,0,0,1890,1892,5,147,0,0, - 1891,1890,1,0,0,0,1891,1892,1,0,0,0,1892,1893,1,0,0,0,1893,1895,3,216, - 108,0,1894,1887,1,0,0,0,1895,1898,1,0,0,0,1896,1894,1,0,0,0,1896,1897, - 1,0,0,0,1897,215,1,0,0,0,1898,1896,1,0,0,0,1899,1901,5,115,0,0,1900,1902, - 5,147,0,0,1901,1900,1,0,0,0,1901,1902,1,0,0,0,1902,1904,1,0,0,0,1903, - 1899,1,0,0,0,1904,1907,1,0,0,0,1905,1903,1,0,0,0,1905,1906,1,0,0,0,1906, - 1908,1,0,0,0,1907,1905,1,0,0,0,1908,1913,3,218,109,0,1909,1911,5,147, - 0,0,1910,1909,1,0,0,0,1910,1911,1,0,0,0,1911,1912,1,0,0,0,1912,1914,5, - 116,0,0,1913,1910,1,0,0,0,1913,1914,1,0,0,0,1914,217,1,0,0,0,1915,1923, - 3,228,114,0,1916,1924,3,222,111,0,1917,1919,3,220,110,0,1918,1917,1,0, - 0,0,1919,1920,1,0,0,0,1920,1918,1,0,0,0,1920,1921,1,0,0,0,1921,1924,1, - 0,0,0,1922,1924,3,226,113,0,1923,1916,1,0,0,0,1923,1918,1,0,0,0,1923, - 1922,1,0,0,0,1923,1924,1,0,0,0,1924,219,1,0,0,0,1925,1926,5,147,0,0,1926, - 1928,5,118,0,0,1927,1929,5,147,0,0,1928,1927,1,0,0,0,1928,1929,1,0,0, - 0,1929,1930,1,0,0,0,1930,1945,3,228,114,0,1931,1932,5,6,0,0,1932,1933, - 3,184,92,0,1933,1934,5,7,0,0,1934,1945,1,0,0,0,1935,1937,5,6,0,0,1936, - 1938,3,184,92,0,1937,1936,1,0,0,0,1937,1938,1,0,0,0,1938,1939,1,0,0,0, - 1939,1941,5,117,0,0,1940,1942,3,184,92,0,1941,1940,1,0,0,0,1941,1942, - 1,0,0,0,1942,1943,1,0,0,0,1943,1945,5,7,0,0,1944,1925,1,0,0,0,1944,1931, - 1,0,0,0,1944,1935,1,0,0,0,1945,221,1,0,0,0,1946,1958,3,224,112,0,1947, - 1948,5,147,0,0,1948,1949,5,119,0,0,1949,1950,5,147,0,0,1950,1958,5,95, - 0,0,1951,1952,5,147,0,0,1952,1953,5,120,0,0,1953,1954,5,147,0,0,1954, - 1958,5,95,0,0,1955,1956,5,147,0,0,1956,1958,5,121,0,0,1957,1946,1,0,0, - 0,1957,1947,1,0,0,0,1957,1951,1,0,0,0,1957,1955,1,0,0,0,1958,1960,1,0, - 0,0,1959,1961,5,147,0,0,1960,1959,1,0,0,0,1960,1961,1,0,0,0,1961,1962, - 1,0,0,0,1962,1963,3,228,114,0,1963,223,1,0,0,0,1964,1966,5,147,0,0,1965, - 1964,1,0,0,0,1965,1966,1,0,0,0,1966,1967,1,0,0,0,1967,1968,5,24,0,0,1968, - 225,1,0,0,0,1969,1970,5,147,0,0,1970,1971,5,122,0,0,1971,1972,5,147,0, - 0,1972,1980,5,123,0,0,1973,1974,5,147,0,0,1974,1975,5,122,0,0,1975,1976, - 5,147,0,0,1976,1977,5,113,0,0,1977,1978,5,147,0,0,1978,1980,5,123,0,0, - 1979,1969,1,0,0,0,1979,1973,1,0,0,0,1980,227,1,0,0,0,1981,1988,3,230, - 115,0,1982,1984,5,147,0,0,1983,1982,1,0,0,0,1983,1984,1,0,0,0,1984,1985, - 1,0,0,0,1985,1987,3,258,129,0,1986,1983,1,0,0,0,1987,1990,1,0,0,0,1988, - 1986,1,0,0,0,1988,1989,1,0,0,0,1989,229,1,0,0,0,1990,1988,1,0,0,0,1991, - 2001,3,232,116,0,1992,2001,3,268,134,0,1993,2001,3,260,130,0,1994,2001, - 3,244,122,0,1995,2001,3,246,123,0,1996,2001,3,252,126,0,1997,2001,3,254, - 127,0,1998,2001,3,256,128,0,1999,2001,3,264,132,0,2000,1991,1,0,0,0,2000, - 1992,1,0,0,0,2000,1993,1,0,0,0,2000,1994,1,0,0,0,2000,1995,1,0,0,0,2000, - 1996,1,0,0,0,2000,1997,1,0,0,0,2000,1998,1,0,0,0,2000,1999,1,0,0,0,2001, - 231,1,0,0,0,2002,2009,3,266,133,0,2003,2009,5,133,0,0,2004,2009,3,234, - 117,0,2005,2009,5,123,0,0,2006,2009,3,236,118,0,2007,2009,3,240,120,0, - 2008,2002,1,0,0,0,2008,2003,1,0,0,0,2008,2004,1,0,0,0,2008,2005,1,0,0, - 0,2008,2006,1,0,0,0,2008,2007,1,0,0,0,2009,233,1,0,0,0,2010,2011,7,6, - 0,0,2011,235,1,0,0,0,2012,2014,5,6,0,0,2013,2015,5,147,0,0,2014,2013, - 1,0,0,0,2014,2015,1,0,0,0,2015,2029,1,0,0,0,2016,2018,3,184,92,0,2017, - 2019,5,147,0,0,2018,2017,1,0,0,0,2018,2019,1,0,0,0,2019,2026,1,0,0,0, - 2020,2022,3,238,119,0,2021,2023,5,147,0,0,2022,2021,1,0,0,0,2022,2023, - 1,0,0,0,2023,2025,1,0,0,0,2024,2020,1,0,0,0,2025,2028,1,0,0,0,2026,2024, - 1,0,0,0,2026,2027,1,0,0,0,2027,2030,1,0,0,0,2028,2026,1,0,0,0,2029,2016, - 1,0,0,0,2029,2030,1,0,0,0,2030,2031,1,0,0,0,2031,2032,5,7,0,0,2032,237, - 1,0,0,0,2033,2035,5,4,0,0,2034,2036,5,147,0,0,2035,2034,1,0,0,0,2035, - 2036,1,0,0,0,2036,2038,1,0,0,0,2037,2039,3,184,92,0,2038,2037,1,0,0,0, - 2038,2039,1,0,0,0,2039,239,1,0,0,0,2040,2042,5,8,0,0,2041,2043,5,147, - 0,0,2042,2041,1,0,0,0,2042,2043,1,0,0,0,2043,2044,1,0,0,0,2044,2046,3, - 242,121,0,2045,2047,5,147,0,0,2046,2045,1,0,0,0,2046,2047,1,0,0,0,2047, - 2058,1,0,0,0,2048,2050,5,4,0,0,2049,2051,5,147,0,0,2050,2049,1,0,0,0, - 2050,2051,1,0,0,0,2051,2052,1,0,0,0,2052,2054,3,242,121,0,2053,2055,5, - 147,0,0,2054,2053,1,0,0,0,2054,2055,1,0,0,0,2055,2057,1,0,0,0,2056,2048, - 1,0,0,0,2057,2060,1,0,0,0,2058,2056,1,0,0,0,2058,2059,1,0,0,0,2059,2061, - 1,0,0,0,2060,2058,1,0,0,0,2061,2062,5,9,0,0,2062,241,1,0,0,0,2063,2066, - 3,280,140,0,2064,2066,5,133,0,0,2065,2063,1,0,0,0,2065,2064,1,0,0,0,2066, - 2068,1,0,0,0,2067,2069,5,147,0,0,2068,2067,1,0,0,0,2068,2069,1,0,0,0, - 2069,2070,1,0,0,0,2070,2072,5,117,0,0,2071,2073,5,147,0,0,2072,2071,1, - 0,0,0,2072,2073,1,0,0,0,2073,2074,1,0,0,0,2074,2075,3,184,92,0,2075,243, - 1,0,0,0,2076,2078,5,2,0,0,2077,2079,5,147,0,0,2078,2077,1,0,0,0,2078, - 2079,1,0,0,0,2079,2080,1,0,0,0,2080,2082,3,184,92,0,2081,2083,5,147,0, - 0,2082,2081,1,0,0,0,2082,2083,1,0,0,0,2083,2084,1,0,0,0,2084,2085,5,3, - 0,0,2085,245,1,0,0,0,2086,2088,5,126,0,0,2087,2089,5,147,0,0,2088,2087, - 1,0,0,0,2088,2089,1,0,0,0,2089,2090,1,0,0,0,2090,2092,5,2,0,0,2091,2093, - 5,147,0,0,2092,2091,1,0,0,0,2092,2093,1,0,0,0,2093,2094,1,0,0,0,2094, - 2096,5,98,0,0,2095,2097,5,147,0,0,2096,2095,1,0,0,0,2096,2097,1,0,0,0, - 2097,2098,1,0,0,0,2098,2135,5,3,0,0,2099,2101,3,248,124,0,2100,2102,5, - 147,0,0,2101,2100,1,0,0,0,2101,2102,1,0,0,0,2102,2103,1,0,0,0,2103,2105, - 5,2,0,0,2104,2106,5,147,0,0,2105,2104,1,0,0,0,2105,2106,1,0,0,0,2106, - 2111,1,0,0,0,2107,2109,5,97,0,0,2108,2110,5,147,0,0,2109,2108,1,0,0,0, - 2109,2110,1,0,0,0,2110,2112,1,0,0,0,2111,2107,1,0,0,0,2111,2112,1,0,0, - 0,2112,2130,1,0,0,0,2113,2115,3,250,125,0,2114,2116,5,147,0,0,2115,2114, - 1,0,0,0,2115,2116,1,0,0,0,2116,2127,1,0,0,0,2117,2119,5,4,0,0,2118,2120, - 5,147,0,0,2119,2118,1,0,0,0,2119,2120,1,0,0,0,2120,2121,1,0,0,0,2121, - 2123,3,250,125,0,2122,2124,5,147,0,0,2123,2122,1,0,0,0,2123,2124,1,0, - 0,0,2124,2126,1,0,0,0,2125,2117,1,0,0,0,2126,2129,1,0,0,0,2127,2125,1, - 0,0,0,2127,2128,1,0,0,0,2128,2131,1,0,0,0,2129,2127,1,0,0,0,2130,2113, - 1,0,0,0,2130,2131,1,0,0,0,2131,2132,1,0,0,0,2132,2133,5,3,0,0,2133,2135, - 1,0,0,0,2134,2086,1,0,0,0,2134,2099,1,0,0,0,2135,247,1,0,0,0,2136,2137, - 3,280,140,0,2137,249,1,0,0,0,2138,2140,3,280,140,0,2139,2141,5,147,0, - 0,2140,2139,1,0,0,0,2140,2141,1,0,0,0,2141,2142,1,0,0,0,2142,2143,5,117, - 0,0,2143,2145,5,5,0,0,2144,2146,5,147,0,0,2145,2144,1,0,0,0,2145,2146, - 1,0,0,0,2146,2148,1,0,0,0,2147,2138,1,0,0,0,2147,2148,1,0,0,0,2148,2149, - 1,0,0,0,2149,2150,3,184,92,0,2150,251,1,0,0,0,2151,2156,3,152,76,0,2152, - 2154,5,147,0,0,2153,2152,1,0,0,0,2153,2154,1,0,0,0,2154,2155,1,0,0,0, - 2155,2157,3,154,77,0,2156,2153,1,0,0,0,2157,2158,1,0,0,0,2158,2156,1, - 0,0,0,2158,2159,1,0,0,0,2159,253,1,0,0,0,2160,2162,5,127,0,0,2161,2163, - 5,147,0,0,2162,2161,1,0,0,0,2162,2163,1,0,0,0,2163,2164,1,0,0,0,2164, - 2166,5,8,0,0,2165,2167,5,147,0,0,2166,2165,1,0,0,0,2166,2167,1,0,0,0, - 2167,2168,1,0,0,0,2168,2170,5,87,0,0,2169,2171,5,147,0,0,2170,2169,1, - 0,0,0,2170,2171,1,0,0,0,2171,2172,1,0,0,0,2172,2177,3,144,72,0,2173,2175, - 5,147,0,0,2174,2173,1,0,0,0,2174,2175,1,0,0,0,2175,2176,1,0,0,0,2176, - 2178,3,142,71,0,2177,2174,1,0,0,0,2177,2178,1,0,0,0,2178,2180,1,0,0,0, - 2179,2181,5,147,0,0,2180,2179,1,0,0,0,2180,2181,1,0,0,0,2181,2182,1,0, - 0,0,2182,2183,5,9,0,0,2183,255,1,0,0,0,2184,2186,5,126,0,0,2185,2187, - 5,147,0,0,2186,2185,1,0,0,0,2186,2187,1,0,0,0,2187,2188,1,0,0,0,2188, - 2190,5,8,0,0,2189,2191,5,147,0,0,2190,2189,1,0,0,0,2190,2191,1,0,0,0, - 2191,2192,1,0,0,0,2192,2194,5,87,0,0,2193,2195,5,147,0,0,2194,2193,1, - 0,0,0,2194,2195,1,0,0,0,2195,2196,1,0,0,0,2196,2201,3,144,72,0,2197,2199, - 5,147,0,0,2198,2197,1,0,0,0,2198,2199,1,0,0,0,2199,2200,1,0,0,0,2200, - 2202,3,142,71,0,2201,2198,1,0,0,0,2201,2202,1,0,0,0,2202,2204,1,0,0,0, - 2203,2205,5,147,0,0,2204,2203,1,0,0,0,2204,2205,1,0,0,0,2205,2206,1,0, - 0,0,2206,2207,5,9,0,0,2207,257,1,0,0,0,2208,2210,5,25,0,0,2209,2211,5, - 147,0,0,2210,2209,1,0,0,0,2210,2211,1,0,0,0,2211,2214,1,0,0,0,2212,2215, - 3,272,136,0,2213,2215,5,98,0,0,2214,2212,1,0,0,0,2214,2213,1,0,0,0,2215, - 259,1,0,0,0,2216,2221,5,128,0,0,2217,2219,5,147,0,0,2218,2217,1,0,0,0, - 2218,2219,1,0,0,0,2219,2220,1,0,0,0,2220,2222,3,262,131,0,2221,2218,1, - 0,0,0,2222,2223,1,0,0,0,2223,2221,1,0,0,0,2223,2224,1,0,0,0,2224,2239, - 1,0,0,0,2225,2227,5,128,0,0,2226,2228,5,147,0,0,2227,2226,1,0,0,0,2227, - 2228,1,0,0,0,2228,2229,1,0,0,0,2229,2234,3,184,92,0,2230,2232,5,147,0, - 0,2231,2230,1,0,0,0,2231,2232,1,0,0,0,2232,2233,1,0,0,0,2233,2235,3,262, - 131,0,2234,2231,1,0,0,0,2235,2236,1,0,0,0,2236,2234,1,0,0,0,2236,2237, - 1,0,0,0,2237,2239,1,0,0,0,2238,2216,1,0,0,0,2238,2225,1,0,0,0,2239,2248, - 1,0,0,0,2240,2242,5,147,0,0,2241,2240,1,0,0,0,2241,2242,1,0,0,0,2242, - 2243,1,0,0,0,2243,2245,5,129,0,0,2244,2246,5,147,0,0,2245,2244,1,0,0, - 0,2245,2246,1,0,0,0,2246,2247,1,0,0,0,2247,2249,3,184,92,0,2248,2241, - 1,0,0,0,2248,2249,1,0,0,0,2249,2251,1,0,0,0,2250,2252,5,147,0,0,2251, - 2250,1,0,0,0,2251,2252,1,0,0,0,2252,2253,1,0,0,0,2253,2254,5,130,0,0, - 2254,261,1,0,0,0,2255,2257,5,131,0,0,2256,2258,5,147,0,0,2257,2256,1, - 0,0,0,2257,2258,1,0,0,0,2258,2259,1,0,0,0,2259,2261,3,184,92,0,2260,2262, - 5,147,0,0,2261,2260,1,0,0,0,2261,2262,1,0,0,0,2262,2263,1,0,0,0,2263, - 2265,5,132,0,0,2264,2266,5,147,0,0,2265,2264,1,0,0,0,2265,2266,1,0,0, - 0,2266,2267,1,0,0,0,2267,2268,3,184,92,0,2268,263,1,0,0,0,2269,2270,3, - 280,140,0,2270,265,1,0,0,0,2271,2274,3,276,138,0,2272,2274,3,274,137, - 0,2273,2271,1,0,0,0,2273,2272,1,0,0,0,2274,267,1,0,0,0,2275,2278,5,26, - 0,0,2276,2279,3,280,140,0,2277,2279,5,135,0,0,2278,2276,1,0,0,0,2278, - 2277,1,0,0,0,2279,269,1,0,0,0,2280,2282,3,230,115,0,2281,2283,5,147,0, - 0,2282,2281,1,0,0,0,2282,2283,1,0,0,0,2283,2284,1,0,0,0,2284,2285,3,258, - 129,0,2285,271,1,0,0,0,2286,2287,3,278,139,0,2287,273,1,0,0,0,2288,2289, - 5,135,0,0,2289,275,1,0,0,0,2290,2291,5,142,0,0,2291,277,1,0,0,0,2292, - 2293,3,280,140,0,2293,279,1,0,0,0,2294,2300,5,143,0,0,2295,2296,5,146, - 0,0,2296,2300,6,140,-1,0,2297,2300,5,136,0,0,2298,2300,3,282,141,0,2299, - 2294,1,0,0,0,2299,2295,1,0,0,0,2299,2297,1,0,0,0,2299,2298,1,0,0,0,2300, - 281,1,0,0,0,2301,2302,7,7,0,0,2302,283,1,0,0,0,2303,2304,7,8,0,0,2304, - 285,1,0,0,0,2305,2306,7,9,0,0,2306,287,1,0,0,0,2307,2308,7,10,0,0,2308, - 289,1,0,0,0,401,292,296,301,305,310,313,317,320,334,340,344,348,352,355, - 361,364,368,372,376,380,384,389,400,404,408,413,426,430,438,442,446,450, - 458,462,466,470,482,486,508,512,515,518,521,524,528,533,537,547,551,556, - 561,566,572,576,580,585,592,596,600,603,607,611,616,621,625,635,645,649, - 653,657,662,674,678,682,686,690,692,696,700,702,716,720,724,728,733,736, - 740,744,746,750,754,756,792,803,825,829,834,845,849,853,861,865,869,875, - 879,883,889,893,897,901,905,909,915,922,927,933,953,957,965,975,980,985, - 989,994,1000,1005,1008,1012,1016,1020,1026,1030,1035,1040,1044,1047,1051, - 1055,1059,1063,1067,1073,1077,1082,1086,1095,1101,1109,1113,1117,1121, - 1128,1132,1136,1140,1143,1146,1149,1155,1158,1162,1166,1170,1173,1177, - 1187,1193,1200,1213,1217,1221,1225,1230,1235,1239,1245,1249,1253,1257, - 1262,1268,1271,1277,1280,1286,1290,1294,1298,1302,1307,1312,1316,1321, - 1324,1333,1342,1347,1360,1363,1371,1375,1380,1385,1389,1394,1400,1405, - 1412,1416,1420,1422,1426,1428,1432,1434,1440,1446,1450,1453,1456,1462, - 1465,1468,1472,1478,1481,1484,1488,1492,1496,1498,1502,1504,1508,1510, - 1514,1516,1522,1526,1530,1534,1538,1542,1546,1550,1554,1557,1563,1567, - 1571,1574,1579,1584,1589,1594,1600,1606,1609,1612,1615,1619,1622,1625, - 1628,1631,1635,1639,1643,1647,1651,1654,1657,1661,1665,1669,1673,1675, - 1681,1684,1687,1693,1696,1699,1720,1730,1740,1745,1749,1756,1760,1764, - 1768,1772,1780,1784,1788,1792,1798,1802,1808,1812,1817,1822,1826,1831, - 1836,1840,1846,1853,1857,1863,1870,1874,1880,1887,1891,1896,1901,1905, - 1910,1913,1920,1923,1928,1937,1941,1944,1957,1960,1965,1979,1983,1988, - 2000,2008,2014,2018,2022,2026,2029,2035,2038,2042,2046,2050,2054,2058, - 2065,2068,2072,2078,2082,2088,2092,2096,2101,2105,2109,2111,2115,2119, - 2123,2127,2130,2134,2140,2145,2147,2153,2158,2162,2166,2170,2174,2177, - 2180,2186,2190,2194,2198,2201,2204,2210,2214,2218,2223,2227,2231,2236, - 2238,2241,2245,2248,2251,2257,2261,2265,2273,2278,2282,2299 + 278,280,282,284,286,288,290,292,294,0,11,2,0,59,59,61,61,1,0,106,109, + 2,0,5,5,12,16,1,0,18,19,2,0,20,20,117,117,2,0,21,22,100,100,1,0,126,127, + 7,0,49,49,55,58,69,69,73,73,120,120,128,128,132,132,2,0,13,13,27,30,2, + 0,15,15,31,34,2,0,35,45,117,117,2636,0,296,1,0,0,0,2,316,1,0,0,0,4,342, + 1,0,0,0,6,344,1,0,0,0,8,366,1,0,0,0,10,401,1,0,0,0,12,403,1,0,0,0,14, + 433,1,0,0,0,16,454,1,0,0,0,18,465,1,0,0,0,20,471,1,0,0,0,22,498,1,0,0, + 0,24,502,1,0,0,0,26,514,1,0,0,0,28,526,1,0,0,0,30,569,1,0,0,0,32,583, + 1,0,0,0,34,627,1,0,0,0,36,629,1,0,0,0,38,652,1,0,0,0,40,668,1,0,0,0,42, + 670,1,0,0,0,44,699,1,0,0,0,46,739,1,0,0,0,48,793,1,0,0,0,50,801,1,0,0, + 0,52,807,1,0,0,0,54,813,1,0,0,0,56,825,1,0,0,0,58,827,1,0,0,0,60,838, + 1,0,0,0,62,842,1,0,0,0,64,848,1,0,0,0,66,856,1,0,0,0,68,870,1,0,0,0,70, + 874,1,0,0,0,72,942,1,0,0,0,74,951,1,0,0,0,76,958,1,0,0,0,78,966,1,0,0, + 0,80,968,1,0,0,0,82,970,1,0,0,0,84,986,1,0,0,0,86,990,1,0,0,0,88,992, + 1,0,0,0,90,1000,1,0,0,0,92,1004,1,0,0,0,94,1027,1,0,0,0,96,1041,1,0,0, + 0,98,1045,1,0,0,0,100,1092,1,0,0,0,102,1098,1,0,0,0,104,1110,1,0,0,0, + 106,1128,1,0,0,0,108,1134,1,0,0,0,110,1136,1,0,0,0,112,1172,1,0,0,0,114, + 1183,1,0,0,0,116,1196,1,0,0,0,118,1206,1,0,0,0,120,1212,1,0,0,0,122,1234, + 1,0,0,0,124,1236,1,0,0,0,126,1254,1,0,0,0,128,1266,1,0,0,0,130,1286,1, + 0,0,0,132,1294,1,0,0,0,134,1301,1,0,0,0,136,1345,1,0,0,0,138,1354,1,0, + 0,0,140,1356,1,0,0,0,142,1371,1,0,0,0,144,1375,1,0,0,0,146,1379,1,0,0, + 0,148,1386,1,0,0,0,150,1390,1,0,0,0,152,1415,1,0,0,0,154,1417,1,0,0,0, + 156,1433,1,0,0,0,158,1435,1,0,0,0,160,1459,1,0,0,0,162,1509,1,0,0,0,164, + 1511,1,0,0,0,166,1541,1,0,0,0,168,1582,1,0,0,0,170,1603,1,0,0,0,172,1613, + 1,0,0,0,174,1619,1,0,0,0,176,1654,1,0,0,0,178,1700,1,0,0,0,180,1712,1, + 0,0,0,182,1724,1,0,0,0,184,1726,1,0,0,0,186,1728,1,0,0,0,188,1730,1,0, + 0,0,190,1732,1,0,0,0,192,1734,1,0,0,0,194,1744,1,0,0,0,196,1754,1,0,0, + 0,198,1770,1,0,0,0,200,1823,1,0,0,0,202,1825,1,0,0,0,204,1827,1,0,0,0, + 206,1841,1,0,0,0,208,1855,1,0,0,0,210,1870,1,0,0,0,212,1872,1,0,0,0,214, + 1887,1,0,0,0,216,1889,1,0,0,0,218,1904,1,0,0,0,220,1906,1,0,0,0,222,1926, + 1,0,0,0,224,1936,1,0,0,0,226,1965,1,0,0,0,228,1978,1,0,0,0,230,1986,1, + 0,0,0,232,2000,1,0,0,0,234,2002,1,0,0,0,236,2021,1,0,0,0,238,2029,1,0, + 0,0,240,2031,1,0,0,0,242,2033,1,0,0,0,244,2054,1,0,0,0,246,2061,1,0,0, + 0,248,2086,1,0,0,0,250,2097,1,0,0,0,252,2155,1,0,0,0,254,2157,1,0,0,0, + 256,2168,1,0,0,0,258,2172,1,0,0,0,260,2181,1,0,0,0,262,2205,1,0,0,0,264, + 2229,1,0,0,0,266,2259,1,0,0,0,268,2276,1,0,0,0,270,2290,1,0,0,0,272,2294, + 1,0,0,0,274,2296,1,0,0,0,276,2301,1,0,0,0,278,2307,1,0,0,0,280,2309,1, + 0,0,0,282,2311,1,0,0,0,284,2313,1,0,0,0,286,2320,1,0,0,0,288,2322,1,0, + 0,0,290,2324,1,0,0,0,292,2326,1,0,0,0,294,2328,1,0,0,0,296,307,3,2,1, + 0,297,299,5,149,0,0,298,297,1,0,0,0,298,299,1,0,0,0,299,300,1,0,0,0,300, + 302,5,1,0,0,301,303,5,149,0,0,302,301,1,0,0,0,302,303,1,0,0,0,303,304, + 1,0,0,0,304,306,3,2,1,0,305,298,1,0,0,0,306,309,1,0,0,0,307,305,1,0,0, + 0,307,308,1,0,0,0,308,311,1,0,0,0,309,307,1,0,0,0,310,312,5,149,0,0,311, + 310,1,0,0,0,311,312,1,0,0,0,312,313,1,0,0,0,313,314,5,0,0,1,314,1,1,0, + 0,0,315,317,3,78,39,0,316,315,1,0,0,0,316,317,1,0,0,0,317,319,1,0,0,0, + 318,320,5,149,0,0,319,318,1,0,0,0,319,320,1,0,0,0,320,321,1,0,0,0,321, + 326,3,4,2,0,322,324,5,149,0,0,323,322,1,0,0,0,323,324,1,0,0,0,324,325, + 1,0,0,0,325,327,5,1,0,0,326,323,1,0,0,0,326,327,1,0,0,0,327,3,1,0,0,0, + 328,343,3,92,46,0,329,343,3,40,20,0,330,343,3,6,3,0,331,343,3,12,6,0, + 332,343,3,14,7,0,333,343,3,24,12,0,334,343,3,28,14,0,335,343,3,26,13, + 0,336,343,3,84,42,0,337,343,3,86,43,0,338,343,3,16,8,0,339,343,3,18,9, + 0,340,343,3,20,10,0,341,343,3,22,11,0,342,328,1,0,0,0,342,329,1,0,0,0, + 342,330,1,0,0,0,342,331,1,0,0,0,342,332,1,0,0,0,342,333,1,0,0,0,342,334, + 1,0,0,0,342,335,1,0,0,0,342,336,1,0,0,0,342,337,1,0,0,0,342,338,1,0,0, + 0,342,339,1,0,0,0,342,340,1,0,0,0,342,341,1,0,0,0,343,5,1,0,0,0,344,345, + 5,52,0,0,345,346,5,149,0,0,346,355,3,284,142,0,347,349,5,149,0,0,348, + 347,1,0,0,0,348,349,1,0,0,0,349,350,1,0,0,0,350,352,3,8,4,0,351,353,5, + 149,0,0,352,351,1,0,0,0,352,353,1,0,0,0,353,356,1,0,0,0,354,356,5,149, + 0,0,355,348,1,0,0,0,355,354,1,0,0,0,356,357,1,0,0,0,357,358,5,53,0,0, + 358,359,5,149,0,0,359,364,3,10,5,0,360,362,5,149,0,0,361,360,1,0,0,0, + 361,362,1,0,0,0,362,363,1,0,0,0,363,365,3,36,18,0,364,361,1,0,0,0,364, + 365,1,0,0,0,365,7,1,0,0,0,366,368,5,2,0,0,367,369,5,149,0,0,368,367,1, + 0,0,0,368,369,1,0,0,0,369,370,1,0,0,0,370,381,3,284,142,0,371,373,5,149, + 0,0,372,371,1,0,0,0,372,373,1,0,0,0,373,374,1,0,0,0,374,376,5,3,0,0,375, + 377,5,149,0,0,376,375,1,0,0,0,376,377,1,0,0,0,377,378,1,0,0,0,378,380, + 3,284,142,0,379,372,1,0,0,0,380,383,1,0,0,0,381,379,1,0,0,0,381,382,1, + 0,0,0,382,385,1,0,0,0,383,381,1,0,0,0,384,386,5,149,0,0,385,384,1,0,0, + 0,385,386,1,0,0,0,386,387,1,0,0,0,387,388,5,4,0,0,388,9,1,0,0,0,389,402, + 3,34,17,0,390,392,5,2,0,0,391,393,5,149,0,0,392,391,1,0,0,0,392,393,1, + 0,0,0,393,394,1,0,0,0,394,396,3,92,46,0,395,397,5,149,0,0,396,395,1,0, + 0,0,396,397,1,0,0,0,397,398,1,0,0,0,398,399,5,4,0,0,399,402,1,0,0,0,400, + 402,3,270,135,0,401,389,1,0,0,0,401,390,1,0,0,0,401,400,1,0,0,0,402,11, + 1,0,0,0,403,404,5,52,0,0,404,405,5,149,0,0,405,406,3,284,142,0,406,407, + 5,149,0,0,407,408,5,53,0,0,408,409,5,149,0,0,409,411,5,2,0,0,410,412, + 5,149,0,0,411,410,1,0,0,0,411,412,1,0,0,0,412,413,1,0,0,0,413,424,5,135, + 0,0,414,416,5,149,0,0,415,414,1,0,0,0,415,416,1,0,0,0,416,417,1,0,0,0, + 417,419,5,3,0,0,418,420,5,149,0,0,419,418,1,0,0,0,419,420,1,0,0,0,420, + 421,1,0,0,0,421,423,5,135,0,0,422,415,1,0,0,0,423,426,1,0,0,0,424,422, + 1,0,0,0,424,425,1,0,0,0,425,427,1,0,0,0,426,424,1,0,0,0,427,428,5,4,0, + 0,428,429,5,149,0,0,429,430,5,103,0,0,430,431,5,149,0,0,431,432,5,54, + 0,0,432,13,1,0,0,0,433,434,5,52,0,0,434,435,5,149,0,0,435,437,5,2,0,0, + 436,438,5,149,0,0,437,436,1,0,0,0,437,438,1,0,0,0,438,439,1,0,0,0,439, + 441,3,92,46,0,440,442,5,149,0,0,441,440,1,0,0,0,441,442,1,0,0,0,442,443, + 1,0,0,0,443,444,5,4,0,0,444,445,5,149,0,0,445,446,5,70,0,0,446,447,5, + 149,0,0,447,452,5,135,0,0,448,450,5,149,0,0,449,448,1,0,0,0,449,450,1, + 0,0,0,450,451,1,0,0,0,451,453,3,36,18,0,452,449,1,0,0,0,452,453,1,0,0, + 0,453,15,1,0,0,0,454,455,5,55,0,0,455,456,5,149,0,0,456,457,5,57,0,0, + 457,458,5,149,0,0,458,463,5,135,0,0,459,461,5,149,0,0,460,459,1,0,0,0, + 460,461,1,0,0,0,461,462,1,0,0,0,462,464,3,36,18,0,463,460,1,0,0,0,463, + 464,1,0,0,0,464,17,1,0,0,0,465,466,5,56,0,0,466,467,5,149,0,0,467,468, + 5,57,0,0,468,469,5,149,0,0,469,470,5,135,0,0,470,19,1,0,0,0,471,472,5, + 46,0,0,472,473,5,149,0,0,473,480,5,135,0,0,474,475,5,149,0,0,475,476, + 5,101,0,0,476,477,5,149,0,0,477,478,3,284,142,0,478,479,5,149,0,0,479, + 481,1,0,0,0,480,474,1,0,0,0,480,481,1,0,0,0,481,496,1,0,0,0,482,484,5, + 149,0,0,483,482,1,0,0,0,483,484,1,0,0,0,484,485,1,0,0,0,485,487,5,2,0, + 0,486,488,5,149,0,0,487,486,1,0,0,0,487,488,1,0,0,0,488,489,1,0,0,0,489, + 490,5,47,0,0,490,491,5,149,0,0,491,493,5,135,0,0,492,494,5,149,0,0,493, + 492,1,0,0,0,493,494,1,0,0,0,494,495,1,0,0,0,495,497,5,4,0,0,496,483,1, + 0,0,0,496,497,1,0,0,0,497,21,1,0,0,0,498,499,5,95,0,0,499,500,5,149,0, + 0,500,501,3,284,142,0,501,23,1,0,0,0,502,503,5,48,0,0,503,504,5,149,0, + 0,504,506,3,286,143,0,505,507,5,149,0,0,506,505,1,0,0,0,506,507,1,0,0, + 0,507,508,1,0,0,0,508,510,5,5,0,0,509,511,5,149,0,0,510,509,1,0,0,0,510, + 511,1,0,0,0,511,512,1,0,0,0,512,513,3,238,119,0,513,25,1,0,0,0,514,515, + 5,49,0,0,515,516,5,149,0,0,516,517,5,93,0,0,517,518,5,149,0,0,518,519, + 5,59,0,0,519,520,5,149,0,0,520,521,3,284,142,0,521,522,5,149,0,0,522, + 523,5,124,0,0,523,524,5,149,0,0,524,525,5,135,0,0,525,27,1,0,0,0,526, + 527,5,91,0,0,527,528,5,149,0,0,528,529,5,50,0,0,529,530,5,149,0,0,530, + 532,3,254,127,0,531,533,5,149,0,0,532,531,1,0,0,0,532,533,1,0,0,0,533, + 534,1,0,0,0,534,536,5,2,0,0,535,537,5,149,0,0,536,535,1,0,0,0,536,537, + 1,0,0,0,537,539,1,0,0,0,538,540,3,30,15,0,539,538,1,0,0,0,539,540,1,0, + 0,0,540,542,1,0,0,0,541,543,5,149,0,0,542,541,1,0,0,0,542,543,1,0,0,0, + 543,545,1,0,0,0,544,546,3,32,16,0,545,544,1,0,0,0,545,546,1,0,0,0,546, + 557,1,0,0,0,547,549,5,149,0,0,548,547,1,0,0,0,548,549,1,0,0,0,549,550, + 1,0,0,0,550,552,5,3,0,0,551,553,5,149,0,0,552,551,1,0,0,0,552,553,1,0, + 0,0,553,554,1,0,0,0,554,556,3,32,16,0,555,548,1,0,0,0,556,559,1,0,0,0, + 557,555,1,0,0,0,557,558,1,0,0,0,558,561,1,0,0,0,559,557,1,0,0,0,560,562, + 5,149,0,0,561,560,1,0,0,0,561,562,1,0,0,0,562,563,1,0,0,0,563,564,5,4, + 0,0,564,565,5,149,0,0,565,566,5,101,0,0,566,567,5,149,0,0,567,568,3,190, + 95,0,568,29,1,0,0,0,569,580,3,286,143,0,570,572,5,149,0,0,571,570,1,0, + 0,0,571,572,1,0,0,0,572,573,1,0,0,0,573,575,5,3,0,0,574,576,5,149,0,0, + 575,574,1,0,0,0,575,576,1,0,0,0,576,577,1,0,0,0,577,579,3,286,143,0,578, + 571,1,0,0,0,579,582,1,0,0,0,580,578,1,0,0,0,580,581,1,0,0,0,581,31,1, + 0,0,0,582,580,1,0,0,0,583,585,3,286,143,0,584,586,5,149,0,0,585,584,1, + 0,0,0,585,586,1,0,0,0,586,587,1,0,0,0,587,588,5,119,0,0,588,590,5,5,0, + 0,589,591,5,149,0,0,590,589,1,0,0,0,590,591,1,0,0,0,591,592,1,0,0,0,592, + 593,3,238,119,0,593,33,1,0,0,0,594,596,5,6,0,0,595,597,5,149,0,0,596, + 595,1,0,0,0,596,597,1,0,0,0,597,598,1,0,0,0,598,609,5,135,0,0,599,601, + 5,149,0,0,600,599,1,0,0,0,600,601,1,0,0,0,601,602,1,0,0,0,602,604,5,3, + 0,0,603,605,5,149,0,0,604,603,1,0,0,0,604,605,1,0,0,0,605,606,1,0,0,0, + 606,608,5,135,0,0,607,600,1,0,0,0,608,611,1,0,0,0,609,607,1,0,0,0,609, + 610,1,0,0,0,610,612,1,0,0,0,611,609,1,0,0,0,612,628,5,7,0,0,613,628,5, + 135,0,0,614,616,5,51,0,0,615,617,5,149,0,0,616,615,1,0,0,0,616,617,1, + 0,0,0,617,618,1,0,0,0,618,620,5,2,0,0,619,621,5,149,0,0,620,619,1,0,0, + 0,620,621,1,0,0,0,621,622,1,0,0,0,622,624,5,135,0,0,623,625,5,149,0,0, + 624,623,1,0,0,0,624,625,1,0,0,0,625,626,1,0,0,0,626,628,5,4,0,0,627,594, + 1,0,0,0,627,613,1,0,0,0,627,614,1,0,0,0,628,35,1,0,0,0,629,631,5,2,0, + 0,630,632,5,149,0,0,631,630,1,0,0,0,631,632,1,0,0,0,632,633,1,0,0,0,633, + 644,3,38,19,0,634,636,5,149,0,0,635,634,1,0,0,0,635,636,1,0,0,0,636,637, + 1,0,0,0,637,639,5,3,0,0,638,640,5,149,0,0,639,638,1,0,0,0,639,640,1,0, + 0,0,640,641,1,0,0,0,641,643,3,38,19,0,642,635,1,0,0,0,643,646,1,0,0,0, + 644,642,1,0,0,0,644,645,1,0,0,0,645,648,1,0,0,0,646,644,1,0,0,0,647,649, + 5,149,0,0,648,647,1,0,0,0,648,649,1,0,0,0,649,650,1,0,0,0,650,651,5,4, + 0,0,651,37,1,0,0,0,652,654,3,286,143,0,653,655,5,149,0,0,654,653,1,0, + 0,0,654,655,1,0,0,0,655,656,1,0,0,0,656,658,5,5,0,0,657,659,5,149,0,0, + 658,657,1,0,0,0,658,659,1,0,0,0,659,660,1,0,0,0,660,661,3,238,119,0,661, + 39,1,0,0,0,662,669,3,42,21,0,663,669,3,44,22,0,664,669,3,46,23,0,665, + 669,3,50,25,0,666,669,3,52,26,0,667,669,3,54,27,0,668,662,1,0,0,0,668, + 663,1,0,0,0,668,664,1,0,0,0,668,665,1,0,0,0,668,666,1,0,0,0,668,667,1, + 0,0,0,669,41,1,0,0,0,670,671,5,91,0,0,671,672,5,149,0,0,672,673,5,58, + 0,0,673,674,5,149,0,0,674,675,5,59,0,0,675,676,5,149,0,0,676,678,3,284, + 142,0,677,679,5,149,0,0,678,677,1,0,0,0,678,679,1,0,0,0,679,680,1,0,0, + 0,680,682,5,2,0,0,681,683,5,149,0,0,682,681,1,0,0,0,682,683,1,0,0,0,683, + 684,1,0,0,0,684,686,3,66,33,0,685,687,5,149,0,0,686,685,1,0,0,0,686,687, + 1,0,0,0,687,688,1,0,0,0,688,690,5,3,0,0,689,691,5,149,0,0,690,689,1,0, + 0,0,690,691,1,0,0,0,691,692,1,0,0,0,692,693,3,70,35,0,693,695,1,0,0,0, + 694,696,5,149,0,0,695,694,1,0,0,0,695,696,1,0,0,0,696,697,1,0,0,0,697, + 698,5,4,0,0,698,43,1,0,0,0,699,700,5,91,0,0,700,701,5,149,0,0,701,702, + 5,69,0,0,702,703,5,149,0,0,703,704,5,59,0,0,704,705,5,149,0,0,705,707, + 3,284,142,0,706,708,5,149,0,0,707,706,1,0,0,0,707,708,1,0,0,0,708,709, + 1,0,0,0,709,711,5,2,0,0,710,712,5,149,0,0,711,710,1,0,0,0,711,712,1,0, + 0,0,712,713,1,0,0,0,713,715,3,48,24,0,714,716,5,149,0,0,715,714,1,0,0, + 0,715,716,1,0,0,0,716,725,1,0,0,0,717,719,5,3,0,0,718,720,5,149,0,0,719, + 718,1,0,0,0,719,720,1,0,0,0,720,721,1,0,0,0,721,723,3,66,33,0,722,724, + 5,149,0,0,723,722,1,0,0,0,723,724,1,0,0,0,724,726,1,0,0,0,725,717,1,0, + 0,0,725,726,1,0,0,0,726,735,1,0,0,0,727,729,5,3,0,0,728,730,5,149,0,0, + 729,728,1,0,0,0,729,730,1,0,0,0,730,731,1,0,0,0,731,733,3,286,143,0,732, + 734,5,149,0,0,733,732,1,0,0,0,733,734,1,0,0,0,734,736,1,0,0,0,735,727, + 1,0,0,0,735,736,1,0,0,0,736,737,1,0,0,0,737,738,5,4,0,0,738,45,1,0,0, + 0,739,740,5,91,0,0,740,741,5,149,0,0,741,742,5,69,0,0,742,743,5,149,0, + 0,743,744,5,59,0,0,744,745,5,149,0,0,745,746,5,60,0,0,746,747,5,149,0, + 0,747,749,3,284,142,0,748,750,5,149,0,0,749,748,1,0,0,0,749,750,1,0,0, + 0,750,751,1,0,0,0,751,753,5,2,0,0,752,754,5,149,0,0,753,752,1,0,0,0,753, + 754,1,0,0,0,754,755,1,0,0,0,755,757,3,48,24,0,756,758,5,149,0,0,757,756, + 1,0,0,0,757,758,1,0,0,0,758,764,1,0,0,0,759,761,5,3,0,0,760,762,5,149, + 0,0,761,760,1,0,0,0,761,762,1,0,0,0,762,763,1,0,0,0,763,765,3,48,24,0, + 764,759,1,0,0,0,765,766,1,0,0,0,766,764,1,0,0,0,766,767,1,0,0,0,767,769, + 1,0,0,0,768,770,5,149,0,0,769,768,1,0,0,0,769,770,1,0,0,0,770,779,1,0, + 0,0,771,773,5,3,0,0,772,774,5,149,0,0,773,772,1,0,0,0,773,774,1,0,0,0, + 774,775,1,0,0,0,775,777,3,66,33,0,776,778,5,149,0,0,777,776,1,0,0,0,777, + 778,1,0,0,0,778,780,1,0,0,0,779,771,1,0,0,0,779,780,1,0,0,0,780,789,1, + 0,0,0,781,783,5,3,0,0,782,784,5,149,0,0,783,782,1,0,0,0,783,784,1,0,0, + 0,784,785,1,0,0,0,785,787,3,286,143,0,786,788,5,149,0,0,787,786,1,0,0, + 0,787,788,1,0,0,0,788,790,1,0,0,0,789,781,1,0,0,0,789,790,1,0,0,0,790, + 791,1,0,0,0,791,792,5,4,0,0,792,47,1,0,0,0,793,794,5,53,0,0,794,795,5, + 149,0,0,795,796,3,284,142,0,796,797,5,149,0,0,797,798,5,70,0,0,798,799, + 5,149,0,0,799,800,3,284,142,0,800,49,1,0,0,0,801,802,5,91,0,0,802,803, + 5,149,0,0,803,804,5,61,0,0,804,805,5,149,0,0,805,806,3,284,142,0,806, + 51,1,0,0,0,807,808,5,62,0,0,808,809,5,149,0,0,809,810,7,0,0,0,810,811, + 5,149,0,0,811,812,3,284,142,0,812,53,1,0,0,0,813,814,5,63,0,0,814,815, + 5,149,0,0,815,816,5,59,0,0,816,817,5,149,0,0,817,818,3,284,142,0,818, + 819,5,149,0,0,819,820,3,56,28,0,820,55,1,0,0,0,821,826,3,58,29,0,822, + 826,3,60,30,0,823,826,3,62,31,0,824,826,3,64,32,0,825,821,1,0,0,0,825, + 822,1,0,0,0,825,823,1,0,0,0,825,824,1,0,0,0,826,57,1,0,0,0,827,828,5, + 66,0,0,828,829,5,149,0,0,829,830,3,278,139,0,830,831,5,149,0,0,831,836, + 3,72,36,0,832,833,5,149,0,0,833,834,5,64,0,0,834,835,5,149,0,0,835,837, + 3,190,95,0,836,832,1,0,0,0,836,837,1,0,0,0,837,59,1,0,0,0,838,839,5,62, + 0,0,839,840,5,149,0,0,840,841,3,278,139,0,841,61,1,0,0,0,842,843,5,65, + 0,0,843,844,5,149,0,0,844,845,5,70,0,0,845,846,5,149,0,0,846,847,3,284, + 142,0,847,63,1,0,0,0,848,849,5,65,0,0,849,850,5,149,0,0,850,851,3,278, + 139,0,851,852,5,149,0,0,852,853,5,70,0,0,853,854,5,149,0,0,854,855,3, + 278,139,0,855,65,1,0,0,0,856,867,3,68,34,0,857,859,5,149,0,0,858,857, + 1,0,0,0,858,859,1,0,0,0,859,860,1,0,0,0,860,862,5,3,0,0,861,863,5,149, + 0,0,862,861,1,0,0,0,862,863,1,0,0,0,863,864,1,0,0,0,864,866,3,68,34,0, + 865,858,1,0,0,0,866,869,1,0,0,0,867,865,1,0,0,0,867,868,1,0,0,0,868,67, + 1,0,0,0,869,867,1,0,0,0,870,871,3,278,139,0,871,872,5,149,0,0,872,873, + 3,72,36,0,873,69,1,0,0,0,874,875,5,67,0,0,875,876,5,149,0,0,876,878,5, + 68,0,0,877,879,5,149,0,0,878,877,1,0,0,0,878,879,1,0,0,0,879,880,1,0, + 0,0,880,882,5,2,0,0,881,883,5,149,0,0,882,881,1,0,0,0,882,883,1,0,0,0, + 883,884,1,0,0,0,884,886,3,278,139,0,885,887,5,149,0,0,886,885,1,0,0,0, + 886,887,1,0,0,0,887,888,1,0,0,0,888,889,5,4,0,0,889,71,1,0,0,0,890,891, + 6,36,-1,0,891,943,3,286,143,0,892,894,5,84,0,0,893,895,5,149,0,0,894, + 893,1,0,0,0,894,895,1,0,0,0,895,896,1,0,0,0,896,898,5,2,0,0,897,899,5, + 149,0,0,898,897,1,0,0,0,898,899,1,0,0,0,899,900,1,0,0,0,900,902,3,66, + 33,0,901,903,5,149,0,0,902,901,1,0,0,0,902,903,1,0,0,0,903,904,1,0,0, + 0,904,905,5,4,0,0,905,943,1,0,0,0,906,908,3,286,143,0,907,909,5,149,0, + 0,908,907,1,0,0,0,908,909,1,0,0,0,909,910,1,0,0,0,910,912,5,2,0,0,911, + 913,5,149,0,0,912,911,1,0,0,0,912,913,1,0,0,0,913,914,1,0,0,0,914,916, + 3,66,33,0,915,917,5,149,0,0,916,915,1,0,0,0,916,917,1,0,0,0,917,918,1, + 0,0,0,918,919,5,4,0,0,919,943,1,0,0,0,920,922,3,286,143,0,921,923,5,149, + 0,0,922,921,1,0,0,0,922,923,1,0,0,0,923,924,1,0,0,0,924,926,5,2,0,0,925, + 927,5,149,0,0,926,925,1,0,0,0,926,927,1,0,0,0,927,928,1,0,0,0,928,930, + 3,72,36,0,929,931,5,149,0,0,930,929,1,0,0,0,930,931,1,0,0,0,931,932,1, + 0,0,0,932,934,5,3,0,0,933,935,5,149,0,0,934,933,1,0,0,0,934,935,1,0,0, + 0,935,936,1,0,0,0,936,938,3,72,36,0,937,939,5,149,0,0,938,937,1,0,0,0, + 938,939,1,0,0,0,939,940,1,0,0,0,940,941,5,4,0,0,941,943,1,0,0,0,942,890, + 1,0,0,0,942,892,1,0,0,0,942,906,1,0,0,0,942,920,1,0,0,0,943,948,1,0,0, + 0,944,945,10,4,0,0,945,947,3,74,37,0,946,944,1,0,0,0,947,950,1,0,0,0, + 948,946,1,0,0,0,948,949,1,0,0,0,949,73,1,0,0,0,950,948,1,0,0,0,951,955, + 3,76,38,0,952,954,3,76,38,0,953,952,1,0,0,0,954,957,1,0,0,0,955,953,1, + 0,0,0,955,956,1,0,0,0,956,75,1,0,0,0,957,955,1,0,0,0,958,960,5,6,0,0, + 959,961,3,280,140,0,960,959,1,0,0,0,960,961,1,0,0,0,961,962,1,0,0,0,962, + 963,5,7,0,0,963,77,1,0,0,0,964,967,3,80,40,0,965,967,3,82,41,0,966,964, + 1,0,0,0,966,965,1,0,0,0,967,79,1,0,0,0,968,969,5,71,0,0,969,81,1,0,0, + 0,970,971,5,72,0,0,971,83,1,0,0,0,972,973,5,73,0,0,973,974,5,149,0,0, + 974,987,5,74,0,0,975,976,5,73,0,0,976,977,5,149,0,0,977,978,5,74,0,0, + 978,979,5,149,0,0,979,980,5,75,0,0,980,981,5,149,0,0,981,987,5,76,0,0, + 982,987,5,78,0,0,983,987,5,79,0,0,984,987,5,80,0,0,985,987,5,81,0,0,986, + 972,1,0,0,0,986,975,1,0,0,0,986,982,1,0,0,0,986,983,1,0,0,0,986,984,1, + 0,0,0,986,985,1,0,0,0,987,85,1,0,0,0,988,991,3,88,44,0,989,991,3,90,45, + 0,990,988,1,0,0,0,990,989,1,0,0,0,991,87,1,0,0,0,992,993,5,86,0,0,993, + 994,5,149,0,0,994,995,5,83,0,0,995,998,5,149,0,0,996,999,5,135,0,0,997, + 999,3,270,135,0,998,996,1,0,0,0,998,997,1,0,0,0,999,89,1,0,0,0,1000,1001, + 5,82,0,0,1001,1002,5,149,0,0,1002,1003,3,270,135,0,1003,91,1,0,0,0,1004, + 1005,3,94,47,0,1005,93,1,0,0,0,1006,1013,3,98,49,0,1007,1009,5,149,0, + 0,1008,1007,1,0,0,0,1008,1009,1,0,0,0,1009,1010,1,0,0,0,1010,1012,3,96, + 48,0,1011,1008,1,0,0,0,1012,1015,1,0,0,0,1013,1011,1,0,0,0,1013,1014, + 1,0,0,0,1014,1028,1,0,0,0,1015,1013,1,0,0,0,1016,1018,3,132,66,0,1017, + 1019,5,149,0,0,1018,1017,1,0,0,0,1018,1019,1,0,0,0,1019,1021,1,0,0,0, + 1020,1016,1,0,0,0,1021,1022,1,0,0,0,1022,1020,1,0,0,0,1022,1023,1,0,0, + 0,1023,1024,1,0,0,0,1024,1025,3,98,49,0,1025,1026,6,47,-1,0,1026,1028, + 1,0,0,0,1027,1006,1,0,0,0,1027,1020,1,0,0,0,1028,95,1,0,0,0,1029,1030, + 5,84,0,0,1030,1031,5,149,0,0,1031,1033,5,85,0,0,1032,1034,5,149,0,0,1033, + 1032,1,0,0,0,1033,1034,1,0,0,0,1034,1035,1,0,0,0,1035,1042,3,98,49,0, + 1036,1038,5,84,0,0,1037,1039,5,149,0,0,1038,1037,1,0,0,0,1038,1039,1, + 0,0,0,1039,1040,1,0,0,0,1040,1042,3,98,49,0,1041,1029,1,0,0,0,1041,1036, + 1,0,0,0,1042,97,1,0,0,0,1043,1046,3,100,50,0,1044,1046,3,102,51,0,1045, + 1043,1,0,0,0,1045,1044,1,0,0,0,1046,99,1,0,0,0,1047,1049,3,108,54,0,1048, + 1050,5,149,0,0,1049,1048,1,0,0,0,1049,1050,1,0,0,0,1050,1052,1,0,0,0, + 1051,1047,1,0,0,0,1052,1055,1,0,0,0,1053,1051,1,0,0,0,1053,1054,1,0,0, + 0,1054,1056,1,0,0,0,1055,1053,1,0,0,0,1056,1093,3,132,66,0,1057,1059, + 3,108,54,0,1058,1060,5,149,0,0,1059,1058,1,0,0,0,1059,1060,1,0,0,0,1060, + 1062,1,0,0,0,1061,1057,1,0,0,0,1062,1065,1,0,0,0,1063,1061,1,0,0,0,1063, + 1064,1,0,0,0,1064,1066,1,0,0,0,1065,1063,1,0,0,0,1066,1073,3,106,53,0, + 1067,1069,5,149,0,0,1068,1067,1,0,0,0,1068,1069,1,0,0,0,1069,1070,1,0, + 0,0,1070,1072,3,106,53,0,1071,1068,1,0,0,0,1072,1075,1,0,0,0,1073,1071, + 1,0,0,0,1073,1074,1,0,0,0,1074,1080,1,0,0,0,1075,1073,1,0,0,0,1076,1078, + 5,149,0,0,1077,1076,1,0,0,0,1077,1078,1,0,0,0,1078,1079,1,0,0,0,1079, + 1081,3,132,66,0,1080,1077,1,0,0,0,1080,1081,1,0,0,0,1081,1093,1,0,0,0, + 1082,1084,3,108,54,0,1083,1085,5,149,0,0,1084,1083,1,0,0,0,1084,1085, + 1,0,0,0,1085,1087,1,0,0,0,1086,1082,1,0,0,0,1087,1088,1,0,0,0,1088,1086, + 1,0,0,0,1088,1089,1,0,0,0,1089,1090,1,0,0,0,1090,1091,6,50,-1,0,1091, + 1093,1,0,0,0,1092,1053,1,0,0,0,1092,1063,1,0,0,0,1092,1086,1,0,0,0,1093, + 101,1,0,0,0,1094,1096,3,104,52,0,1095,1097,5,149,0,0,1096,1095,1,0,0, + 0,1096,1097,1,0,0,0,1097,1099,1,0,0,0,1098,1094,1,0,0,0,1099,1100,1,0, + 0,0,1100,1098,1,0,0,0,1100,1101,1,0,0,0,1101,1102,1,0,0,0,1102,1103,3, + 100,50,0,1103,103,1,0,0,0,1104,1106,3,108,54,0,1105,1107,5,149,0,0,1106, + 1105,1,0,0,0,1106,1107,1,0,0,0,1107,1109,1,0,0,0,1108,1104,1,0,0,0,1109, + 1112,1,0,0,0,1110,1108,1,0,0,0,1110,1111,1,0,0,0,1111,1119,1,0,0,0,1112, + 1110,1,0,0,0,1113,1115,3,106,53,0,1114,1116,5,149,0,0,1115,1114,1,0,0, + 0,1115,1116,1,0,0,0,1116,1118,1,0,0,0,1117,1113,1,0,0,0,1118,1121,1,0, + 0,0,1119,1117,1,0,0,0,1119,1120,1,0,0,0,1120,1122,1,0,0,0,1121,1119,1, + 0,0,0,1122,1123,3,130,65,0,1123,105,1,0,0,0,1124,1129,3,118,59,0,1125, + 1129,3,120,60,0,1126,1129,3,124,62,0,1127,1129,3,128,64,0,1128,1124,1, + 0,0,0,1128,1125,1,0,0,0,1128,1126,1,0,0,0,1128,1127,1,0,0,0,1129,107, + 1,0,0,0,1130,1135,3,114,57,0,1131,1135,3,116,58,0,1132,1135,3,112,56, + 0,1133,1135,3,110,55,0,1134,1130,1,0,0,0,1134,1131,1,0,0,0,1134,1132, + 1,0,0,0,1134,1133,1,0,0,0,1135,109,1,0,0,0,1136,1154,5,86,0,0,1137,1138, + 5,149,0,0,1138,1139,5,97,0,0,1139,1140,5,149,0,0,1140,1142,5,87,0,0,1141, + 1143,5,149,0,0,1142,1141,1,0,0,0,1142,1143,1,0,0,0,1143,1144,1,0,0,0, + 1144,1146,5,2,0,0,1145,1147,5,149,0,0,1146,1145,1,0,0,0,1146,1147,1,0, + 0,0,1147,1148,1,0,0,0,1148,1150,3,66,33,0,1149,1151,5,149,0,0,1150,1149, + 1,0,0,0,1150,1151,1,0,0,0,1151,1152,1,0,0,0,1152,1153,5,4,0,0,1153,1155, + 1,0,0,0,1154,1137,1,0,0,0,1154,1155,1,0,0,0,1155,1156,1,0,0,0,1156,1157, + 5,149,0,0,1157,1158,5,53,0,0,1158,1159,5,149,0,0,1159,1164,3,10,5,0,1160, + 1162,5,149,0,0,1161,1160,1,0,0,0,1161,1162,1,0,0,0,1162,1163,1,0,0,0, + 1163,1165,3,36,18,0,1164,1161,1,0,0,0,1164,1165,1,0,0,0,1165,1170,1,0, + 0,0,1166,1168,5,149,0,0,1167,1166,1,0,0,0,1167,1168,1,0,0,0,1168,1169, + 1,0,0,0,1169,1171,3,148,74,0,1170,1167,1,0,0,0,1170,1171,1,0,0,0,1171, + 111,1,0,0,0,1172,1173,5,48,0,0,1173,1174,5,149,0,0,1174,1179,3,252,126, + 0,1175,1177,5,149,0,0,1176,1175,1,0,0,0,1176,1177,1,0,0,0,1177,1178,1, + 0,0,0,1178,1180,3,148,74,0,1179,1176,1,0,0,0,1179,1180,1,0,0,0,1180,113, + 1,0,0,0,1181,1182,5,88,0,0,1182,1184,5,149,0,0,1183,1181,1,0,0,0,1183, + 1184,1,0,0,0,1184,1185,1,0,0,0,1185,1187,5,89,0,0,1186,1188,5,149,0,0, + 1187,1186,1,0,0,0,1187,1188,1,0,0,0,1188,1189,1,0,0,0,1189,1194,3,150, + 75,0,1190,1192,5,149,0,0,1191,1190,1,0,0,0,1191,1192,1,0,0,0,1192,1193, + 1,0,0,0,1193,1195,3,148,74,0,1194,1191,1,0,0,0,1194,1195,1,0,0,0,1195, + 115,1,0,0,0,1196,1198,5,90,0,0,1197,1199,5,149,0,0,1198,1197,1,0,0,0, + 1198,1199,1,0,0,0,1199,1200,1,0,0,0,1200,1201,3,190,95,0,1201,1202,5, + 149,0,0,1202,1203,5,101,0,0,1203,1204,5,149,0,0,1204,1205,3,270,135,0, + 1205,117,1,0,0,0,1206,1208,5,91,0,0,1207,1209,5,149,0,0,1208,1207,1,0, + 0,0,1208,1209,1,0,0,0,1209,1210,1,0,0,0,1210,1211,3,150,75,0,1211,119, + 1,0,0,0,1212,1214,5,92,0,0,1213,1215,5,149,0,0,1214,1213,1,0,0,0,1214, + 1215,1,0,0,0,1215,1216,1,0,0,0,1216,1221,3,150,75,0,1217,1218,5,149,0, + 0,1218,1220,3,122,61,0,1219,1217,1,0,0,0,1220,1223,1,0,0,0,1221,1219, + 1,0,0,0,1221,1222,1,0,0,0,1222,121,1,0,0,0,1223,1221,1,0,0,0,1224,1225, + 5,93,0,0,1225,1226,5,149,0,0,1226,1227,5,89,0,0,1227,1228,5,149,0,0,1228, + 1235,3,124,62,0,1229,1230,5,93,0,0,1230,1231,5,149,0,0,1231,1232,5,91, + 0,0,1232,1233,5,149,0,0,1233,1235,3,124,62,0,1234,1224,1,0,0,0,1234,1229, + 1,0,0,0,1235,123,1,0,0,0,1236,1238,5,94,0,0,1237,1239,5,149,0,0,1238, + 1237,1,0,0,0,1238,1239,1,0,0,0,1239,1240,1,0,0,0,1240,1251,3,126,63,0, + 1241,1243,5,149,0,0,1242,1241,1,0,0,0,1242,1243,1,0,0,0,1243,1244,1,0, + 0,0,1244,1246,5,3,0,0,1245,1247,5,149,0,0,1246,1245,1,0,0,0,1246,1247, + 1,0,0,0,1247,1248,1,0,0,0,1248,1250,3,126,63,0,1249,1242,1,0,0,0,1250, + 1253,1,0,0,0,1251,1249,1,0,0,0,1251,1252,1,0,0,0,1252,125,1,0,0,0,1253, + 1251,1,0,0,0,1254,1256,3,276,138,0,1255,1257,5,149,0,0,1256,1255,1,0, + 0,0,1256,1257,1,0,0,0,1257,1258,1,0,0,0,1258,1260,5,5,0,0,1259,1261,5, + 149,0,0,1260,1259,1,0,0,0,1260,1261,1,0,0,0,1261,1262,1,0,0,0,1262,1263, + 3,190,95,0,1263,127,1,0,0,0,1264,1265,5,95,0,0,1265,1267,5,149,0,0,1266, + 1264,1,0,0,0,1266,1267,1,0,0,0,1267,1268,1,0,0,0,1268,1270,5,96,0,0,1269, + 1271,5,149,0,0,1270,1269,1,0,0,0,1270,1271,1,0,0,0,1271,1272,1,0,0,0, + 1272,1283,3,190,95,0,1273,1275,5,149,0,0,1274,1273,1,0,0,0,1274,1275, + 1,0,0,0,1275,1276,1,0,0,0,1276,1278,5,3,0,0,1277,1279,5,149,0,0,1278, + 1277,1,0,0,0,1278,1279,1,0,0,0,1279,1280,1,0,0,0,1280,1282,3,190,95,0, + 1281,1274,1,0,0,0,1282,1285,1,0,0,0,1283,1281,1,0,0,0,1283,1284,1,0,0, + 0,1284,129,1,0,0,0,1285,1283,1,0,0,0,1286,1287,5,97,0,0,1287,1292,3,134, + 67,0,1288,1290,5,149,0,0,1289,1288,1,0,0,0,1289,1290,1,0,0,0,1290,1291, + 1,0,0,0,1291,1293,3,148,74,0,1292,1289,1,0,0,0,1292,1293,1,0,0,0,1293, + 131,1,0,0,0,1294,1295,5,98,0,0,1295,1296,3,134,67,0,1296,133,1,0,0,0, + 1297,1299,5,149,0,0,1298,1297,1,0,0,0,1298,1299,1,0,0,0,1299,1300,1,0, + 0,0,1300,1302,5,99,0,0,1301,1298,1,0,0,0,1301,1302,1,0,0,0,1302,1303, + 1,0,0,0,1303,1304,5,149,0,0,1304,1307,3,136,68,0,1305,1306,5,149,0,0, + 1306,1308,3,140,70,0,1307,1305,1,0,0,0,1307,1308,1,0,0,0,1308,1311,1, + 0,0,0,1309,1310,5,149,0,0,1310,1312,3,142,71,0,1311,1309,1,0,0,0,1311, + 1312,1,0,0,0,1312,1315,1,0,0,0,1313,1314,5,149,0,0,1314,1316,3,144,72, + 0,1315,1313,1,0,0,0,1315,1316,1,0,0,0,1316,135,1,0,0,0,1317,1328,5,100, + 0,0,1318,1320,5,149,0,0,1319,1318,1,0,0,0,1319,1320,1,0,0,0,1320,1321, + 1,0,0,0,1321,1323,5,3,0,0,1322,1324,5,149,0,0,1323,1322,1,0,0,0,1323, + 1324,1,0,0,0,1324,1325,1,0,0,0,1325,1327,3,138,69,0,1326,1319,1,0,0,0, + 1327,1330,1,0,0,0,1328,1326,1,0,0,0,1328,1329,1,0,0,0,1329,1346,1,0,0, + 0,1330,1328,1,0,0,0,1331,1342,3,138,69,0,1332,1334,5,149,0,0,1333,1332, + 1,0,0,0,1333,1334,1,0,0,0,1334,1335,1,0,0,0,1335,1337,5,3,0,0,1336,1338, + 5,149,0,0,1337,1336,1,0,0,0,1337,1338,1,0,0,0,1338,1339,1,0,0,0,1339, + 1341,3,138,69,0,1340,1333,1,0,0,0,1341,1344,1,0,0,0,1342,1340,1,0,0,0, + 1342,1343,1,0,0,0,1343,1346,1,0,0,0,1344,1342,1,0,0,0,1345,1317,1,0,0, + 0,1345,1331,1,0,0,0,1346,137,1,0,0,0,1347,1348,3,190,95,0,1348,1349,5, + 149,0,0,1349,1350,5,101,0,0,1350,1351,5,149,0,0,1351,1352,3,270,135,0, + 1352,1355,1,0,0,0,1353,1355,3,190,95,0,1354,1347,1,0,0,0,1354,1353,1, + 0,0,0,1355,139,1,0,0,0,1356,1357,5,102,0,0,1357,1358,5,149,0,0,1358,1359, + 5,103,0,0,1359,1360,5,149,0,0,1360,1368,3,146,73,0,1361,1363,5,3,0,0, + 1362,1364,5,149,0,0,1363,1362,1,0,0,0,1363,1364,1,0,0,0,1364,1365,1,0, + 0,0,1365,1367,3,146,73,0,1366,1361,1,0,0,0,1367,1370,1,0,0,0,1368,1366, + 1,0,0,0,1368,1369,1,0,0,0,1369,141,1,0,0,0,1370,1368,1,0,0,0,1371,1372, + 5,104,0,0,1372,1373,5,149,0,0,1373,1374,3,190,95,0,1374,143,1,0,0,0,1375, + 1376,5,105,0,0,1376,1377,5,149,0,0,1377,1378,3,190,95,0,1378,145,1,0, + 0,0,1379,1384,3,190,95,0,1380,1382,5,149,0,0,1381,1380,1,0,0,0,1381,1382, + 1,0,0,0,1382,1383,1,0,0,0,1383,1385,7,1,0,0,1384,1381,1,0,0,0,1384,1385, + 1,0,0,0,1385,147,1,0,0,0,1386,1387,5,110,0,0,1387,1388,5,149,0,0,1388, + 1389,3,190,95,0,1389,149,1,0,0,0,1390,1401,3,152,76,0,1391,1393,5,149, + 0,0,1392,1391,1,0,0,0,1392,1393,1,0,0,0,1393,1394,1,0,0,0,1394,1396,5, + 3,0,0,1395,1397,5,149,0,0,1396,1395,1,0,0,0,1396,1397,1,0,0,0,1397,1398, + 1,0,0,0,1398,1400,3,152,76,0,1399,1392,1,0,0,0,1400,1403,1,0,0,0,1401, + 1399,1,0,0,0,1401,1402,1,0,0,0,1402,151,1,0,0,0,1403,1401,1,0,0,0,1404, + 1406,3,270,135,0,1405,1407,5,149,0,0,1406,1405,1,0,0,0,1406,1407,1,0, + 0,0,1407,1408,1,0,0,0,1408,1410,5,5,0,0,1409,1411,5,149,0,0,1410,1409, + 1,0,0,0,1410,1411,1,0,0,0,1411,1412,1,0,0,0,1412,1413,3,154,77,0,1413, + 1416,1,0,0,0,1414,1416,3,154,77,0,1415,1404,1,0,0,0,1415,1414,1,0,0,0, + 1416,153,1,0,0,0,1417,1418,3,156,78,0,1418,155,1,0,0,0,1419,1426,3,158, + 79,0,1420,1422,5,149,0,0,1421,1420,1,0,0,0,1421,1422,1,0,0,0,1422,1423, + 1,0,0,0,1423,1425,3,160,80,0,1424,1421,1,0,0,0,1425,1428,1,0,0,0,1426, + 1424,1,0,0,0,1426,1427,1,0,0,0,1427,1434,1,0,0,0,1428,1426,1,0,0,0,1429, + 1430,5,2,0,0,1430,1431,3,156,78,0,1431,1432,5,4,0,0,1432,1434,1,0,0,0, + 1433,1419,1,0,0,0,1433,1429,1,0,0,0,1434,157,1,0,0,0,1435,1437,5,2,0, + 0,1436,1438,5,149,0,0,1437,1436,1,0,0,0,1437,1438,1,0,0,0,1438,1443,1, + 0,0,0,1439,1441,3,270,135,0,1440,1442,5,149,0,0,1441,1440,1,0,0,0,1441, + 1442,1,0,0,0,1442,1444,1,0,0,0,1443,1439,1,0,0,0,1443,1444,1,0,0,0,1444, + 1449,1,0,0,0,1445,1447,3,170,85,0,1446,1448,5,149,0,0,1447,1446,1,0,0, + 0,1447,1448,1,0,0,0,1448,1450,1,0,0,0,1449,1445,1,0,0,0,1449,1450,1,0, + 0,0,1450,1455,1,0,0,0,1451,1453,3,166,83,0,1452,1454,5,149,0,0,1453,1452, + 1,0,0,0,1453,1454,1,0,0,0,1454,1456,1,0,0,0,1455,1451,1,0,0,0,1455,1456, + 1,0,0,0,1456,1457,1,0,0,0,1457,1458,5,4,0,0,1458,159,1,0,0,0,1459,1461, + 3,162,81,0,1460,1462,5,149,0,0,1461,1460,1,0,0,0,1461,1462,1,0,0,0,1462, + 1463,1,0,0,0,1463,1464,3,158,79,0,1464,161,1,0,0,0,1465,1467,3,290,145, + 0,1466,1468,5,149,0,0,1467,1466,1,0,0,0,1467,1468,1,0,0,0,1468,1469,1, + 0,0,0,1469,1471,3,294,147,0,1470,1472,5,149,0,0,1471,1470,1,0,0,0,1471, + 1472,1,0,0,0,1472,1474,1,0,0,0,1473,1475,3,164,82,0,1474,1473,1,0,0,0, + 1474,1475,1,0,0,0,1475,1477,1,0,0,0,1476,1478,5,149,0,0,1477,1476,1,0, + 0,0,1477,1478,1,0,0,0,1478,1479,1,0,0,0,1479,1480,3,294,147,0,1480,1510, + 1,0,0,0,1481,1483,3,294,147,0,1482,1484,5,149,0,0,1483,1482,1,0,0,0,1483, + 1484,1,0,0,0,1484,1486,1,0,0,0,1485,1487,3,164,82,0,1486,1485,1,0,0,0, + 1486,1487,1,0,0,0,1487,1489,1,0,0,0,1488,1490,5,149,0,0,1489,1488,1,0, + 0,0,1489,1490,1,0,0,0,1490,1491,1,0,0,0,1491,1493,3,294,147,0,1492,1494, + 5,149,0,0,1493,1492,1,0,0,0,1493,1494,1,0,0,0,1494,1495,1,0,0,0,1495, + 1496,3,292,146,0,1496,1510,1,0,0,0,1497,1499,3,294,147,0,1498,1500,5, + 149,0,0,1499,1498,1,0,0,0,1499,1500,1,0,0,0,1500,1502,1,0,0,0,1501,1503, + 3,164,82,0,1502,1501,1,0,0,0,1502,1503,1,0,0,0,1503,1505,1,0,0,0,1504, + 1506,5,149,0,0,1505,1504,1,0,0,0,1505,1506,1,0,0,0,1506,1507,1,0,0,0, + 1507,1508,3,294,147,0,1508,1510,1,0,0,0,1509,1465,1,0,0,0,1509,1481,1, + 0,0,0,1509,1497,1,0,0,0,1510,163,1,0,0,0,1511,1513,5,6,0,0,1512,1514, + 5,149,0,0,1513,1512,1,0,0,0,1513,1514,1,0,0,0,1514,1519,1,0,0,0,1515, + 1517,3,270,135,0,1516,1518,5,149,0,0,1517,1516,1,0,0,0,1517,1518,1,0, + 0,0,1518,1520,1,0,0,0,1519,1515,1,0,0,0,1519,1520,1,0,0,0,1520,1525,1, + 0,0,0,1521,1523,3,168,84,0,1522,1524,5,149,0,0,1523,1522,1,0,0,0,1523, + 1524,1,0,0,0,1524,1526,1,0,0,0,1525,1521,1,0,0,0,1525,1526,1,0,0,0,1526, + 1531,1,0,0,0,1527,1529,3,174,87,0,1528,1530,5,149,0,0,1529,1528,1,0,0, + 0,1529,1530,1,0,0,0,1530,1532,1,0,0,0,1531,1527,1,0,0,0,1531,1532,1,0, + 0,0,1532,1537,1,0,0,0,1533,1535,3,166,83,0,1534,1536,5,149,0,0,1535,1534, + 1,0,0,0,1535,1536,1,0,0,0,1536,1538,1,0,0,0,1537,1533,1,0,0,0,1537,1538, + 1,0,0,0,1538,1539,1,0,0,0,1539,1540,5,7,0,0,1540,165,1,0,0,0,1541,1543, + 5,8,0,0,1542,1544,5,149,0,0,1543,1542,1,0,0,0,1543,1544,1,0,0,0,1544, + 1578,1,0,0,0,1545,1547,3,278,139,0,1546,1548,5,149,0,0,1547,1546,1,0, + 0,0,1547,1548,1,0,0,0,1548,1549,1,0,0,0,1549,1551,5,119,0,0,1550,1552, + 5,149,0,0,1551,1550,1,0,0,0,1551,1552,1,0,0,0,1552,1553,1,0,0,0,1553, + 1555,3,190,95,0,1554,1556,5,149,0,0,1555,1554,1,0,0,0,1555,1556,1,0,0, + 0,1556,1575,1,0,0,0,1557,1559,5,3,0,0,1558,1560,5,149,0,0,1559,1558,1, + 0,0,0,1559,1560,1,0,0,0,1560,1561,1,0,0,0,1561,1563,3,278,139,0,1562, + 1564,5,149,0,0,1563,1562,1,0,0,0,1563,1564,1,0,0,0,1564,1565,1,0,0,0, + 1565,1567,5,119,0,0,1566,1568,5,149,0,0,1567,1566,1,0,0,0,1567,1568,1, + 0,0,0,1568,1569,1,0,0,0,1569,1571,3,190,95,0,1570,1572,5,149,0,0,1571, + 1570,1,0,0,0,1571,1572,1,0,0,0,1572,1574,1,0,0,0,1573,1557,1,0,0,0,1574, + 1577,1,0,0,0,1575,1573,1,0,0,0,1575,1576,1,0,0,0,1576,1579,1,0,0,0,1577, + 1575,1,0,0,0,1578,1545,1,0,0,0,1578,1579,1,0,0,0,1579,1580,1,0,0,0,1580, + 1581,5,9,0,0,1581,167,1,0,0,0,1582,1584,5,119,0,0,1583,1585,5,149,0,0, + 1584,1583,1,0,0,0,1584,1585,1,0,0,0,1585,1586,1,0,0,0,1586,1600,3,188, + 94,0,1587,1589,5,149,0,0,1588,1587,1,0,0,0,1588,1589,1,0,0,0,1589,1590, + 1,0,0,0,1590,1592,5,10,0,0,1591,1593,5,119,0,0,1592,1591,1,0,0,0,1592, + 1593,1,0,0,0,1593,1595,1,0,0,0,1594,1596,5,149,0,0,1595,1594,1,0,0,0, + 1595,1596,1,0,0,0,1596,1597,1,0,0,0,1597,1599,3,188,94,0,1598,1588,1, + 0,0,0,1599,1602,1,0,0,0,1600,1598,1,0,0,0,1600,1601,1,0,0,0,1601,169, + 1,0,0,0,1602,1600,1,0,0,0,1603,1610,3,172,86,0,1604,1606,5,149,0,0,1605, + 1604,1,0,0,0,1605,1606,1,0,0,0,1606,1607,1,0,0,0,1607,1609,3,172,86,0, + 1608,1605,1,0,0,0,1609,1612,1,0,0,0,1610,1608,1,0,0,0,1610,1611,1,0,0, + 0,1611,171,1,0,0,0,1612,1610,1,0,0,0,1613,1615,5,119,0,0,1614,1616,5, + 149,0,0,1615,1614,1,0,0,0,1615,1616,1,0,0,0,1616,1617,1,0,0,0,1617,1618, + 3,186,93,0,1618,173,1,0,0,0,1619,1621,5,100,0,0,1620,1622,5,149,0,0,1621, + 1620,1,0,0,0,1621,1622,1,0,0,0,1622,1627,1,0,0,0,1623,1628,5,111,0,0, + 1624,1625,5,85,0,0,1625,1626,5,149,0,0,1626,1628,5,111,0,0,1627,1623, + 1,0,0,0,1627,1624,1,0,0,0,1627,1628,1,0,0,0,1628,1630,1,0,0,0,1629,1631, + 5,149,0,0,1630,1629,1,0,0,0,1630,1631,1,0,0,0,1631,1646,1,0,0,0,1632, + 1634,3,182,91,0,1633,1632,1,0,0,0,1633,1634,1,0,0,0,1634,1636,1,0,0,0, + 1635,1637,5,149,0,0,1636,1635,1,0,0,0,1636,1637,1,0,0,0,1637,1638,1,0, + 0,0,1638,1640,5,11,0,0,1639,1641,5,149,0,0,1640,1639,1,0,0,0,1640,1641, + 1,0,0,0,1641,1643,1,0,0,0,1642,1644,3,184,92,0,1643,1642,1,0,0,0,1643, + 1644,1,0,0,0,1644,1647,1,0,0,0,1645,1647,3,280,140,0,1646,1633,1,0,0, + 0,1646,1645,1,0,0,0,1646,1647,1,0,0,0,1647,1652,1,0,0,0,1648,1650,5,149, + 0,0,1649,1648,1,0,0,0,1649,1650,1,0,0,0,1650,1651,1,0,0,0,1651,1653,3, + 176,88,0,1652,1649,1,0,0,0,1652,1653,1,0,0,0,1653,175,1,0,0,0,1654,1656, + 5,2,0,0,1655,1657,5,149,0,0,1656,1655,1,0,0,0,1656,1657,1,0,0,0,1657, + 1658,1,0,0,0,1658,1660,3,270,135,0,1659,1661,5,149,0,0,1660,1659,1,0, + 0,0,1660,1661,1,0,0,0,1661,1662,1,0,0,0,1662,1664,5,3,0,0,1663,1665,5, + 149,0,0,1664,1663,1,0,0,0,1664,1665,1,0,0,0,1665,1666,1,0,0,0,1666,1675, + 3,270,135,0,1667,1669,5,149,0,0,1668,1667,1,0,0,0,1668,1669,1,0,0,0,1669, + 1670,1,0,0,0,1670,1672,5,10,0,0,1671,1673,5,149,0,0,1672,1671,1,0,0,0, + 1672,1673,1,0,0,0,1673,1674,1,0,0,0,1674,1676,3,148,74,0,1675,1668,1, + 0,0,0,1675,1676,1,0,0,0,1676,1696,1,0,0,0,1677,1679,5,149,0,0,1678,1677, + 1,0,0,0,1678,1679,1,0,0,0,1679,1680,1,0,0,0,1680,1682,5,10,0,0,1681,1683, + 5,149,0,0,1682,1681,1,0,0,0,1682,1683,1,0,0,0,1683,1684,1,0,0,0,1684, + 1686,3,180,90,0,1685,1687,5,149,0,0,1686,1685,1,0,0,0,1686,1687,1,0,0, + 0,1687,1688,1,0,0,0,1688,1690,5,3,0,0,1689,1691,5,149,0,0,1690,1689,1, + 0,0,0,1690,1691,1,0,0,0,1691,1692,1,0,0,0,1692,1694,3,178,89,0,1693,1695, + 5,149,0,0,1694,1693,1,0,0,0,1694,1695,1,0,0,0,1695,1697,1,0,0,0,1696, + 1678,1,0,0,0,1696,1697,1,0,0,0,1697,1698,1,0,0,0,1698,1699,5,4,0,0,1699, + 177,1,0,0,0,1700,1702,5,8,0,0,1701,1703,5,149,0,0,1702,1701,1,0,0,0,1702, + 1703,1,0,0,0,1703,1705,1,0,0,0,1704,1706,3,136,68,0,1705,1704,1,0,0,0, + 1705,1706,1,0,0,0,1706,1708,1,0,0,0,1707,1709,5,149,0,0,1708,1707,1,0, + 0,0,1708,1709,1,0,0,0,1709,1710,1,0,0,0,1710,1711,5,9,0,0,1711,179,1, + 0,0,0,1712,1714,5,8,0,0,1713,1715,5,149,0,0,1714,1713,1,0,0,0,1714,1715, + 1,0,0,0,1715,1717,1,0,0,0,1716,1718,3,136,68,0,1717,1716,1,0,0,0,1717, + 1718,1,0,0,0,1718,1720,1,0,0,0,1719,1721,5,149,0,0,1720,1719,1,0,0,0, + 1720,1721,1,0,0,0,1721,1722,1,0,0,0,1722,1723,5,9,0,0,1723,181,1,0,0, + 0,1724,1725,5,137,0,0,1725,183,1,0,0,0,1726,1727,5,137,0,0,1727,185,1, + 0,0,0,1728,1729,3,284,142,0,1729,187,1,0,0,0,1730,1731,3,284,142,0,1731, + 189,1,0,0,0,1732,1733,3,192,96,0,1733,191,1,0,0,0,1734,1741,3,194,97, + 0,1735,1736,5,149,0,0,1736,1737,5,112,0,0,1737,1738,5,149,0,0,1738,1740, + 3,194,97,0,1739,1735,1,0,0,0,1740,1743,1,0,0,0,1741,1739,1,0,0,0,1741, + 1742,1,0,0,0,1742,193,1,0,0,0,1743,1741,1,0,0,0,1744,1751,3,196,98,0, + 1745,1746,5,149,0,0,1746,1747,5,113,0,0,1747,1748,5,149,0,0,1748,1750, + 3,196,98,0,1749,1745,1,0,0,0,1750,1753,1,0,0,0,1751,1749,1,0,0,0,1751, + 1752,1,0,0,0,1752,195,1,0,0,0,1753,1751,1,0,0,0,1754,1761,3,198,99,0, + 1755,1756,5,149,0,0,1756,1757,5,114,0,0,1757,1758,5,149,0,0,1758,1760, + 3,198,99,0,1759,1755,1,0,0,0,1760,1763,1,0,0,0,1761,1759,1,0,0,0,1761, + 1762,1,0,0,0,1762,197,1,0,0,0,1763,1761,1,0,0,0,1764,1766,5,115,0,0,1765, + 1767,5,149,0,0,1766,1765,1,0,0,0,1766,1767,1,0,0,0,1767,1769,1,0,0,0, + 1768,1764,1,0,0,0,1769,1772,1,0,0,0,1770,1768,1,0,0,0,1770,1771,1,0,0, + 0,1771,1773,1,0,0,0,1772,1770,1,0,0,0,1773,1774,3,200,100,0,1774,199, + 1,0,0,0,1775,1785,3,204,102,0,1776,1778,5,149,0,0,1777,1776,1,0,0,0,1777, + 1778,1,0,0,0,1778,1779,1,0,0,0,1779,1781,3,202,101,0,1780,1782,5,149, + 0,0,1781,1780,1,0,0,0,1781,1782,1,0,0,0,1782,1783,1,0,0,0,1783,1784,3, + 204,102,0,1784,1786,1,0,0,0,1785,1777,1,0,0,0,1785,1786,1,0,0,0,1786, + 1824,1,0,0,0,1787,1789,3,204,102,0,1788,1790,5,149,0,0,1789,1788,1,0, + 0,0,1789,1790,1,0,0,0,1790,1791,1,0,0,0,1791,1793,5,116,0,0,1792,1794, + 5,149,0,0,1793,1792,1,0,0,0,1793,1794,1,0,0,0,1794,1795,1,0,0,0,1795, + 1796,3,204,102,0,1796,1797,1,0,0,0,1797,1798,6,100,-1,0,1798,1824,1,0, + 0,0,1799,1801,3,204,102,0,1800,1802,5,149,0,0,1801,1800,1,0,0,0,1801, + 1802,1,0,0,0,1802,1803,1,0,0,0,1803,1805,3,202,101,0,1804,1806,5,149, + 0,0,1805,1804,1,0,0,0,1805,1806,1,0,0,0,1806,1807,1,0,0,0,1807,1817,3, + 204,102,0,1808,1810,5,149,0,0,1809,1808,1,0,0,0,1809,1810,1,0,0,0,1810, + 1811,1,0,0,0,1811,1813,3,202,101,0,1812,1814,5,149,0,0,1813,1812,1,0, + 0,0,1813,1814,1,0,0,0,1814,1815,1,0,0,0,1815,1816,3,204,102,0,1816,1818, + 1,0,0,0,1817,1809,1,0,0,0,1818,1819,1,0,0,0,1819,1817,1,0,0,0,1819,1820, + 1,0,0,0,1820,1821,1,0,0,0,1821,1822,6,100,-1,0,1822,1824,1,0,0,0,1823, + 1775,1,0,0,0,1823,1787,1,0,0,0,1823,1799,1,0,0,0,1824,201,1,0,0,0,1825, + 1826,7,2,0,0,1826,203,1,0,0,0,1827,1838,3,206,103,0,1828,1830,5,149,0, + 0,1829,1828,1,0,0,0,1829,1830,1,0,0,0,1830,1831,1,0,0,0,1831,1833,5,10, + 0,0,1832,1834,5,149,0,0,1833,1832,1,0,0,0,1833,1834,1,0,0,0,1834,1835, + 1,0,0,0,1835,1837,3,206,103,0,1836,1829,1,0,0,0,1837,1840,1,0,0,0,1838, + 1836,1,0,0,0,1838,1839,1,0,0,0,1839,205,1,0,0,0,1840,1838,1,0,0,0,1841, + 1852,3,208,104,0,1842,1844,5,149,0,0,1843,1842,1,0,0,0,1843,1844,1,0, + 0,0,1844,1845,1,0,0,0,1845,1847,5,17,0,0,1846,1848,5,149,0,0,1847,1846, + 1,0,0,0,1847,1848,1,0,0,0,1848,1849,1,0,0,0,1849,1851,3,208,104,0,1850, + 1843,1,0,0,0,1851,1854,1,0,0,0,1852,1850,1,0,0,0,1852,1853,1,0,0,0,1853, + 207,1,0,0,0,1854,1852,1,0,0,0,1855,1867,3,212,106,0,1856,1858,5,149,0, + 0,1857,1856,1,0,0,0,1857,1858,1,0,0,0,1858,1859,1,0,0,0,1859,1861,3,210, + 105,0,1860,1862,5,149,0,0,1861,1860,1,0,0,0,1861,1862,1,0,0,0,1862,1863, + 1,0,0,0,1863,1864,3,212,106,0,1864,1866,1,0,0,0,1865,1857,1,0,0,0,1866, + 1869,1,0,0,0,1867,1865,1,0,0,0,1867,1868,1,0,0,0,1868,209,1,0,0,0,1869, + 1867,1,0,0,0,1870,1871,7,3,0,0,1871,211,1,0,0,0,1872,1884,3,216,108,0, + 1873,1875,5,149,0,0,1874,1873,1,0,0,0,1874,1875,1,0,0,0,1875,1876,1,0, + 0,0,1876,1878,3,214,107,0,1877,1879,5,149,0,0,1878,1877,1,0,0,0,1878, + 1879,1,0,0,0,1879,1880,1,0,0,0,1880,1881,3,216,108,0,1881,1883,1,0,0, + 0,1882,1874,1,0,0,0,1883,1886,1,0,0,0,1884,1882,1,0,0,0,1884,1885,1,0, + 0,0,1885,213,1,0,0,0,1886,1884,1,0,0,0,1887,1888,7,4,0,0,1888,215,1,0, + 0,0,1889,1901,3,220,110,0,1890,1892,5,149,0,0,1891,1890,1,0,0,0,1891, + 1892,1,0,0,0,1892,1893,1,0,0,0,1893,1895,3,218,109,0,1894,1896,5,149, + 0,0,1895,1894,1,0,0,0,1895,1896,1,0,0,0,1896,1897,1,0,0,0,1897,1898,3, + 220,110,0,1898,1900,1,0,0,0,1899,1891,1,0,0,0,1900,1903,1,0,0,0,1901, + 1899,1,0,0,0,1901,1902,1,0,0,0,1902,217,1,0,0,0,1903,1901,1,0,0,0,1904, + 1905,7,5,0,0,1905,219,1,0,0,0,1906,1917,3,222,111,0,1907,1909,5,149,0, + 0,1908,1907,1,0,0,0,1908,1909,1,0,0,0,1909,1910,1,0,0,0,1910,1912,5,23, + 0,0,1911,1913,5,149,0,0,1912,1911,1,0,0,0,1912,1913,1,0,0,0,1913,1914, + 1,0,0,0,1914,1916,3,222,111,0,1915,1908,1,0,0,0,1916,1919,1,0,0,0,1917, + 1915,1,0,0,0,1917,1918,1,0,0,0,1918,221,1,0,0,0,1919,1917,1,0,0,0,1920, + 1922,5,117,0,0,1921,1923,5,149,0,0,1922,1921,1,0,0,0,1922,1923,1,0,0, + 0,1923,1925,1,0,0,0,1924,1920,1,0,0,0,1925,1928,1,0,0,0,1926,1924,1,0, + 0,0,1926,1927,1,0,0,0,1927,1929,1,0,0,0,1928,1926,1,0,0,0,1929,1934,3, + 224,112,0,1930,1932,5,149,0,0,1931,1930,1,0,0,0,1931,1932,1,0,0,0,1932, + 1933,1,0,0,0,1933,1935,5,118,0,0,1934,1931,1,0,0,0,1934,1935,1,0,0,0, + 1935,223,1,0,0,0,1936,1944,3,234,117,0,1937,1945,3,228,114,0,1938,1940, + 3,226,113,0,1939,1938,1,0,0,0,1940,1941,1,0,0,0,1941,1939,1,0,0,0,1941, + 1942,1,0,0,0,1942,1945,1,0,0,0,1943,1945,3,232,116,0,1944,1937,1,0,0, + 0,1944,1939,1,0,0,0,1944,1943,1,0,0,0,1944,1945,1,0,0,0,1945,225,1,0, + 0,0,1946,1947,5,149,0,0,1947,1949,5,120,0,0,1948,1950,5,149,0,0,1949, + 1948,1,0,0,0,1949,1950,1,0,0,0,1950,1951,1,0,0,0,1951,1966,3,234,117, + 0,1952,1953,5,6,0,0,1953,1954,3,190,95,0,1954,1955,5,7,0,0,1955,1966, + 1,0,0,0,1956,1958,5,6,0,0,1957,1959,3,190,95,0,1958,1957,1,0,0,0,1958, + 1959,1,0,0,0,1959,1960,1,0,0,0,1960,1962,5,119,0,0,1961,1963,3,190,95, + 0,1962,1961,1,0,0,0,1962,1963,1,0,0,0,1963,1964,1,0,0,0,1964,1966,5,7, + 0,0,1965,1946,1,0,0,0,1965,1952,1,0,0,0,1965,1956,1,0,0,0,1966,227,1, + 0,0,0,1967,1979,3,230,115,0,1968,1969,5,149,0,0,1969,1970,5,121,0,0,1970, + 1971,5,149,0,0,1971,1979,5,97,0,0,1972,1973,5,149,0,0,1973,1974,5,122, + 0,0,1974,1975,5,149,0,0,1975,1979,5,97,0,0,1976,1977,5,149,0,0,1977,1979, + 5,123,0,0,1978,1967,1,0,0,0,1978,1968,1,0,0,0,1978,1972,1,0,0,0,1978, + 1976,1,0,0,0,1979,1981,1,0,0,0,1980,1982,5,149,0,0,1981,1980,1,0,0,0, + 1981,1982,1,0,0,0,1982,1983,1,0,0,0,1983,1984,3,234,117,0,1984,229,1, + 0,0,0,1985,1987,5,149,0,0,1986,1985,1,0,0,0,1986,1987,1,0,0,0,1987,1988, + 1,0,0,0,1988,1989,5,24,0,0,1989,231,1,0,0,0,1990,1991,5,149,0,0,1991, + 1992,5,124,0,0,1992,1993,5,149,0,0,1993,2001,5,125,0,0,1994,1995,5,149, + 0,0,1995,1996,5,124,0,0,1996,1997,5,149,0,0,1997,1998,5,115,0,0,1998, + 1999,5,149,0,0,1999,2001,5,125,0,0,2000,1990,1,0,0,0,2000,1994,1,0,0, + 0,2001,233,1,0,0,0,2002,2009,3,236,118,0,2003,2005,5,149,0,0,2004,2003, + 1,0,0,0,2004,2005,1,0,0,0,2005,2006,1,0,0,0,2006,2008,3,264,132,0,2007, + 2004,1,0,0,0,2008,2011,1,0,0,0,2009,2007,1,0,0,0,2009,2010,1,0,0,0,2010, + 235,1,0,0,0,2011,2009,1,0,0,0,2012,2022,3,238,119,0,2013,2022,3,274,137, + 0,2014,2022,3,266,133,0,2015,2022,3,250,125,0,2016,2022,3,252,126,0,2017, + 2022,3,258,129,0,2018,2022,3,260,130,0,2019,2022,3,262,131,0,2020,2022, + 3,270,135,0,2021,2012,1,0,0,0,2021,2013,1,0,0,0,2021,2014,1,0,0,0,2021, + 2015,1,0,0,0,2021,2016,1,0,0,0,2021,2017,1,0,0,0,2021,2018,1,0,0,0,2021, + 2019,1,0,0,0,2021,2020,1,0,0,0,2022,237,1,0,0,0,2023,2030,3,272,136,0, + 2024,2030,5,135,0,0,2025,2030,3,240,120,0,2026,2030,5,125,0,0,2027,2030, + 3,242,121,0,2028,2030,3,246,123,0,2029,2023,1,0,0,0,2029,2024,1,0,0,0, + 2029,2025,1,0,0,0,2029,2026,1,0,0,0,2029,2027,1,0,0,0,2029,2028,1,0,0, + 0,2030,239,1,0,0,0,2031,2032,7,6,0,0,2032,241,1,0,0,0,2033,2035,5,6,0, + 0,2034,2036,5,149,0,0,2035,2034,1,0,0,0,2035,2036,1,0,0,0,2036,2050,1, + 0,0,0,2037,2039,3,190,95,0,2038,2040,5,149,0,0,2039,2038,1,0,0,0,2039, + 2040,1,0,0,0,2040,2047,1,0,0,0,2041,2043,3,244,122,0,2042,2044,5,149, + 0,0,2043,2042,1,0,0,0,2043,2044,1,0,0,0,2044,2046,1,0,0,0,2045,2041,1, + 0,0,0,2046,2049,1,0,0,0,2047,2045,1,0,0,0,2047,2048,1,0,0,0,2048,2051, + 1,0,0,0,2049,2047,1,0,0,0,2050,2037,1,0,0,0,2050,2051,1,0,0,0,2051,2052, + 1,0,0,0,2052,2053,5,7,0,0,2053,243,1,0,0,0,2054,2056,5,3,0,0,2055,2057, + 5,149,0,0,2056,2055,1,0,0,0,2056,2057,1,0,0,0,2057,2059,1,0,0,0,2058, + 2060,3,190,95,0,2059,2058,1,0,0,0,2059,2060,1,0,0,0,2060,245,1,0,0,0, + 2061,2063,5,8,0,0,2062,2064,5,149,0,0,2063,2062,1,0,0,0,2063,2064,1,0, + 0,0,2064,2065,1,0,0,0,2065,2067,3,248,124,0,2066,2068,5,149,0,0,2067, + 2066,1,0,0,0,2067,2068,1,0,0,0,2068,2079,1,0,0,0,2069,2071,5,3,0,0,2070, + 2072,5,149,0,0,2071,2070,1,0,0,0,2071,2072,1,0,0,0,2072,2073,1,0,0,0, + 2073,2075,3,248,124,0,2074,2076,5,149,0,0,2075,2074,1,0,0,0,2075,2076, + 1,0,0,0,2076,2078,1,0,0,0,2077,2069,1,0,0,0,2078,2081,1,0,0,0,2079,2077, + 1,0,0,0,2079,2080,1,0,0,0,2080,2082,1,0,0,0,2081,2079,1,0,0,0,2082,2083, + 5,9,0,0,2083,247,1,0,0,0,2084,2087,3,286,143,0,2085,2087,5,135,0,0,2086, + 2084,1,0,0,0,2086,2085,1,0,0,0,2087,2089,1,0,0,0,2088,2090,5,149,0,0, + 2089,2088,1,0,0,0,2089,2090,1,0,0,0,2090,2091,1,0,0,0,2091,2093,5,119, + 0,0,2092,2094,5,149,0,0,2093,2092,1,0,0,0,2093,2094,1,0,0,0,2094,2095, + 1,0,0,0,2095,2096,3,190,95,0,2096,249,1,0,0,0,2097,2099,5,2,0,0,2098, + 2100,5,149,0,0,2099,2098,1,0,0,0,2099,2100,1,0,0,0,2100,2101,1,0,0,0, + 2101,2103,3,190,95,0,2102,2104,5,149,0,0,2103,2102,1,0,0,0,2103,2104, + 1,0,0,0,2104,2105,1,0,0,0,2105,2106,5,4,0,0,2106,251,1,0,0,0,2107,2109, + 5,128,0,0,2108,2110,5,149,0,0,2109,2108,1,0,0,0,2109,2110,1,0,0,0,2110, + 2111,1,0,0,0,2111,2113,5,2,0,0,2112,2114,5,149,0,0,2113,2112,1,0,0,0, + 2113,2114,1,0,0,0,2114,2115,1,0,0,0,2115,2117,5,100,0,0,2116,2118,5,149, + 0,0,2117,2116,1,0,0,0,2117,2118,1,0,0,0,2118,2119,1,0,0,0,2119,2156,5, + 4,0,0,2120,2122,3,254,127,0,2121,2123,5,149,0,0,2122,2121,1,0,0,0,2122, + 2123,1,0,0,0,2123,2124,1,0,0,0,2124,2126,5,2,0,0,2125,2127,5,149,0,0, + 2126,2125,1,0,0,0,2126,2127,1,0,0,0,2127,2132,1,0,0,0,2128,2130,5,99, + 0,0,2129,2131,5,149,0,0,2130,2129,1,0,0,0,2130,2131,1,0,0,0,2131,2133, + 1,0,0,0,2132,2128,1,0,0,0,2132,2133,1,0,0,0,2133,2151,1,0,0,0,2134,2136, + 3,256,128,0,2135,2137,5,149,0,0,2136,2135,1,0,0,0,2136,2137,1,0,0,0,2137, + 2148,1,0,0,0,2138,2140,5,3,0,0,2139,2141,5,149,0,0,2140,2139,1,0,0,0, + 2140,2141,1,0,0,0,2141,2142,1,0,0,0,2142,2144,3,256,128,0,2143,2145,5, + 149,0,0,2144,2143,1,0,0,0,2144,2145,1,0,0,0,2145,2147,1,0,0,0,2146,2138, + 1,0,0,0,2147,2150,1,0,0,0,2148,2146,1,0,0,0,2148,2149,1,0,0,0,2149,2152, + 1,0,0,0,2150,2148,1,0,0,0,2151,2134,1,0,0,0,2151,2152,1,0,0,0,2152,2153, + 1,0,0,0,2153,2154,5,4,0,0,2154,2156,1,0,0,0,2155,2107,1,0,0,0,2155,2120, + 1,0,0,0,2156,253,1,0,0,0,2157,2158,3,286,143,0,2158,255,1,0,0,0,2159, + 2161,3,286,143,0,2160,2162,5,149,0,0,2161,2160,1,0,0,0,2161,2162,1,0, + 0,0,2162,2163,1,0,0,0,2163,2164,5,119,0,0,2164,2166,5,5,0,0,2165,2167, + 5,149,0,0,2166,2165,1,0,0,0,2166,2167,1,0,0,0,2167,2169,1,0,0,0,2168, + 2159,1,0,0,0,2168,2169,1,0,0,0,2169,2170,1,0,0,0,2170,2171,3,190,95,0, + 2171,257,1,0,0,0,2172,2177,3,158,79,0,2173,2175,5,149,0,0,2174,2173,1, + 0,0,0,2174,2175,1,0,0,0,2175,2176,1,0,0,0,2176,2178,3,160,80,0,2177,2174, + 1,0,0,0,2178,2179,1,0,0,0,2179,2177,1,0,0,0,2179,2180,1,0,0,0,2180,259, + 1,0,0,0,2181,2183,5,129,0,0,2182,2184,5,149,0,0,2183,2182,1,0,0,0,2183, + 2184,1,0,0,0,2184,2185,1,0,0,0,2185,2187,5,8,0,0,2186,2188,5,149,0,0, + 2187,2186,1,0,0,0,2187,2188,1,0,0,0,2188,2189,1,0,0,0,2189,2191,5,89, + 0,0,2190,2192,5,149,0,0,2191,2190,1,0,0,0,2191,2192,1,0,0,0,2192,2193, + 1,0,0,0,2193,2198,3,150,75,0,2194,2196,5,149,0,0,2195,2194,1,0,0,0,2195, + 2196,1,0,0,0,2196,2197,1,0,0,0,2197,2199,3,148,74,0,2198,2195,1,0,0,0, + 2198,2199,1,0,0,0,2199,2201,1,0,0,0,2200,2202,5,149,0,0,2201,2200,1,0, + 0,0,2201,2202,1,0,0,0,2202,2203,1,0,0,0,2203,2204,5,9,0,0,2204,261,1, + 0,0,0,2205,2207,5,128,0,0,2206,2208,5,149,0,0,2207,2206,1,0,0,0,2207, + 2208,1,0,0,0,2208,2209,1,0,0,0,2209,2211,5,8,0,0,2210,2212,5,149,0,0, + 2211,2210,1,0,0,0,2211,2212,1,0,0,0,2212,2213,1,0,0,0,2213,2215,5,89, + 0,0,2214,2216,5,149,0,0,2215,2214,1,0,0,0,2215,2216,1,0,0,0,2216,2217, + 1,0,0,0,2217,2222,3,150,75,0,2218,2220,5,149,0,0,2219,2218,1,0,0,0,2219, + 2220,1,0,0,0,2220,2221,1,0,0,0,2221,2223,3,148,74,0,2222,2219,1,0,0,0, + 2222,2223,1,0,0,0,2223,2225,1,0,0,0,2224,2226,5,149,0,0,2225,2224,1,0, + 0,0,2225,2226,1,0,0,0,2226,2227,1,0,0,0,2227,2228,5,9,0,0,2228,263,1, + 0,0,0,2229,2231,5,25,0,0,2230,2232,5,149,0,0,2231,2230,1,0,0,0,2231,2232, + 1,0,0,0,2232,2235,1,0,0,0,2233,2236,3,278,139,0,2234,2236,5,100,0,0,2235, + 2233,1,0,0,0,2235,2234,1,0,0,0,2236,265,1,0,0,0,2237,2242,5,130,0,0,2238, + 2240,5,149,0,0,2239,2238,1,0,0,0,2239,2240,1,0,0,0,2240,2241,1,0,0,0, + 2241,2243,3,268,134,0,2242,2239,1,0,0,0,2243,2244,1,0,0,0,2244,2242,1, + 0,0,0,2244,2245,1,0,0,0,2245,2260,1,0,0,0,2246,2248,5,130,0,0,2247,2249, + 5,149,0,0,2248,2247,1,0,0,0,2248,2249,1,0,0,0,2249,2250,1,0,0,0,2250, + 2255,3,190,95,0,2251,2253,5,149,0,0,2252,2251,1,0,0,0,2252,2253,1,0,0, + 0,2253,2254,1,0,0,0,2254,2256,3,268,134,0,2255,2252,1,0,0,0,2256,2257, + 1,0,0,0,2257,2255,1,0,0,0,2257,2258,1,0,0,0,2258,2260,1,0,0,0,2259,2237, + 1,0,0,0,2259,2246,1,0,0,0,2260,2269,1,0,0,0,2261,2263,5,149,0,0,2262, + 2261,1,0,0,0,2262,2263,1,0,0,0,2263,2264,1,0,0,0,2264,2266,5,131,0,0, + 2265,2267,5,149,0,0,2266,2265,1,0,0,0,2266,2267,1,0,0,0,2267,2268,1,0, + 0,0,2268,2270,3,190,95,0,2269,2262,1,0,0,0,2269,2270,1,0,0,0,2270,2272, + 1,0,0,0,2271,2273,5,149,0,0,2272,2271,1,0,0,0,2272,2273,1,0,0,0,2273, + 2274,1,0,0,0,2274,2275,5,132,0,0,2275,267,1,0,0,0,2276,2278,5,133,0,0, + 2277,2279,5,149,0,0,2278,2277,1,0,0,0,2278,2279,1,0,0,0,2279,2280,1,0, + 0,0,2280,2282,3,190,95,0,2281,2283,5,149,0,0,2282,2281,1,0,0,0,2282,2283, + 1,0,0,0,2283,2284,1,0,0,0,2284,2286,5,134,0,0,2285,2287,5,149,0,0,2286, + 2285,1,0,0,0,2286,2287,1,0,0,0,2287,2288,1,0,0,0,2288,2289,3,190,95,0, + 2289,269,1,0,0,0,2290,2291,3,286,143,0,2291,271,1,0,0,0,2292,2295,3,282, + 141,0,2293,2295,3,280,140,0,2294,2292,1,0,0,0,2294,2293,1,0,0,0,2295, + 273,1,0,0,0,2296,2299,5,26,0,0,2297,2300,3,286,143,0,2298,2300,5,137, + 0,0,2299,2297,1,0,0,0,2299,2298,1,0,0,0,2300,275,1,0,0,0,2301,2303,3, + 236,118,0,2302,2304,5,149,0,0,2303,2302,1,0,0,0,2303,2304,1,0,0,0,2304, + 2305,1,0,0,0,2305,2306,3,264,132,0,2306,277,1,0,0,0,2307,2308,3,284,142, + 0,2308,279,1,0,0,0,2309,2310,5,137,0,0,2310,281,1,0,0,0,2311,2312,5,144, + 0,0,2312,283,1,0,0,0,2313,2314,3,286,143,0,2314,285,1,0,0,0,2315,2321, + 5,145,0,0,2316,2317,5,148,0,0,2317,2321,6,143,-1,0,2318,2321,5,138,0, + 0,2319,2321,3,288,144,0,2320,2315,1,0,0,0,2320,2316,1,0,0,0,2320,2318, + 1,0,0,0,2320,2319,1,0,0,0,2321,287,1,0,0,0,2322,2323,7,7,0,0,2323,289, + 1,0,0,0,2324,2325,7,8,0,0,2325,291,1,0,0,0,2326,2327,7,9,0,0,2327,293, + 1,0,0,0,2328,2329,7,10,0,0,2329,295,1,0,0,0,401,298,302,307,311,316,319, + 323,326,342,348,352,355,361,364,368,372,376,381,385,392,396,401,411,415, + 419,424,437,441,449,452,460,463,480,483,487,493,496,506,510,532,536,539, + 542,545,548,552,557,561,571,575,580,585,590,596,600,604,609,616,620,624, + 627,631,635,639,644,648,654,658,668,678,682,686,690,695,707,711,715,719, + 723,725,729,733,735,749,753,757,761,766,769,773,777,779,783,787,789,825, + 836,858,862,867,878,882,886,894,898,902,908,912,916,922,926,930,934,938, + 942,948,955,960,966,986,990,998,1008,1013,1018,1022,1027,1033,1038,1041, + 1045,1049,1053,1059,1063,1068,1073,1077,1080,1084,1088,1092,1096,1100, + 1106,1110,1115,1119,1128,1134,1142,1146,1150,1154,1161,1164,1167,1170, + 1176,1179,1183,1187,1191,1194,1198,1208,1214,1221,1234,1238,1242,1246, + 1251,1256,1260,1266,1270,1274,1278,1283,1289,1292,1298,1301,1307,1311, + 1315,1319,1323,1328,1333,1337,1342,1345,1354,1363,1368,1381,1384,1392, + 1396,1401,1406,1410,1415,1421,1426,1433,1437,1441,1443,1447,1449,1453, + 1455,1461,1467,1471,1474,1477,1483,1486,1489,1493,1499,1502,1505,1509, + 1513,1517,1519,1523,1525,1529,1531,1535,1537,1543,1547,1551,1555,1559, + 1563,1567,1571,1575,1578,1584,1588,1592,1595,1600,1605,1610,1615,1621, + 1627,1630,1633,1636,1640,1643,1646,1649,1652,1656,1660,1664,1668,1672, + 1675,1678,1682,1686,1690,1694,1696,1702,1705,1708,1714,1717,1720,1741, + 1751,1761,1766,1770,1777,1781,1785,1789,1793,1801,1805,1809,1813,1819, + 1823,1829,1833,1838,1843,1847,1852,1857,1861,1867,1874,1878,1884,1891, + 1895,1901,1908,1912,1917,1922,1926,1931,1934,1941,1944,1949,1958,1962, + 1965,1978,1981,1986,2000,2004,2009,2021,2029,2035,2039,2043,2047,2050, + 2056,2059,2063,2067,2071,2075,2079,2086,2089,2093,2099,2103,2109,2113, + 2117,2122,2126,2130,2132,2136,2140,2144,2148,2151,2155,2161,2166,2168, + 2174,2179,2183,2187,2191,2195,2198,2201,2207,2211,2215,2219,2222,2225, + 2231,2235,2239,2244,2248,2252,2257,2259,2262,2266,2269,2272,2278,2282, + 2286,2294,2299,2303,2320 }; staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0])); @@ -1130,29 +1141,29 @@ CypherParser::Ku_StatementsContext* CypherParser::ku_Statements() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(290); + setState(296); oC_Cypher(); - setState(301); + setState(307); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 2, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(292); + setState(298); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(291); + setState(297); match(CypherParser::SP); } - setState(294); + setState(300); match(CypherParser::T__0); - setState(296); + setState(302); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 1, _ctx)) { case 1: { - setState(295); + setState(301); match(CypherParser::SP); break; } @@ -1160,22 +1171,22 @@ CypherParser::Ku_StatementsContext* CypherParser::ku_Statements() { default: break; } - setState(298); + setState(304); oC_Cypher(); } - setState(303); + setState(309); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 2, _ctx); } - setState(305); + setState(311); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(304); + setState(310); match(CypherParser::SP); } - setState(307); + setState(313); match(CypherParser::EOF); } @@ -1230,41 +1241,41 @@ CypherParser::OC_CypherContext* CypherParser::oC_Cypher() { }); try { enterOuterAlt(_localctx, 1); - setState(310); + setState(316); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::EXPLAIN || _la == CypherParser::PROFILE) { - setState(309); + setState(315); oC_AnyCypherOption(); } - setState(313); + setState(319); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(312); + setState(318); match(CypherParser::SP); } - setState(315); + setState(321); oC_Statement(); - setState(320); + setState(326); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 7, _ctx)) { case 1: { - setState(317); + setState(323); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(316); + setState(322); match(CypherParser::SP); } - setState(319); + setState(325); match(CypherParser::T__0); break; } @@ -1337,6 +1348,14 @@ CypherParser::KU_ImportDatabaseContext* CypherParser::OC_StatementContext::kU_Im return getRuleContext(0); } +CypherParser::KU_AttachDatabaseContext* CypherParser::OC_StatementContext::kU_AttachDatabase() { + return getRuleContext(0); +} + +CypherParser::KU_DetachDatabaseContext* CypherParser::OC_StatementContext::kU_DetachDatabase() { + return getRuleContext(0); +} + size_t CypherParser::OC_StatementContext::getRuleIndex() const { return CypherParser::RuleOC_Statement; @@ -1355,93 +1374,107 @@ CypherParser::OC_StatementContext* CypherParser::oC_Statement() { exitRule(); }); try { - setState(334); + setState(342); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 8, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(322); + setState(328); oC_Query(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(323); + setState(329); kU_DDL(); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(324); + setState(330); kU_CopyFrom(); break; } case 4: { enterOuterAlt(_localctx, 4); - setState(325); + setState(331); kU_CopyFromByColumn(); break; } case 5: { enterOuterAlt(_localctx, 5); - setState(326); + setState(332); kU_CopyTO(); break; } case 6: { enterOuterAlt(_localctx, 6); - setState(327); + setState(333); kU_StandaloneCall(); break; } case 7: { enterOuterAlt(_localctx, 7); - setState(328); + setState(334); kU_CreateMacro(); break; } case 8: { enterOuterAlt(_localctx, 8); - setState(329); + setState(335); kU_CommentOn(); break; } case 9: { enterOuterAlt(_localctx, 9); - setState(330); + setState(336); kU_Transaction(); break; } case 10: { enterOuterAlt(_localctx, 10); - setState(331); + setState(337); kU_Extension(); break; } case 11: { enterOuterAlt(_localctx, 11); - setState(332); + setState(338); kU_ExportDatabase(); break; } case 12: { enterOuterAlt(_localctx, 12); - setState(333); + setState(339); kU_ImportDatabase(); break; } + case 13: { + enterOuterAlt(_localctx, 13); + setState(340); + kU_AttachDatabase(); + break; + } + + case 14: { + enterOuterAlt(_localctx, 14); + setState(341); + kU_DetachDatabase(); + break; + } + default: break; } @@ -1482,12 +1515,8 @@ tree::TerminalNode* CypherParser::KU_CopyFromContext::FROM() { return getToken(CypherParser::FROM, 0); } -CypherParser::KU_FilePathsContext* CypherParser::KU_CopyFromContext::kU_FilePaths() { - return getRuleContext(0); -} - -CypherParser::OC_VariableContext* CypherParser::KU_CopyFromContext::oC_Variable() { - return getRuleContext(0); +CypherParser::KU_ScanSourceContext* CypherParser::KU_CopyFromContext::kU_ScanSource() { + return getRuleContext(0); } CypherParser::KU_ParsingOptionsContext* CypherParser::KU_CopyFromContext::kU_ParsingOptions() { @@ -1518,36 +1547,16 @@ CypherParser::KU_CopyFromContext* CypherParser::kU_CopyFrom() { }); try { enterOuterAlt(_localctx, 1); - setState(336); + setState(344); match(CypherParser::COPY); - setState(337); + setState(345); match(CypherParser::SP); - setState(338); + setState(346); oC_SchemaName(); setState(355); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 13, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 11, _ctx)) { case 1: { - setState(340); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(339); - match(CypherParser::SP); - } - setState(342); - match(CypherParser::T__1); - setState(344); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(343); - match(CypherParser::SP); - } - setState(346); - kU_ColumnNames(); setState(348); _errHandler->sync(this); @@ -1557,7 +1566,7 @@ CypherParser::KU_CopyFromContext* CypherParser::kU_CopyFrom() { match(CypherParser::SP); } setState(350); - match(CypherParser::T__2); + kU_ColumnNames(); setState(352); _errHandler->sync(this); @@ -1582,73 +1591,23 @@ CypherParser::KU_CopyFromContext* CypherParser::kU_CopyFrom() { match(CypherParser::FROM); setState(358); match(CypherParser::SP); - setState(361); - _errHandler->sync(this); - switch (_input->LA(1)) { - case CypherParser::T__5: - case CypherParser::GLOB: - case CypherParser::StringLiteral: { - setState(359); - kU_FilePaths(); - break; - } - - case CypherParser::COMMENT: - case CypherParser::EXPORT: - case CypherParser::IMPORT: - case CypherParser::DATABASE: - case CypherParser::NODE: - case CypherParser::REL: - case CypherParser::BEGIN: - case CypherParser::IN: - case CypherParser::COUNT: - case CypherParser::END: - case CypherParser::HexLetter: - case CypherParser::UnescapedSymbolicName: - case CypherParser::EscapedSymbolicName: { - setState(360); - oC_Variable(); - break; - } - - default: - throw NoViableAltException(this); - } - setState(376); + setState(359); + kU_ScanSource(); + setState(364); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 18, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 13, _ctx)) { case 1: { - setState(364); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(363); - match(CypherParser::SP); - } - setState(366); - match(CypherParser::T__1); - setState(368); + setState(361); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(367); + setState(360); match(CypherParser::SP); } - setState(370); + setState(363); kU_ParsingOptions(); - setState(372); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(371); - match(CypherParser::SP); - } - setState(374); - match(CypherParser::T__2); break; } @@ -1709,37 +1668,174 @@ CypherParser::KU_ColumnNamesContext* CypherParser::kU_ColumnNames() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(378); + setState(366); + match(CypherParser::T__1); + setState(368); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(367); + match(CypherParser::SP); + } + setState(370); oC_SchemaName(); - setState(389); + setState(381); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 21, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 17, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(380); + setState(372); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(379); + setState(371); match(CypherParser::SP); } - setState(382); - match(CypherParser::T__3); - setState(384); + setState(374); + match(CypherParser::T__2); + setState(376); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(383); + setState(375); match(CypherParser::SP); } - setState(386); + setState(378); oC_SchemaName(); } - setState(391); + setState(383); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 21, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 17, _ctx); + } + setState(385); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(384); + match(CypherParser::SP); + } + setState(387); + match(CypherParser::T__3); + + } + catch (RecognitionException &e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- KU_ScanSourceContext ------------------------------------------------------------------ + +CypherParser::KU_ScanSourceContext::KU_ScanSourceContext(ParserRuleContext *parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) { +} + +CypherParser::KU_FilePathsContext* CypherParser::KU_ScanSourceContext::kU_FilePaths() { + return getRuleContext(0); +} + +CypherParser::OC_QueryContext* CypherParser::KU_ScanSourceContext::oC_Query() { + return getRuleContext(0); +} + +std::vector CypherParser::KU_ScanSourceContext::SP() { + return getTokens(CypherParser::SP); +} + +tree::TerminalNode* CypherParser::KU_ScanSourceContext::SP(size_t i) { + return getToken(CypherParser::SP, i); +} + +CypherParser::OC_VariableContext* CypherParser::KU_ScanSourceContext::oC_Variable() { + return getRuleContext(0); +} + + +size_t CypherParser::KU_ScanSourceContext::getRuleIndex() const { + return CypherParser::RuleKU_ScanSource; +} + + +CypherParser::KU_ScanSourceContext* CypherParser::kU_ScanSource() { + KU_ScanSourceContext *_localctx = _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 10, CypherParser::RuleKU_ScanSource); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + setState(401); + _errHandler->sync(this); + switch (_input->LA(1)) { + case CypherParser::T__5: + case CypherParser::GLOB: + case CypherParser::StringLiteral: { + enterOuterAlt(_localctx, 1); + setState(389); + kU_FilePaths(); + break; + } + + case CypherParser::T__1: { + enterOuterAlt(_localctx, 2); + setState(390); + match(CypherParser::T__1); + setState(392); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(391); + match(CypherParser::SP); + } + setState(394); + oC_Query(); + setState(396); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(395); + match(CypherParser::SP); + } + setState(398); + match(CypherParser::T__3); + break; + } + + case CypherParser::COMMENT_: + case CypherParser::EXPORT: + case CypherParser::IMPORT: + case CypherParser::DATABASE: + case CypherParser::NODE: + case CypherParser::REL: + case CypherParser::BEGIN: + case CypherParser::IN: + case CypherParser::COUNT: + case CypherParser::END: + case CypherParser::HexLetter: + case CypherParser::UnescapedSymbolicName: + case CypherParser::EscapedSymbolicName: { + enterOuterAlt(_localctx, 3); + setState(400); + oC_Variable(); + break; + } + + default: + throw NoViableAltException(this); } } @@ -1802,7 +1898,7 @@ size_t CypherParser::KU_CopyFromByColumnContext::getRuleIndex() const { CypherParser::KU_CopyFromByColumnContext* CypherParser::kU_CopyFromByColumn() { KU_CopyFromByColumnContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 10, CypherParser::RuleKU_CopyFromByColumn); + enterRule(_localctx, 12, CypherParser::RuleKU_CopyFromByColumn); size_t _la = 0; #if __cplusplus > 201703L @@ -1814,67 +1910,67 @@ CypherParser::KU_CopyFromByColumnContext* CypherParser::kU_CopyFromByColumn() { }); try { enterOuterAlt(_localctx, 1); - setState(392); + setState(403); match(CypherParser::COPY); - setState(393); + setState(404); match(CypherParser::SP); - setState(394); + setState(405); oC_SchemaName(); - setState(395); + setState(406); match(CypherParser::SP); - setState(396); + setState(407); match(CypherParser::FROM); - setState(397); + setState(408); match(CypherParser::SP); - setState(398); + setState(409); match(CypherParser::T__1); - setState(400); + setState(411); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(399); + setState(410); match(CypherParser::SP); } - setState(402); - match(CypherParser::StringLiteral); setState(413); + match(CypherParser::StringLiteral); + setState(424); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3 || _la == CypherParser::SP) { - setState(404); + while (_la == CypherParser::T__2 || _la == CypherParser::SP) { + setState(415); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(403); + setState(414); match(CypherParser::SP); } - setState(406); - match(CypherParser::T__3); - setState(408); + setState(417); + match(CypherParser::T__2); + setState(419); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(407); + setState(418); match(CypherParser::SP); } - setState(410); + setState(421); match(CypherParser::StringLiteral); - setState(415); + setState(426); _errHandler->sync(this); _la = _input->LA(1); } - setState(416); - match(CypherParser::T__2); - setState(417); + setState(427); + match(CypherParser::T__3); + setState(428); match(CypherParser::SP); - setState(418); + setState(429); match(CypherParser::BY); - setState(419); + setState(430); match(CypherParser::SP); - setState(420); + setState(431); match(CypherParser::COLUMN); } @@ -1929,7 +2025,7 @@ size_t CypherParser::KU_CopyTOContext::getRuleIndex() const { CypherParser::KU_CopyTOContext* CypherParser::kU_CopyTO() { KU_CopyTOContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 12, CypherParser::RuleKU_CopyTO); + enterRule(_localctx, 14, CypherParser::RuleKU_CopyTO); size_t _la = 0; #if __cplusplus > 201703L @@ -1941,75 +2037,55 @@ CypherParser::KU_CopyTOContext* CypherParser::kU_CopyTO() { }); try { enterOuterAlt(_localctx, 1); - setState(422); + setState(433); match(CypherParser::COPY); - setState(423); + setState(434); match(CypherParser::SP); - setState(424); + setState(435); match(CypherParser::T__1); - setState(426); + setState(437); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(425); + setState(436); match(CypherParser::SP); } - setState(428); + setState(439); oC_Query(); - setState(430); + setState(441); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(429); + setState(440); match(CypherParser::SP); } - setState(432); - match(CypherParser::T__2); - setState(433); + setState(443); + match(CypherParser::T__3); + setState(444); match(CypherParser::SP); - setState(434); + setState(445); match(CypherParser::TO); - setState(435); + setState(446); match(CypherParser::SP); - setState(436); + setState(447); match(CypherParser::StringLiteral); - setState(450); + setState(452); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 31, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 29, _ctx)) { case 1: { - setState(438); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(437); - match(CypherParser::SP); - } - setState(440); - match(CypherParser::T__1); - setState(442); + setState(449); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(441); + setState(448); match(CypherParser::SP); } - setState(444); + setState(451); kU_ParsingOptions(); - setState(446); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(445); - match(CypherParser::SP); - } - setState(448); - match(CypherParser::T__2); break; } @@ -2065,7 +2141,7 @@ size_t CypherParser::KU_ExportDatabaseContext::getRuleIndex() const { CypherParser::KU_ExportDatabaseContext* CypherParser::kU_ExportDatabase() { KU_ExportDatabaseContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 14, CypherParser::RuleKU_ExportDatabase); + enterRule(_localctx, 16, CypherParser::RuleKU_ExportDatabase); size_t _la = 0; #if __cplusplus > 201703L @@ -2077,51 +2153,31 @@ CypherParser::KU_ExportDatabaseContext* CypherParser::kU_ExportDatabase() { }); try { enterOuterAlt(_localctx, 1); - setState(452); - match(CypherParser::EXPORT); - setState(453); - match(CypherParser::SP); setState(454); - match(CypherParser::DATABASE); + match(CypherParser::EXPORT); setState(455); match(CypherParser::SP); setState(456); + match(CypherParser::DATABASE); + setState(457); + match(CypherParser::SP); + setState(458); match(CypherParser::StringLiteral); - setState(470); + setState(463); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 35, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 31, _ctx)) { case 1: { - setState(458); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(457); - match(CypherParser::SP); - } setState(460); - match(CypherParser::T__1); - setState(462); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(461); + setState(459); match(CypherParser::SP); } - setState(464); + setState(462); kU_ParsingOptions(); - setState(466); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(465); - match(CypherParser::SP); - } - setState(468); - match(CypherParser::T__2); break; } @@ -2153,27 +2209,226 @@ std::vector CypherParser::KU_ImportDatabaseContext::SP() { return getTokens(CypherParser::SP); } -tree::TerminalNode* CypherParser::KU_ImportDatabaseContext::SP(size_t i) { - return getToken(CypherParser::SP, i); +tree::TerminalNode* CypherParser::KU_ImportDatabaseContext::SP(size_t i) { + return getToken(CypherParser::SP, i); +} + +tree::TerminalNode* CypherParser::KU_ImportDatabaseContext::DATABASE() { + return getToken(CypherParser::DATABASE, 0); +} + +tree::TerminalNode* CypherParser::KU_ImportDatabaseContext::StringLiteral() { + return getToken(CypherParser::StringLiteral, 0); +} + + +size_t CypherParser::KU_ImportDatabaseContext::getRuleIndex() const { + return CypherParser::RuleKU_ImportDatabase; +} + + +CypherParser::KU_ImportDatabaseContext* CypherParser::kU_ImportDatabase() { + KU_ImportDatabaseContext *_localctx = _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 18, CypherParser::RuleKU_ImportDatabase); + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(465); + match(CypherParser::IMPORT); + setState(466); + match(CypherParser::SP); + setState(467); + match(CypherParser::DATABASE); + setState(468); + match(CypherParser::SP); + setState(469); + match(CypherParser::StringLiteral); + + } + catch (RecognitionException &e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- KU_AttachDatabaseContext ------------------------------------------------------------------ + +CypherParser::KU_AttachDatabaseContext::KU_AttachDatabaseContext(ParserRuleContext *parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) { +} + +tree::TerminalNode* CypherParser::KU_AttachDatabaseContext::ATTACH() { + return getToken(CypherParser::ATTACH, 0); +} + +std::vector CypherParser::KU_AttachDatabaseContext::SP() { + return getTokens(CypherParser::SP); +} + +tree::TerminalNode* CypherParser::KU_AttachDatabaseContext::SP(size_t i) { + return getToken(CypherParser::SP, i); +} + +std::vector CypherParser::KU_AttachDatabaseContext::StringLiteral() { + return getTokens(CypherParser::StringLiteral); +} + +tree::TerminalNode* CypherParser::KU_AttachDatabaseContext::StringLiteral(size_t i) { + return getToken(CypherParser::StringLiteral, i); +} + +tree::TerminalNode* CypherParser::KU_AttachDatabaseContext::AS() { + return getToken(CypherParser::AS, 0); +} + +CypherParser::OC_SchemaNameContext* CypherParser::KU_AttachDatabaseContext::oC_SchemaName() { + return getRuleContext(0); +} + +tree::TerminalNode* CypherParser::KU_AttachDatabaseContext::DBTYPE() { + return getToken(CypherParser::DBTYPE, 0); +} + + +size_t CypherParser::KU_AttachDatabaseContext::getRuleIndex() const { + return CypherParser::RuleKU_AttachDatabase; +} + + +CypherParser::KU_AttachDatabaseContext* CypherParser::kU_AttachDatabase() { + KU_AttachDatabaseContext *_localctx = _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 20, CypherParser::RuleKU_AttachDatabase); + size_t _la = 0; + +#if __cplusplus > 201703L + auto onExit = finally([=, this] { +#else + auto onExit = finally([=] { +#endif + exitRule(); + }); + try { + enterOuterAlt(_localctx, 1); + setState(471); + match(CypherParser::ATTACH); + setState(472); + match(CypherParser::SP); + setState(473); + match(CypherParser::StringLiteral); + setState(480); + _errHandler->sync(this); + + switch (getInterpreter()->adaptivePredict(_input, 32, _ctx)) { + case 1: { + setState(474); + match(CypherParser::SP); + setState(475); + match(CypherParser::AS); + setState(476); + match(CypherParser::SP); + setState(477); + oC_SchemaName(); + setState(478); + match(CypherParser::SP); + break; + } + + default: + break; + } + setState(496); + _errHandler->sync(this); + + switch (getInterpreter()->adaptivePredict(_input, 36, _ctx)) { + case 1: { + setState(483); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(482); + match(CypherParser::SP); + } + setState(485); + match(CypherParser::T__1); + setState(487); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(486); + match(CypherParser::SP); + } + setState(489); + match(CypherParser::DBTYPE); + setState(490); + match(CypherParser::SP); + setState(491); + match(CypherParser::StringLiteral); + setState(493); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(492); + match(CypherParser::SP); + } + setState(495); + match(CypherParser::T__3); + break; + } + + default: + break; + } + + } + catch (RecognitionException &e) { + _errHandler->reportError(this, e); + _localctx->exception = std::current_exception(); + _errHandler->recover(this, _localctx->exception); + } + + return _localctx; +} + +//----------------- KU_DetachDatabaseContext ------------------------------------------------------------------ + +CypherParser::KU_DetachDatabaseContext::KU_DetachDatabaseContext(ParserRuleContext *parent, size_t invokingState) + : ParserRuleContext(parent, invokingState) { +} + +tree::TerminalNode* CypherParser::KU_DetachDatabaseContext::DETACH() { + return getToken(CypherParser::DETACH, 0); } -tree::TerminalNode* CypherParser::KU_ImportDatabaseContext::DATABASE() { - return getToken(CypherParser::DATABASE, 0); +tree::TerminalNode* CypherParser::KU_DetachDatabaseContext::SP() { + return getToken(CypherParser::SP, 0); } -tree::TerminalNode* CypherParser::KU_ImportDatabaseContext::StringLiteral() { - return getToken(CypherParser::StringLiteral, 0); +CypherParser::OC_SchemaNameContext* CypherParser::KU_DetachDatabaseContext::oC_SchemaName() { + return getRuleContext(0); } -size_t CypherParser::KU_ImportDatabaseContext::getRuleIndex() const { - return CypherParser::RuleKU_ImportDatabase; +size_t CypherParser::KU_DetachDatabaseContext::getRuleIndex() const { + return CypherParser::RuleKU_DetachDatabase; } -CypherParser::KU_ImportDatabaseContext* CypherParser::kU_ImportDatabase() { - KU_ImportDatabaseContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 16, CypherParser::RuleKU_ImportDatabase); +CypherParser::KU_DetachDatabaseContext* CypherParser::kU_DetachDatabase() { + KU_DetachDatabaseContext *_localctx = _tracker.createInstance(_ctx, getState()); + enterRule(_localctx, 22, CypherParser::RuleKU_DetachDatabase); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2184,16 +2439,12 @@ CypherParser::KU_ImportDatabaseContext* CypherParser::kU_ImportDatabase() { }); try { enterOuterAlt(_localctx, 1); - setState(472); - match(CypherParser::IMPORT); - setState(473); - match(CypherParser::SP); - setState(474); - match(CypherParser::DATABASE); - setState(475); + setState(498); + match(CypherParser::DETACH); + setState(499); match(CypherParser::SP); - setState(476); - match(CypherParser::StringLiteral); + setState(500); + oC_SchemaName(); } catch (RecognitionException &e) { @@ -2239,7 +2490,7 @@ size_t CypherParser::KU_StandaloneCallContext::getRuleIndex() const { CypherParser::KU_StandaloneCallContext* CypherParser::kU_StandaloneCall() { KU_StandaloneCallContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 18, CypherParser::RuleKU_StandaloneCall); + enterRule(_localctx, 24, CypherParser::RuleKU_StandaloneCall); size_t _la = 0; #if __cplusplus > 201703L @@ -2251,31 +2502,31 @@ CypherParser::KU_StandaloneCallContext* CypherParser::kU_StandaloneCall() { }); try { enterOuterAlt(_localctx, 1); - setState(478); + setState(502); match(CypherParser::CALL); - setState(479); + setState(503); match(CypherParser::SP); - setState(480); + setState(504); oC_SymbolicName(); - setState(482); + setState(506); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(481); + setState(505); match(CypherParser::SP); } - setState(484); + setState(508); match(CypherParser::T__4); - setState(486); + setState(510); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(485); + setState(509); match(CypherParser::SP); } - setState(488); + setState(512); oC_Literal(); } @@ -2294,8 +2545,8 @@ CypherParser::KU_CommentOnContext::KU_CommentOnContext(ParserRuleContext *parent : ParserRuleContext(parent, invokingState) { } -tree::TerminalNode* CypherParser::KU_CommentOnContext::COMMENT() { - return getToken(CypherParser::COMMENT, 0); +tree::TerminalNode* CypherParser::KU_CommentOnContext::COMMENT_() { + return getToken(CypherParser::COMMENT_, 0); } std::vector CypherParser::KU_CommentOnContext::SP() { @@ -2334,7 +2585,7 @@ size_t CypherParser::KU_CommentOnContext::getRuleIndex() const { CypherParser::KU_CommentOnContext* CypherParser::kU_CommentOn() { KU_CommentOnContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 20, CypherParser::RuleKU_CommentOn); + enterRule(_localctx, 26, CypherParser::RuleKU_CommentOn); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -2345,27 +2596,27 @@ CypherParser::KU_CommentOnContext* CypherParser::kU_CommentOn() { }); try { enterOuterAlt(_localctx, 1); - setState(490); - match(CypherParser::COMMENT); - setState(491); + setState(514); + match(CypherParser::COMMENT_); + setState(515); match(CypherParser::SP); - setState(492); + setState(516); match(CypherParser::ON); - setState(493); + setState(517); match(CypherParser::SP); - setState(494); + setState(518); match(CypherParser::TABLE); - setState(495); + setState(519); match(CypherParser::SP); - setState(496); + setState(520); oC_SchemaName(); - setState(497); + setState(521); match(CypherParser::SP); - setState(498); + setState(522); match(CypherParser::IS); - setState(499); + setState(523); match(CypherParser::SP); - setState(500); + setState(524); match(CypherParser::StringLiteral); } @@ -2432,7 +2683,7 @@ size_t CypherParser::KU_CreateMacroContext::getRuleIndex() const { CypherParser::KU_CreateMacroContext* CypherParser::kU_CreateMacro() { KU_CreateMacroContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 22, CypherParser::RuleKU_CreateMacro); + enterRule(_localctx, 28, CypherParser::RuleKU_CreateMacro); size_t _la = 0; #if __cplusplus > 201703L @@ -2445,32 +2696,32 @@ CypherParser::KU_CreateMacroContext* CypherParser::kU_CreateMacro() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(502); + setState(526); match(CypherParser::CREATE); - setState(503); + setState(527); match(CypherParser::SP); - setState(504); + setState(528); match(CypherParser::MACRO); - setState(505); + setState(529); match(CypherParser::SP); - setState(506); + setState(530); oC_FunctionName(); - setState(508); + setState(532); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(507); + setState(531); match(CypherParser::SP); } - setState(510); + setState(534); match(CypherParser::T__1); - setState(512); + setState(536); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 39, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 40, _ctx)) { case 1: { - setState(511); + setState(535); match(CypherParser::SP); break; } @@ -2478,12 +2729,12 @@ CypherParser::KU_CreateMacroContext* CypherParser::kU_CreateMacro() { default: break; } - setState(515); + setState(539); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 40, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 41, _ctx)) { case 1: { - setState(514); + setState(538); kU_PositionalArgs(); break; } @@ -2491,12 +2742,12 @@ CypherParser::KU_CreateMacroContext* CypherParser::kU_CreateMacro() { default: break; } - setState(518); + setState(542); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 41, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 42, _ctx)) { case 1: { - setState(517); + setState(541); match(CypherParser::SP); break; } @@ -2504,63 +2755,63 @@ CypherParser::KU_CreateMacroContext* CypherParser::kU_CreateMacro() { default: break; } - setState(521); + setState(545); _errHandler->sync(this); _la = _input->LA(1); - if (((((_la - 47) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 47)) & 17826753) != 0) || ((((_la - 118) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 118)) & 302256385) != 0)) { - setState(520); + if (((((_la - 49) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 49)) & 17826753) != 0) || ((((_la - 120) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 120)) & 302256385) != 0)) { + setState(544); kU_DefaultArg(); } - setState(533); + setState(557); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 45, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 46, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(524); + setState(548); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(523); + setState(547); match(CypherParser::SP); } - setState(526); - match(CypherParser::T__3); - setState(528); + setState(550); + match(CypherParser::T__2); + setState(552); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(527); + setState(551); match(CypherParser::SP); } - setState(530); + setState(554); kU_DefaultArg(); } - setState(535); + setState(559); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 45, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 46, _ctx); } - setState(537); + setState(561); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(536); + setState(560); match(CypherParser::SP); } - setState(539); - match(CypherParser::T__2); - setState(540); + setState(563); + match(CypherParser::T__3); + setState(564); match(CypherParser::SP); - setState(541); + setState(565); match(CypherParser::AS); - setState(542); + setState(566); match(CypherParser::SP); - setState(543); + setState(567); oC_Expression(); } @@ -2603,7 +2854,7 @@ size_t CypherParser::KU_PositionalArgsContext::getRuleIndex() const { CypherParser::KU_PositionalArgsContext* CypherParser::kU_PositionalArgs() { KU_PositionalArgsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 24, CypherParser::RuleKU_PositionalArgs); + enterRule(_localctx, 30, CypherParser::RuleKU_PositionalArgs); size_t _la = 0; #if __cplusplus > 201703L @@ -2616,37 +2867,37 @@ CypherParser::KU_PositionalArgsContext* CypherParser::kU_PositionalArgs() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(545); + setState(569); oC_SymbolicName(); - setState(556); + setState(580); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 49, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 50, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(547); + setState(571); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(546); + setState(570); match(CypherParser::SP); } - setState(549); - match(CypherParser::T__3); - setState(551); + setState(573); + match(CypherParser::T__2); + setState(575); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(550); + setState(574); match(CypherParser::SP); } - setState(553); + setState(577); oC_SymbolicName(); } - setState(558); + setState(582); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 49, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 50, _ctx); } } @@ -2693,7 +2944,7 @@ size_t CypherParser::KU_DefaultArgContext::getRuleIndex() const { CypherParser::KU_DefaultArgContext* CypherParser::kU_DefaultArg() { KU_DefaultArgContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 26, CypherParser::RuleKU_DefaultArg); + enterRule(_localctx, 32, CypherParser::RuleKU_DefaultArg); size_t _la = 0; #if __cplusplus > 201703L @@ -2705,29 +2956,29 @@ CypherParser::KU_DefaultArgContext* CypherParser::kU_DefaultArg() { }); try { enterOuterAlt(_localctx, 1); - setState(559); + setState(583); oC_SymbolicName(); - setState(561); + setState(585); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(560); + setState(584); match(CypherParser::SP); } - setState(563); + setState(587); match(CypherParser::COLON); - setState(564); + setState(588); match(CypherParser::T__4); - setState(566); + setState(590); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(565); + setState(589); match(CypherParser::SP); } - setState(568); + setState(592); oC_Literal(); } @@ -2774,7 +3025,7 @@ size_t CypherParser::KU_FilePathsContext::getRuleIndex() const { CypherParser::KU_FilePathsContext* CypherParser::kU_FilePaths() { KU_FilePathsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 28, CypherParser::RuleKU_FilePaths); + enterRule(_localctx, 34, CypherParser::RuleKU_FilePaths); size_t _la = 0; #if __cplusplus > 201703L @@ -2785,97 +3036,97 @@ CypherParser::KU_FilePathsContext* CypherParser::kU_FilePaths() { exitRule(); }); try { - setState(603); + setState(627); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::T__5: { enterOuterAlt(_localctx, 1); - setState(570); + setState(594); match(CypherParser::T__5); - setState(572); + setState(596); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(571); + setState(595); match(CypherParser::SP); } - setState(574); + setState(598); match(CypherParser::StringLiteral); - setState(585); + setState(609); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3 || _la == CypherParser::SP) { - setState(576); + while (_la == CypherParser::T__2 || _la == CypherParser::SP) { + setState(600); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(575); + setState(599); match(CypherParser::SP); } - setState(578); - match(CypherParser::T__3); - setState(580); + setState(602); + match(CypherParser::T__2); + setState(604); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(579); + setState(603); match(CypherParser::SP); } - setState(582); + setState(606); match(CypherParser::StringLiteral); - setState(587); + setState(611); _errHandler->sync(this); _la = _input->LA(1); } - setState(588); + setState(612); match(CypherParser::T__6); break; } case CypherParser::StringLiteral: { enterOuterAlt(_localctx, 2); - setState(589); + setState(613); match(CypherParser::StringLiteral); break; } case CypherParser::GLOB: { enterOuterAlt(_localctx, 3); - setState(590); + setState(614); match(CypherParser::GLOB); - setState(592); + setState(616); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(591); + setState(615); match(CypherParser::SP); } - setState(594); + setState(618); match(CypherParser::T__1); - setState(596); + setState(620); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(595); + setState(619); match(CypherParser::SP); } - setState(598); + setState(622); match(CypherParser::StringLiteral); - setState(600); + setState(624); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(599); + setState(623); match(CypherParser::SP); } - setState(602); - match(CypherParser::T__2); + setState(626); + match(CypherParser::T__3); break; } @@ -2923,7 +3174,7 @@ size_t CypherParser::KU_ParsingOptionsContext::getRuleIndex() const { CypherParser::KU_ParsingOptionsContext* CypherParser::kU_ParsingOptions() { KU_ParsingOptionsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 30, CypherParser::RuleKU_ParsingOptions); + enterRule(_localctx, 36, CypherParser::RuleKU_ParsingOptions); size_t _la = 0; #if __cplusplus > 201703L @@ -2936,38 +3187,58 @@ CypherParser::KU_ParsingOptionsContext* CypherParser::kU_ParsingOptions() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(605); + setState(629); + match(CypherParser::T__1); + setState(631); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(630); + match(CypherParser::SP); + } + setState(633); kU_ParsingOption(); - setState(616); + setState(644); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 62, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 64, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(607); + setState(635); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(606); + setState(634); match(CypherParser::SP); } - setState(609); - match(CypherParser::T__3); - setState(611); + setState(637); + match(CypherParser::T__2); + setState(639); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(610); + setState(638); match(CypherParser::SP); } - setState(613); + setState(641); kU_ParsingOption(); } - setState(618); + setState(646); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 62, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 64, _ctx); + } + setState(648); + _errHandler->sync(this); + + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(647); + match(CypherParser::SP); } + setState(650); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -3009,7 +3280,7 @@ size_t CypherParser::KU_ParsingOptionContext::getRuleIndex() const { CypherParser::KU_ParsingOptionContext* CypherParser::kU_ParsingOption() { KU_ParsingOptionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 32, CypherParser::RuleKU_ParsingOption); + enterRule(_localctx, 38, CypherParser::RuleKU_ParsingOption); size_t _la = 0; #if __cplusplus > 201703L @@ -3021,27 +3292,27 @@ CypherParser::KU_ParsingOptionContext* CypherParser::kU_ParsingOption() { }); try { enterOuterAlt(_localctx, 1); - setState(619); + setState(652); oC_SymbolicName(); - setState(621); + setState(654); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(620); + setState(653); match(CypherParser::SP); } - setState(623); + setState(656); match(CypherParser::T__4); - setState(625); + setState(658); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(624); + setState(657); match(CypherParser::SP); } - setState(627); + setState(660); oC_Literal(); } @@ -3092,7 +3363,7 @@ size_t CypherParser::KU_DDLContext::getRuleIndex() const { CypherParser::KU_DDLContext* CypherParser::kU_DDL() { KU_DDLContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 34, CypherParser::RuleKU_DDL); + enterRule(_localctx, 40, CypherParser::RuleKU_DDL); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -3102,47 +3373,47 @@ CypherParser::KU_DDLContext* CypherParser::kU_DDL() { exitRule(); }); try { - setState(635); + setState(668); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 65, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 68, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(629); + setState(662); kU_CreateNodeTable(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(630); + setState(663); kU_CreateRelTable(); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(631); + setState(664); kU_CreateRelTableGroup(); break; } case 4: { enterOuterAlt(_localctx, 4); - setState(632); + setState(665); kU_CreateRdfGraph(); break; } case 5: { enterOuterAlt(_localctx, 5); - setState(633); + setState(666); kU_DropTable(); break; } case 6: { enterOuterAlt(_localctx, 6); - setState(634); + setState(667); kU_AlterTable(); break; } @@ -3207,7 +3478,7 @@ size_t CypherParser::KU_CreateNodeTableContext::getRuleIndex() const { CypherParser::KU_CreateNodeTableContext* CypherParser::kU_CreateNodeTable() { KU_CreateNodeTableContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 36, CypherParser::RuleKU_CreateNodeTable); + enterRule(_localctx, 42, CypherParser::RuleKU_CreateNodeTable); size_t _la = 0; #if __cplusplus > 201703L @@ -3219,71 +3490,71 @@ CypherParser::KU_CreateNodeTableContext* CypherParser::kU_CreateNodeTable() { }); try { enterOuterAlt(_localctx, 1); - setState(637); + setState(670); match(CypherParser::CREATE); - setState(638); + setState(671); match(CypherParser::SP); - setState(639); + setState(672); match(CypherParser::NODE); - setState(640); + setState(673); match(CypherParser::SP); - setState(641); + setState(674); match(CypherParser::TABLE); - setState(642); + setState(675); match(CypherParser::SP); - setState(643); + setState(676); oC_SchemaName(); - setState(645); + setState(678); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(644); + setState(677); match(CypherParser::SP); } - setState(647); + setState(680); match(CypherParser::T__1); - setState(649); + setState(682); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(648); + setState(681); match(CypherParser::SP); } - setState(651); + setState(684); kU_PropertyDefinitions(); - setState(653); + setState(686); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(652); + setState(685); match(CypherParser::SP); } - setState(655); - match(CypherParser::T__3); - setState(657); + setState(688); + match(CypherParser::T__2); + setState(690); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(656); + setState(689); match(CypherParser::SP); } - setState(659); + setState(692); kU_CreateNodeConstraint(); - setState(662); + setState(695); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(661); + setState(694); match(CypherParser::SP); } - setState(664); - match(CypherParser::T__2); + setState(697); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -3345,7 +3616,7 @@ size_t CypherParser::KU_CreateRelTableContext::getRuleIndex() const { CypherParser::KU_CreateRelTableContext* CypherParser::kU_CreateRelTable() { KU_CreateRelTableContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 38, CypherParser::RuleKU_CreateRelTable); + enterRule(_localctx, 44, CypherParser::RuleKU_CreateRelTable); size_t _la = 0; #if __cplusplus > 201703L @@ -3357,71 +3628,71 @@ CypherParser::KU_CreateRelTableContext* CypherParser::kU_CreateRelTable() { }); try { enterOuterAlt(_localctx, 1); - setState(666); + setState(699); match(CypherParser::CREATE); - setState(667); + setState(700); match(CypherParser::SP); - setState(668); + setState(701); match(CypherParser::REL); - setState(669); + setState(702); match(CypherParser::SP); - setState(670); + setState(703); match(CypherParser::TABLE); - setState(671); + setState(704); match(CypherParser::SP); - setState(672); + setState(705); oC_SchemaName(); - setState(674); + setState(707); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(673); + setState(706); match(CypherParser::SP); } - setState(676); + setState(709); match(CypherParser::T__1); - setState(678); + setState(711); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(677); + setState(710); match(CypherParser::SP); } - setState(680); + setState(713); kU_RelTableConnection(); - setState(682); + setState(715); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(681); + setState(714); match(CypherParser::SP); } - setState(692); + setState(725); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 76, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 79, _ctx)) { case 1: { - setState(684); - match(CypherParser::T__3); - setState(686); + setState(717); + match(CypherParser::T__2); + setState(719); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(685); + setState(718); match(CypherParser::SP); } - setState(688); + setState(721); kU_PropertyDefinitions(); - setState(690); + setState(723); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(689); + setState(722); match(CypherParser::SP); } break; @@ -3430,34 +3701,34 @@ CypherParser::KU_CreateRelTableContext* CypherParser::kU_CreateRelTable() { default: break; } - setState(702); + setState(735); _errHandler->sync(this); _la = _input->LA(1); - if (_la == CypherParser::T__3) { - setState(694); - match(CypherParser::T__3); - setState(696); + if (_la == CypherParser::T__2) { + setState(727); + match(CypherParser::T__2); + setState(729); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(695); + setState(728); match(CypherParser::SP); } - setState(698); + setState(731); oC_SymbolicName(); - setState(700); + setState(733); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(699); + setState(732); match(CypherParser::SP); } } - setState(704); - match(CypherParser::T__2); + setState(737); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -3527,7 +3798,7 @@ size_t CypherParser::KU_CreateRelTableGroupContext::getRuleIndex() const { CypherParser::KU_CreateRelTableGroupContext* CypherParser::kU_CreateRelTableGroup() { KU_CreateRelTableGroupContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 40, CypherParser::RuleKU_CreateRelTableGroup); + enterRule(_localctx, 46, CypherParser::RuleKU_CreateRelTableGroup); size_t _la = 0; #if __cplusplus > 201703L @@ -3540,69 +3811,69 @@ CypherParser::KU_CreateRelTableGroupContext* CypherParser::kU_CreateRelTableGrou try { size_t alt; enterOuterAlt(_localctx, 1); - setState(706); + setState(739); match(CypherParser::CREATE); - setState(707); + setState(740); match(CypherParser::SP); - setState(708); + setState(741); match(CypherParser::REL); - setState(709); + setState(742); match(CypherParser::SP); - setState(710); + setState(743); match(CypherParser::TABLE); - setState(711); + setState(744); match(CypherParser::SP); - setState(712); + setState(745); match(CypherParser::GROUP); - setState(713); + setState(746); match(CypherParser::SP); - setState(714); + setState(747); oC_SchemaName(); - setState(716); + setState(749); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(715); + setState(748); match(CypherParser::SP); } - setState(718); + setState(751); match(CypherParser::T__1); - setState(720); + setState(753); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(719); + setState(752); match(CypherParser::SP); } - setState(722); + setState(755); kU_RelTableConnection(); - setState(724); + setState(757); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(723); + setState(756); match(CypherParser::SP); } - setState(731); + setState(764); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(726); - match(CypherParser::T__3); - setState(728); + setState(759); + match(CypherParser::T__2); + setState(761); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(727); + setState(760); match(CypherParser::SP); } - setState(730); + setState(763); kU_RelTableConnection(); break; } @@ -3610,41 +3881,41 @@ CypherParser::KU_CreateRelTableGroupContext* CypherParser::kU_CreateRelTableGrou default: throw NoViableAltException(this); } - setState(733); + setState(766); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 84, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 87, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); - setState(736); + setState(769); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(735); + setState(768); match(CypherParser::SP); } - setState(746); + setState(779); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 88, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 91, _ctx)) { case 1: { - setState(738); - match(CypherParser::T__3); - setState(740); + setState(771); + match(CypherParser::T__2); + setState(773); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(739); + setState(772); match(CypherParser::SP); } - setState(742); + setState(775); kU_PropertyDefinitions(); - setState(744); + setState(777); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(743); + setState(776); match(CypherParser::SP); } break; @@ -3653,34 +3924,34 @@ CypherParser::KU_CreateRelTableGroupContext* CypherParser::kU_CreateRelTableGrou default: break; } - setState(756); + setState(789); _errHandler->sync(this); _la = _input->LA(1); - if (_la == CypherParser::T__3) { - setState(748); - match(CypherParser::T__3); - setState(750); + if (_la == CypherParser::T__2) { + setState(781); + match(CypherParser::T__2); + setState(783); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(749); + setState(782); match(CypherParser::SP); } - setState(752); + setState(785); oC_SymbolicName(); - setState(754); + setState(787); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(753); + setState(786); match(CypherParser::SP); } } - setState(758); - match(CypherParser::T__2); + setState(791); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -3730,7 +4001,7 @@ size_t CypherParser::KU_RelTableConnectionContext::getRuleIndex() const { CypherParser::KU_RelTableConnectionContext* CypherParser::kU_RelTableConnection() { KU_RelTableConnectionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 42, CypherParser::RuleKU_RelTableConnection); + enterRule(_localctx, 48, CypherParser::RuleKU_RelTableConnection); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -3741,19 +4012,19 @@ CypherParser::KU_RelTableConnectionContext* CypherParser::kU_RelTableConnection( }); try { enterOuterAlt(_localctx, 1); - setState(760); + setState(793); match(CypherParser::FROM); - setState(761); + setState(794); match(CypherParser::SP); - setState(762); + setState(795); oC_SchemaName(); - setState(763); + setState(796); match(CypherParser::SP); - setState(764); + setState(797); match(CypherParser::TO); - setState(765); + setState(798); match(CypherParser::SP); - setState(766); + setState(799); oC_SchemaName(); } @@ -3800,7 +4071,7 @@ size_t CypherParser::KU_CreateRdfGraphContext::getRuleIndex() const { CypherParser::KU_CreateRdfGraphContext* CypherParser::kU_CreateRdfGraph() { KU_CreateRdfGraphContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 44, CypherParser::RuleKU_CreateRdfGraph); + enterRule(_localctx, 50, CypherParser::RuleKU_CreateRdfGraph); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -3811,15 +4082,15 @@ CypherParser::KU_CreateRdfGraphContext* CypherParser::kU_CreateRdfGraph() { }); try { enterOuterAlt(_localctx, 1); - setState(768); + setState(801); match(CypherParser::CREATE); - setState(769); + setState(802); match(CypherParser::SP); - setState(770); + setState(803); match(CypherParser::RDFGRAPH); - setState(771); + setState(804); match(CypherParser::SP); - setState(772); + setState(805); oC_SchemaName(); } @@ -3870,7 +4141,7 @@ size_t CypherParser::KU_DropTableContext::getRuleIndex() const { CypherParser::KU_DropTableContext* CypherParser::kU_DropTable() { KU_DropTableContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 46, CypherParser::RuleKU_DropTable); + enterRule(_localctx, 52, CypherParser::RuleKU_DropTable); size_t _la = 0; #if __cplusplus > 201703L @@ -3882,11 +4153,11 @@ CypherParser::KU_DropTableContext* CypherParser::kU_DropTable() { }); try { enterOuterAlt(_localctx, 1); - setState(774); + setState(807); match(CypherParser::DROP); - setState(775); + setState(808); match(CypherParser::SP); - setState(776); + setState(809); _la = _input->LA(1); if (!(_la == CypherParser::TABLE @@ -3897,9 +4168,9 @@ CypherParser::KU_DropTableContext* CypherParser::kU_DropTable() { _errHandler->reportMatch(this); consume(); } - setState(777); + setState(810); match(CypherParser::SP); - setState(778); + setState(811); oC_SchemaName(); } @@ -3950,7 +4221,7 @@ size_t CypherParser::KU_AlterTableContext::getRuleIndex() const { CypherParser::KU_AlterTableContext* CypherParser::kU_AlterTable() { KU_AlterTableContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 48, CypherParser::RuleKU_AlterTable); + enterRule(_localctx, 54, CypherParser::RuleKU_AlterTable); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -3961,19 +4232,19 @@ CypherParser::KU_AlterTableContext* CypherParser::kU_AlterTable() { }); try { enterOuterAlt(_localctx, 1); - setState(780); + setState(813); match(CypherParser::ALTER); - setState(781); + setState(814); match(CypherParser::SP); - setState(782); + setState(815); match(CypherParser::TABLE); - setState(783); + setState(816); match(CypherParser::SP); - setState(784); + setState(817); oC_SchemaName(); - setState(785); + setState(818); match(CypherParser::SP); - setState(786); + setState(819); kU_AlterOptions(); } @@ -4016,7 +4287,7 @@ size_t CypherParser::KU_AlterOptionsContext::getRuleIndex() const { CypherParser::KU_AlterOptionsContext* CypherParser::kU_AlterOptions() { KU_AlterOptionsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 50, CypherParser::RuleKU_AlterOptions); + enterRule(_localctx, 56, CypherParser::RuleKU_AlterOptions); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4026,33 +4297,33 @@ CypherParser::KU_AlterOptionsContext* CypherParser::kU_AlterOptions() { exitRule(); }); try { - setState(792); + setState(825); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 92, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 95, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(788); + setState(821); kU_AddProperty(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(789); + setState(822); kU_DropProperty(); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(790); + setState(823); kU_RenameTable(); break; } case 4: { enterOuterAlt(_localctx, 4); - setState(791); + setState(824); kU_RenameProperty(); break; } @@ -4113,7 +4384,7 @@ size_t CypherParser::KU_AddPropertyContext::getRuleIndex() const { CypherParser::KU_AddPropertyContext* CypherParser::kU_AddProperty() { KU_AddPropertyContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 52, CypherParser::RuleKU_AddProperty); + enterRule(_localctx, 58, CypherParser::RuleKU_AddProperty); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4124,28 +4395,28 @@ CypherParser::KU_AddPropertyContext* CypherParser::kU_AddProperty() { }); try { enterOuterAlt(_localctx, 1); - setState(794); + setState(827); match(CypherParser::ADD); - setState(795); + setState(828); match(CypherParser::SP); - setState(796); + setState(829); oC_PropertyKeyName(); - setState(797); + setState(830); match(CypherParser::SP); - setState(798); + setState(831); kU_DataType(0); - setState(803); + setState(836); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 93, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 96, _ctx)) { case 1: { - setState(799); + setState(832); match(CypherParser::SP); - setState(800); + setState(833); match(CypherParser::DEFAULT); - setState(801); + setState(834); match(CypherParser::SP); - setState(802); + setState(835); oC_Expression(); break; } @@ -4190,7 +4461,7 @@ size_t CypherParser::KU_DropPropertyContext::getRuleIndex() const { CypherParser::KU_DropPropertyContext* CypherParser::kU_DropProperty() { KU_DropPropertyContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 54, CypherParser::RuleKU_DropProperty); + enterRule(_localctx, 60, CypherParser::RuleKU_DropProperty); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4201,11 +4472,11 @@ CypherParser::KU_DropPropertyContext* CypherParser::kU_DropProperty() { }); try { enterOuterAlt(_localctx, 1); - setState(805); + setState(838); match(CypherParser::DROP); - setState(806); + setState(839); match(CypherParser::SP); - setState(807); + setState(840); oC_PropertyKeyName(); } @@ -4252,7 +4523,7 @@ size_t CypherParser::KU_RenameTableContext::getRuleIndex() const { CypherParser::KU_RenameTableContext* CypherParser::kU_RenameTable() { KU_RenameTableContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 56, CypherParser::RuleKU_RenameTable); + enterRule(_localctx, 62, CypherParser::RuleKU_RenameTable); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4263,15 +4534,15 @@ CypherParser::KU_RenameTableContext* CypherParser::kU_RenameTable() { }); try { enterOuterAlt(_localctx, 1); - setState(809); + setState(842); match(CypherParser::RENAME); - setState(810); + setState(843); match(CypherParser::SP); - setState(811); + setState(844); match(CypherParser::TO); - setState(812); + setState(845); match(CypherParser::SP); - setState(813); + setState(846); oC_SchemaName(); } @@ -4322,7 +4593,7 @@ size_t CypherParser::KU_RenamePropertyContext::getRuleIndex() const { CypherParser::KU_RenamePropertyContext* CypherParser::kU_RenameProperty() { KU_RenamePropertyContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 58, CypherParser::RuleKU_RenameProperty); + enterRule(_localctx, 64, CypherParser::RuleKU_RenameProperty); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4333,19 +4604,19 @@ CypherParser::KU_RenamePropertyContext* CypherParser::kU_RenameProperty() { }); try { enterOuterAlt(_localctx, 1); - setState(815); + setState(848); match(CypherParser::RENAME); - setState(816); + setState(849); match(CypherParser::SP); - setState(817); + setState(850); oC_PropertyKeyName(); - setState(818); + setState(851); match(CypherParser::SP); - setState(819); + setState(852); match(CypherParser::TO); - setState(820); + setState(853); match(CypherParser::SP); - setState(821); + setState(854); oC_PropertyKeyName(); } @@ -4388,7 +4659,7 @@ size_t CypherParser::KU_PropertyDefinitionsContext::getRuleIndex() const { CypherParser::KU_PropertyDefinitionsContext* CypherParser::kU_PropertyDefinitions() { KU_PropertyDefinitionsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 60, CypherParser::RuleKU_PropertyDefinitions); + enterRule(_localctx, 66, CypherParser::RuleKU_PropertyDefinitions); size_t _la = 0; #if __cplusplus > 201703L @@ -4401,37 +4672,37 @@ CypherParser::KU_PropertyDefinitionsContext* CypherParser::kU_PropertyDefinition try { size_t alt; enterOuterAlt(_localctx, 1); - setState(823); + setState(856); kU_PropertyDefinition(); - setState(834); + setState(867); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 96, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 99, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(825); + setState(858); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(824); + setState(857); match(CypherParser::SP); } - setState(827); - match(CypherParser::T__3); - setState(829); + setState(860); + match(CypherParser::T__2); + setState(862); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(828); + setState(861); match(CypherParser::SP); } - setState(831); + setState(864); kU_PropertyDefinition(); } - setState(836); + setState(869); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 96, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 99, _ctx); } } @@ -4470,7 +4741,7 @@ size_t CypherParser::KU_PropertyDefinitionContext::getRuleIndex() const { CypherParser::KU_PropertyDefinitionContext* CypherParser::kU_PropertyDefinition() { KU_PropertyDefinitionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 62, CypherParser::RuleKU_PropertyDefinition); + enterRule(_localctx, 68, CypherParser::RuleKU_PropertyDefinition); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4481,11 +4752,11 @@ CypherParser::KU_PropertyDefinitionContext* CypherParser::kU_PropertyDefinition( }); try { enterOuterAlt(_localctx, 1); - setState(837); + setState(870); oC_PropertyKeyName(); - setState(838); + setState(871); match(CypherParser::SP); - setState(839); + setState(872); kU_DataType(0); } @@ -4532,7 +4803,7 @@ size_t CypherParser::KU_CreateNodeConstraintContext::getRuleIndex() const { CypherParser::KU_CreateNodeConstraintContext* CypherParser::kU_CreateNodeConstraint() { KU_CreateNodeConstraintContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 64, CypherParser::RuleKU_CreateNodeConstraint); + enterRule(_localctx, 70, CypherParser::RuleKU_CreateNodeConstraint); size_t _la = 0; #if __cplusplus > 201703L @@ -4544,42 +4815,42 @@ CypherParser::KU_CreateNodeConstraintContext* CypherParser::kU_CreateNodeConstra }); try { enterOuterAlt(_localctx, 1); - setState(841); + setState(874); match(CypherParser::PRIMARY); - setState(842); + setState(875); match(CypherParser::SP); - setState(843); + setState(876); match(CypherParser::KEY); - setState(845); + setState(878); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(844); + setState(877); match(CypherParser::SP); } - setState(847); + setState(880); match(CypherParser::T__1); - setState(849); + setState(882); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(848); + setState(881); match(CypherParser::SP); } - setState(851); + setState(884); oC_PropertyKeyName(); - setState(853); + setState(886); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(852); + setState(885); match(CypherParser::SP); } - setState(855); - match(CypherParser::T__2); + setState(888); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -4646,8 +4917,8 @@ CypherParser::KU_DataTypeContext* CypherParser::kU_DataType(int precedence) { CypherParser::KU_DataTypeContext *_localctx = _tracker.createInstance(_ctx, parentState); CypherParser::KU_DataTypeContext *previousContext = _localctx; (void)previousContext; // Silence compiler, in case the context is not used by generated code. - size_t startState = 66; - enterRecursionRule(_localctx, 66, CypherParser::RuleKU_DataType, precedence); + size_t startState = 72; + enterRecursionRule(_localctx, 72, CypherParser::RuleKU_DataType, precedence); size_t _la = 0; @@ -4661,140 +4932,140 @@ CypherParser::KU_DataTypeContext* CypherParser::kU_DataType(int precedence) { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(909); + setState(942); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 111, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 114, _ctx)) { case 1: { - setState(858); + setState(891); oC_SymbolicName(); break; } case 2: { - setState(859); + setState(892); match(CypherParser::UNION); - setState(861); + setState(894); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(860); + setState(893); match(CypherParser::SP); } - setState(863); + setState(896); match(CypherParser::T__1); - setState(865); + setState(898); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(864); + setState(897); match(CypherParser::SP); } - setState(867); + setState(900); kU_PropertyDefinitions(); - setState(869); + setState(902); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(868); + setState(901); match(CypherParser::SP); } - setState(871); - match(CypherParser::T__2); + setState(904); + match(CypherParser::T__3); break; } case 3: { - setState(873); + setState(906); oC_SymbolicName(); - setState(875); + setState(908); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(874); + setState(907); match(CypherParser::SP); } - setState(877); + setState(910); match(CypherParser::T__1); - setState(879); + setState(912); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(878); + setState(911); match(CypherParser::SP); } - setState(881); + setState(914); kU_PropertyDefinitions(); - setState(883); + setState(916); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(882); + setState(915); match(CypherParser::SP); } - setState(885); - match(CypherParser::T__2); + setState(918); + match(CypherParser::T__3); break; } case 4: { - setState(887); + setState(920); oC_SymbolicName(); - setState(889); + setState(922); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(888); + setState(921); match(CypherParser::SP); } - setState(891); + setState(924); match(CypherParser::T__1); - setState(893); + setState(926); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(892); + setState(925); match(CypherParser::SP); } - setState(895); + setState(928); kU_DataType(0); - setState(897); + setState(930); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(896); + setState(929); match(CypherParser::SP); } - setState(899); - match(CypherParser::T__3); - setState(901); + setState(932); + match(CypherParser::T__2); + setState(934); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(900); + setState(933); match(CypherParser::SP); } - setState(903); + setState(936); kU_DataType(0); - setState(905); + setState(938); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(904); + setState(937); match(CypherParser::SP); } - setState(907); - match(CypherParser::T__2); + setState(940); + match(CypherParser::T__3); break; } @@ -4802,9 +5073,9 @@ CypherParser::KU_DataTypeContext* CypherParser::kU_DataType(int precedence) { break; } _ctx->stop = _input->LT(-1); - setState(915); + setState(948); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 112, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 115, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { if (!_parseListeners.empty()) @@ -4812,15 +5083,15 @@ CypherParser::KU_DataTypeContext* CypherParser::kU_DataType(int precedence) { previousContext = _localctx; _localctx = _tracker.createInstance(parentContext, parentState); pushNewRecursionContext(_localctx, startState, RuleKU_DataType); - setState(911); + setState(944); if (!(precpred(_ctx, 4))) throw FailedPredicateException(this, "precpred(_ctx, 4)"); - setState(912); + setState(945); kU_ListIdentifiers(); } - setState(917); + setState(950); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 112, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 115, _ctx); } } catch (RecognitionException &e) { @@ -4853,7 +5124,7 @@ size_t CypherParser::KU_ListIdentifiersContext::getRuleIndex() const { CypherParser::KU_ListIdentifiersContext* CypherParser::kU_ListIdentifiers() { KU_ListIdentifiersContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 68, CypherParser::RuleKU_ListIdentifiers); + enterRule(_localctx, 74, CypherParser::RuleKU_ListIdentifiers); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4865,19 +5136,19 @@ CypherParser::KU_ListIdentifiersContext* CypherParser::kU_ListIdentifiers() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(918); + setState(951); kU_ListIdentifier(); - setState(922); + setState(955); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 113, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 116, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(919); + setState(952); kU_ListIdentifier(); } - setState(924); + setState(957); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 113, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 116, _ctx); } } @@ -4908,7 +5179,7 @@ size_t CypherParser::KU_ListIdentifierContext::getRuleIndex() const { CypherParser::KU_ListIdentifierContext* CypherParser::kU_ListIdentifier() { KU_ListIdentifierContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 70, CypherParser::RuleKU_ListIdentifier); + enterRule(_localctx, 76, CypherParser::RuleKU_ListIdentifier); size_t _la = 0; #if __cplusplus > 201703L @@ -4920,17 +5191,17 @@ CypherParser::KU_ListIdentifierContext* CypherParser::kU_ListIdentifier() { }); try { enterOuterAlt(_localctx, 1); - setState(925); + setState(958); match(CypherParser::T__5); - setState(927); + setState(960); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::DecimalInteger) { - setState(926); + setState(959); oC_IntegerLiteral(); } - setState(929); + setState(962); match(CypherParser::T__6); } @@ -4965,7 +5236,7 @@ size_t CypherParser::OC_AnyCypherOptionContext::getRuleIndex() const { CypherParser::OC_AnyCypherOptionContext* CypherParser::oC_AnyCypherOption() { OC_AnyCypherOptionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 72, CypherParser::RuleOC_AnyCypherOption); + enterRule(_localctx, 78, CypherParser::RuleOC_AnyCypherOption); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -4975,19 +5246,19 @@ CypherParser::OC_AnyCypherOptionContext* CypherParser::oC_AnyCypherOption() { exitRule(); }); try { - setState(933); + setState(966); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::EXPLAIN: { enterOuterAlt(_localctx, 1); - setState(931); + setState(964); oC_Explain(); break; } case CypherParser::PROFILE: { enterOuterAlt(_localctx, 2); - setState(932); + setState(965); oC_Profile(); break; } @@ -5024,7 +5295,7 @@ size_t CypherParser::OC_ExplainContext::getRuleIndex() const { CypherParser::OC_ExplainContext* CypherParser::oC_Explain() { OC_ExplainContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 74, CypherParser::RuleOC_Explain); + enterRule(_localctx, 80, CypherParser::RuleOC_Explain); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5035,7 +5306,7 @@ CypherParser::OC_ExplainContext* CypherParser::oC_Explain() { }); try { enterOuterAlt(_localctx, 1); - setState(935); + setState(968); match(CypherParser::EXPLAIN); } @@ -5066,7 +5337,7 @@ size_t CypherParser::OC_ProfileContext::getRuleIndex() const { CypherParser::OC_ProfileContext* CypherParser::oC_Profile() { OC_ProfileContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 76, CypherParser::RuleOC_Profile); + enterRule(_localctx, 82, CypherParser::RuleOC_Profile); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5077,7 +5348,7 @@ CypherParser::OC_ProfileContext* CypherParser::oC_Profile() { }); try { enterOuterAlt(_localctx, 1); - setState(937); + setState(970); match(CypherParser::PROFILE); } @@ -5144,7 +5415,7 @@ size_t CypherParser::KU_TransactionContext::getRuleIndex() const { CypherParser::KU_TransactionContext* CypherParser::kU_Transaction() { KU_TransactionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 78, CypherParser::RuleKU_Transaction); + enterRule(_localctx, 84, CypherParser::RuleKU_Transaction); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5154,63 +5425,63 @@ CypherParser::KU_TransactionContext* CypherParser::kU_Transaction() { exitRule(); }); try { - setState(953); + setState(986); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 116, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 119, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(939); + setState(972); match(CypherParser::BEGIN); - setState(940); + setState(973); match(CypherParser::SP); - setState(941); + setState(974); match(CypherParser::TRANSACTION); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(942); + setState(975); match(CypherParser::BEGIN); - setState(943); + setState(976); match(CypherParser::SP); - setState(944); + setState(977); match(CypherParser::TRANSACTION); - setState(945); + setState(978); match(CypherParser::SP); - setState(946); + setState(979); match(CypherParser::READ); - setState(947); + setState(980); match(CypherParser::SP); - setState(948); + setState(981); match(CypherParser::ONLY); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(949); + setState(982); match(CypherParser::COMMIT); break; } case 4: { enterOuterAlt(_localctx, 4); - setState(950); + setState(983); match(CypherParser::COMMIT_SKIP_CHECKPOINT); break; } case 5: { enterOuterAlt(_localctx, 5); - setState(951); + setState(984); match(CypherParser::ROLLBACK); break; } case 6: { enterOuterAlt(_localctx, 6); - setState(952); + setState(985); match(CypherParser::ROLLBACK_SKIP_CHECKPOINT); break; } @@ -5251,7 +5522,7 @@ size_t CypherParser::KU_ExtensionContext::getRuleIndex() const { CypherParser::KU_ExtensionContext* CypherParser::kU_Extension() { KU_ExtensionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 80, CypherParser::RuleKU_Extension); + enterRule(_localctx, 86, CypherParser::RuleKU_Extension); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5261,19 +5532,19 @@ CypherParser::KU_ExtensionContext* CypherParser::kU_Extension() { exitRule(); }); try { - setState(957); + setState(990); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::LOAD: { enterOuterAlt(_localctx, 1); - setState(955); + setState(988); kU_LoadExtension(); break; } case CypherParser::INSTALL: { enterOuterAlt(_localctx, 2); - setState(956); + setState(989); kU_InstallExtension(); break; } @@ -5330,7 +5601,7 @@ size_t CypherParser::KU_LoadExtensionContext::getRuleIndex() const { CypherParser::KU_LoadExtensionContext* CypherParser::kU_LoadExtension() { KU_LoadExtensionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 82, CypherParser::RuleKU_LoadExtension); + enterRule(_localctx, 88, CypherParser::RuleKU_LoadExtension); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5341,24 +5612,24 @@ CypherParser::KU_LoadExtensionContext* CypherParser::kU_LoadExtension() { }); try { enterOuterAlt(_localctx, 1); - setState(959); + setState(992); match(CypherParser::LOAD); - setState(960); + setState(993); match(CypherParser::SP); - setState(961); + setState(994); match(CypherParser::EXTENSION); - setState(962); + setState(995); match(CypherParser::SP); - setState(965); + setState(998); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::StringLiteral: { - setState(963); + setState(996); match(CypherParser::StringLiteral); break; } - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -5371,7 +5642,7 @@ CypherParser::KU_LoadExtensionContext* CypherParser::kU_LoadExtension() { case CypherParser::HexLetter: case CypherParser::UnescapedSymbolicName: case CypherParser::EscapedSymbolicName: { - setState(964); + setState(997); oC_Variable(); break; } @@ -5416,7 +5687,7 @@ size_t CypherParser::KU_InstallExtensionContext::getRuleIndex() const { CypherParser::KU_InstallExtensionContext* CypherParser::kU_InstallExtension() { KU_InstallExtensionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 84, CypherParser::RuleKU_InstallExtension); + enterRule(_localctx, 90, CypherParser::RuleKU_InstallExtension); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5427,11 +5698,11 @@ CypherParser::KU_InstallExtensionContext* CypherParser::kU_InstallExtension() { }); try { enterOuterAlt(_localctx, 1); - setState(967); + setState(1000); match(CypherParser::INSTALL); - setState(968); + setState(1001); match(CypherParser::SP); - setState(969); + setState(1002); oC_Variable(); } @@ -5462,7 +5733,7 @@ size_t CypherParser::OC_QueryContext::getRuleIndex() const { CypherParser::OC_QueryContext* CypherParser::oC_Query() { OC_QueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 86, CypherParser::RuleOC_Query); + enterRule(_localctx, 92, CypherParser::RuleOC_Query); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5473,7 +5744,7 @@ CypherParser::OC_QueryContext* CypherParser::oC_Query() { }); try { enterOuterAlt(_localctx, 1); - setState(971); + setState(1004); oC_RegularQuery(); } @@ -5528,7 +5799,7 @@ size_t CypherParser::OC_RegularQueryContext::getRuleIndex() const { CypherParser::OC_RegularQueryContext* CypherParser::oC_RegularQuery() { OC_RegularQueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 88, CypherParser::RuleOC_RegularQuery); + enterRule(_localctx, 94, CypherParser::RuleOC_RegularQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -5540,52 +5811,52 @@ CypherParser::OC_RegularQueryContext* CypherParser::oC_RegularQuery() { }); try { size_t alt; - setState(994); + setState(1027); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 123, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 126, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(973); + setState(1006); oC_SingleQuery(); - setState(980); + setState(1013); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 120, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 123, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(975); + setState(1008); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(974); + setState(1007); match(CypherParser::SP); } - setState(977); + setState(1010); oC_Union(); } - setState(982); + setState(1015); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 120, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 123, _ctx); } break; } case 2: { enterOuterAlt(_localctx, 2); - setState(987); + setState(1020); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(983); + setState(1016); oC_Return(); - setState(985); + setState(1018); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(984); + setState(1017); match(CypherParser::SP); } break; @@ -5594,11 +5865,11 @@ CypherParser::OC_RegularQueryContext* CypherParser::oC_RegularQuery() { default: throw NoViableAltException(this); } - setState(989); + setState(1022); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 122, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 125, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); - setState(991); + setState(1024); oC_SingleQuery(); notifyReturnNotAtEnd(_localctx->start); break; @@ -5652,7 +5923,7 @@ size_t CypherParser::OC_UnionContext::getRuleIndex() const { CypherParser::OC_UnionContext* CypherParser::oC_Union() { OC_UnionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 90, CypherParser::RuleOC_Union); + enterRule(_localctx, 96, CypherParser::RuleOC_Union); size_t _la = 0; #if __cplusplus > 201703L @@ -5663,43 +5934,43 @@ CypherParser::OC_UnionContext* CypherParser::oC_Union() { exitRule(); }); try { - setState(1008); + setState(1041); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 126, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 129, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(996); + setState(1029); match(CypherParser::UNION); - setState(997); + setState(1030); match(CypherParser::SP); - setState(998); + setState(1031); match(CypherParser::ALL); - setState(1000); + setState(1033); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(999); + setState(1032); match(CypherParser::SP); } - setState(1002); + setState(1035); oC_SingleQuery(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1003); + setState(1036); match(CypherParser::UNION); - setState(1005); + setState(1038); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1004); + setState(1037); match(CypherParser::SP); } - setState(1007); + setState(1040); oC_SingleQuery(); break; } @@ -5740,7 +6011,7 @@ size_t CypherParser::OC_SingleQueryContext::getRuleIndex() const { CypherParser::OC_SingleQueryContext* CypherParser::oC_SingleQuery() { OC_SingleQueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 92, CypherParser::RuleOC_SingleQuery); + enterRule(_localctx, 98, CypherParser::RuleOC_SingleQuery); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -5750,19 +6021,19 @@ CypherParser::OC_SingleQueryContext* CypherParser::oC_SingleQuery() { exitRule(); }); try { - setState(1012); + setState(1045); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 127, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 130, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1010); + setState(1043); oC_SinglePartQuery(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1011); + setState(1044); oC_MultiPartQuery(); break; } @@ -5823,7 +6094,7 @@ size_t CypherParser::OC_SinglePartQueryContext::getRuleIndex() const { CypherParser::OC_SinglePartQueryContext* CypherParser::oC_SinglePartQuery() { OC_SinglePartQueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 94, CypherParser::RuleOC_SinglePartQuery); + enterRule(_localctx, 100, CypherParser::RuleOC_SinglePartQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -5835,92 +6106,92 @@ CypherParser::OC_SinglePartQueryContext* CypherParser::oC_SinglePartQuery() { }); try { size_t alt; - setState(1059); + setState(1092); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 138, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 141, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1020); + setState(1053); _errHandler->sync(this); _la = _input->LA(1); - while (((((_la - 46) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 46)) & 7971459301377) != 0)) { - setState(1014); + while (((((_la - 48) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 48)) & 7971459301377) != 0)) { + setState(1047); oC_ReadingClause(); - setState(1016); + setState(1049); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1015); + setState(1048); match(CypherParser::SP); } - setState(1022); + setState(1055); _errHandler->sync(this); _la = _input->LA(1); } - setState(1023); + setState(1056); oC_Return(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1030); + setState(1063); _errHandler->sync(this); _la = _input->LA(1); - while (((((_la - 46) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 46)) & 7971459301377) != 0)) { - setState(1024); + while (((((_la - 48) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 48)) & 7971459301377) != 0)) { + setState(1057); oC_ReadingClause(); - setState(1026); + setState(1059); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1025); + setState(1058); match(CypherParser::SP); } - setState(1032); + setState(1065); _errHandler->sync(this); _la = _input->LA(1); } - setState(1033); + setState(1066); oC_UpdatingClause(); - setState(1040); + setState(1073); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 133, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 136, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1035); + setState(1068); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1034); + setState(1067); match(CypherParser::SP); } - setState(1037); + setState(1070); oC_UpdatingClause(); } - setState(1042); + setState(1075); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 133, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 136, _ctx); } - setState(1047); + setState(1080); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 135, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 138, _ctx)) { case 1: { - setState(1044); + setState(1077); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1043); + setState(1076); match(CypherParser::SP); } - setState(1046); + setState(1079); oC_Return(); break; } @@ -5933,18 +6204,18 @@ CypherParser::OC_SinglePartQueryContext* CypherParser::oC_SinglePartQuery() { case 3: { enterOuterAlt(_localctx, 3); - setState(1053); + setState(1086); _errHandler->sync(this); _la = _input->LA(1); do { - setState(1049); + setState(1082); oC_ReadingClause(); - setState(1051); + setState(1084); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 136, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 139, _ctx)) { case 1: { - setState(1050); + setState(1083); match(CypherParser::SP); break; } @@ -5952,11 +6223,11 @@ CypherParser::OC_SinglePartQueryContext* CypherParser::oC_SinglePartQuery() { default: break; } - setState(1055); + setState(1088); _errHandler->sync(this); _la = _input->LA(1); - } while (((((_la - 46) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 46)) & 7971459301377) != 0)); + } while (((((_la - 48) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 48)) & 7971459301377) != 0)); notifyQueryNotConcludeWithReturn(_localctx->start); break; } @@ -6009,7 +6280,7 @@ size_t CypherParser::OC_MultiPartQueryContext::getRuleIndex() const { CypherParser::OC_MultiPartQueryContext* CypherParser::oC_MultiPartQuery() { OC_MultiPartQueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 96, CypherParser::RuleOC_MultiPartQuery); + enterRule(_localctx, 102, CypherParser::RuleOC_MultiPartQuery); size_t _la = 0; #if __cplusplus > 201703L @@ -6022,20 +6293,20 @@ CypherParser::OC_MultiPartQueryContext* CypherParser::oC_MultiPartQuery() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1065); + setState(1098); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(1061); + setState(1094); kU_QueryPart(); - setState(1063); + setState(1096); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1062); + setState(1095); match(CypherParser::SP); } break; @@ -6044,11 +6315,11 @@ CypherParser::OC_MultiPartQueryContext* CypherParser::oC_MultiPartQuery() { default: throw NoViableAltException(this); } - setState(1067); + setState(1100); _errHandler->sync(this); - alt = getInterpreter()->adaptivePredict(_input, 140, _ctx); + alt = getInterpreter()->adaptivePredict(_input, 143, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); - setState(1069); + setState(1102); oC_SinglePartQuery(); } @@ -6103,7 +6374,7 @@ size_t CypherParser::KU_QueryPartContext::getRuleIndex() const { CypherParser::KU_QueryPartContext* CypherParser::kU_QueryPart() { KU_QueryPartContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 98, CypherParser::RuleKU_QueryPart); + enterRule(_localctx, 104, CypherParser::RuleKU_QueryPart); size_t _la = 0; #if __cplusplus > 201703L @@ -6115,45 +6386,45 @@ CypherParser::KU_QueryPartContext* CypherParser::kU_QueryPart() { }); try { enterOuterAlt(_localctx, 1); - setState(1077); + setState(1110); _errHandler->sync(this); _la = _input->LA(1); - while (((((_la - 46) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 46)) & 7971459301377) != 0)) { - setState(1071); + while (((((_la - 48) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 48)) & 7971459301377) != 0)) { + setState(1104); oC_ReadingClause(); - setState(1073); + setState(1106); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1072); + setState(1105); match(CypherParser::SP); } - setState(1079); + setState(1112); _errHandler->sync(this); _la = _input->LA(1); } - setState(1086); + setState(1119); _errHandler->sync(this); _la = _input->LA(1); - while (((((_la - 89) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 89)) & 59) != 0)) { - setState(1080); + while (((((_la - 91) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 91)) & 59) != 0)) { + setState(1113); oC_UpdatingClause(); - setState(1082); + setState(1115); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1081); + setState(1114); match(CypherParser::SP); } - setState(1088); + setState(1121); _errHandler->sync(this); _la = _input->LA(1); } - setState(1089); + setState(1122); oC_With(); } @@ -6196,7 +6467,7 @@ size_t CypherParser::OC_UpdatingClauseContext::getRuleIndex() const { CypherParser::OC_UpdatingClauseContext* CypherParser::oC_UpdatingClause() { OC_UpdatingClauseContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 100, CypherParser::RuleOC_UpdatingClause); + enterRule(_localctx, 106, CypherParser::RuleOC_UpdatingClause); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6206,26 +6477,26 @@ CypherParser::OC_UpdatingClauseContext* CypherParser::oC_UpdatingClause() { exitRule(); }); try { - setState(1095); + setState(1128); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::CREATE: { enterOuterAlt(_localctx, 1); - setState(1091); + setState(1124); oC_Create(); break; } case CypherParser::MERGE: { enterOuterAlt(_localctx, 2); - setState(1092); + setState(1125); oC_Merge(); break; } case CypherParser::SET: { enterOuterAlt(_localctx, 3); - setState(1093); + setState(1126); oC_Set(); break; } @@ -6233,7 +6504,7 @@ CypherParser::OC_UpdatingClauseContext* CypherParser::oC_UpdatingClause() { case CypherParser::DETACH: case CypherParser::DELETE: { enterOuterAlt(_localctx, 4); - setState(1094); + setState(1127); oC_Delete(); break; } @@ -6282,7 +6553,7 @@ size_t CypherParser::OC_ReadingClauseContext::getRuleIndex() const { CypherParser::OC_ReadingClauseContext* CypherParser::oC_ReadingClause() { OC_ReadingClauseContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 102, CypherParser::RuleOC_ReadingClause); + enterRule(_localctx, 108, CypherParser::RuleOC_ReadingClause); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -6292,34 +6563,34 @@ CypherParser::OC_ReadingClauseContext* CypherParser::oC_ReadingClause() { exitRule(); }); try { - setState(1101); + setState(1134); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::OPTIONAL: case CypherParser::MATCH: { enterOuterAlt(_localctx, 1); - setState(1097); + setState(1130); oC_Match(); break; } case CypherParser::UNWIND: { enterOuterAlt(_localctx, 2); - setState(1098); + setState(1131); oC_Unwind(); break; } case CypherParser::CALL: { enterOuterAlt(_localctx, 3); - setState(1099); + setState(1132); kU_InQueryCall(); break; } case CypherParser::LOAD: { enterOuterAlt(_localctx, 4); - setState(1100); + setState(1133); kU_LoadFrom(); break; } @@ -6360,12 +6631,8 @@ tree::TerminalNode* CypherParser::KU_LoadFromContext::FROM() { return getToken(CypherParser::FROM, 0); } -CypherParser::KU_FilePathsContext* CypherParser::KU_LoadFromContext::kU_FilePaths() { - return getRuleContext(0); -} - -CypherParser::OC_VariableContext* CypherParser::KU_LoadFromContext::oC_Variable() { - return getRuleContext(0); +CypherParser::KU_ScanSourceContext* CypherParser::KU_LoadFromContext::kU_ScanSource() { + return getRuleContext(0); } tree::TerminalNode* CypherParser::KU_LoadFromContext::WITH() { @@ -6380,14 +6647,14 @@ CypherParser::KU_PropertyDefinitionsContext* CypherParser::KU_LoadFromContext::k return getRuleContext(0); } -CypherParser::OC_WhereContext* CypherParser::KU_LoadFromContext::oC_Where() { - return getRuleContext(0); -} - CypherParser::KU_ParsingOptionsContext* CypherParser::KU_LoadFromContext::kU_ParsingOptions() { return getRuleContext(0); } +CypherParser::OC_WhereContext* CypherParser::KU_LoadFromContext::oC_Where() { + return getRuleContext(0); +} + size_t CypherParser::KU_LoadFromContext::getRuleIndex() const { return CypherParser::RuleKU_LoadFrom; @@ -6396,7 +6663,7 @@ size_t CypherParser::KU_LoadFromContext::getRuleIndex() const { CypherParser::KU_LoadFromContext* CypherParser::kU_LoadFrom() { KU_LoadFromContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 104, CypherParser::RuleKU_LoadFrom); + enterRule(_localctx, 110, CypherParser::RuleKU_LoadFrom); size_t _la = 0; #if __cplusplus > 201703L @@ -6408,150 +6675,100 @@ CypherParser::KU_LoadFromContext* CypherParser::kU_LoadFrom() { }); try { enterOuterAlt(_localctx, 1); - setState(1103); + setState(1136); match(CypherParser::LOAD); - setState(1121); + setState(1154); _errHandler->sync(this); - switch (getInterpreter()->adaptivePredict(_input, 150, _ctx)) { + switch (getInterpreter()->adaptivePredict(_input, 153, _ctx)) { case 1: { - setState(1104); + setState(1137); match(CypherParser::SP); - setState(1105); + setState(1138); match(CypherParser::WITH); - setState(1106); + setState(1139); match(CypherParser::SP); - setState(1107); + setState(1140); match(CypherParser::HEADERS); - setState(1109); + setState(1142); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1108); + setState(1141); match(CypherParser::SP); } - setState(1111); + setState(1144); match(CypherParser::T__1); - setState(1113); + setState(1146); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1112); + setState(1145); match(CypherParser::SP); } - setState(1115); + setState(1148); kU_PropertyDefinitions(); - setState(1117); + setState(1150); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1116); + setState(1149); match(CypherParser::SP); } - setState(1119); - match(CypherParser::T__2); + setState(1152); + match(CypherParser::T__3); break; } default: break; } - setState(1123); + setState(1156); match(CypherParser::SP); - setState(1124); + setState(1157); match(CypherParser::FROM); - setState(1125); + setState(1158); match(CypherParser::SP); - setState(1143); + setState(1159); + kU_ScanSource(); + setState(1164); _errHandler->sync(this); - switch (_input->LA(1)) { - case CypherParser::T__5: - case CypherParser::GLOB: - case CypherParser::StringLiteral: { - setState(1126); - kU_FilePaths(); - setState(1140); - _errHandler->sync(this); - - switch (getInterpreter()->adaptivePredict(_input, 154, _ctx)) { - case 1: { - setState(1128); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(1127); - match(CypherParser::SP); - } - setState(1130); - match(CypherParser::T__1); - setState(1132); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(1131); - match(CypherParser::SP); - } - setState(1134); - kU_ParsingOptions(); - setState(1136); - _errHandler->sync(this); - - _la = _input->LA(1); - if (_la == CypherParser::SP) { - setState(1135); - match(CypherParser::SP); - } - setState(1138); - match(CypherParser::T__2); - break; - } - default: - break; - } - break; - } + switch (getInterpreter()->adaptivePredict(_input, 155, _ctx)) { + case 1: { + setState(1161); + _errHandler->sync(this); - case CypherParser::COMMENT: - case CypherParser::EXPORT: - case CypherParser::IMPORT: - case CypherParser::DATABASE: - case CypherParser::NODE: - case CypherParser::REL: - case CypherParser::BEGIN: - case CypherParser::IN: - case CypherParser::COUNT: - case CypherParser::END: - case CypherParser::HexLetter: - case CypherParser::UnescapedSymbolicName: - case CypherParser::EscapedSymbolicName: { - setState(1142); - oC_Variable(); - break; + _la = _input->LA(1); + if (_la == CypherParser::SP) { + setState(1160); + match(CypherParser::SP); } + setState(1163); + kU_ParsingOptions(); + break; + } default: - throw NoViableAltException(this); + break; } - setState(1149); + setState(1170); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 157, _ctx)) { case 1: { - setState(1146); + setState(1167); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1145); + setState(1166); match(CypherParser::SP); } - setState(1148); + setState(1169); oC_Where(); break; } @@ -6604,7 +6821,7 @@ size_t CypherParser::KU_InQueryCallContext::getRuleIndex() const { CypherParser::KU_InQueryCallContext* CypherParser::kU_InQueryCall() { KU_InQueryCallContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 106, CypherParser::RuleKU_InQueryCall); + enterRule(_localctx, 112, CypherParser::RuleKU_InQueryCall); size_t _la = 0; #if __cplusplus > 201703L @@ -6616,26 +6833,26 @@ CypherParser::KU_InQueryCallContext* CypherParser::kU_InQueryCall() { }); try { enterOuterAlt(_localctx, 1); - setState(1151); + setState(1172); match(CypherParser::CALL); - setState(1152); + setState(1173); match(CypherParser::SP); - setState(1153); + setState(1174); oC_FunctionInvocation(); - setState(1158); + setState(1179); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 159, _ctx)) { case 1: { - setState(1155); + setState(1176); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1154); + setState(1175); match(CypherParser::SP); } - setState(1157); + setState(1178); oC_Where(); break; } @@ -6692,7 +6909,7 @@ size_t CypherParser::OC_MatchContext::getRuleIndex() const { CypherParser::OC_MatchContext* CypherParser::oC_Match() { OC_MatchContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 108, CypherParser::RuleOC_Match); + enterRule(_localctx, 114, CypherParser::RuleOC_Match); size_t _la = 0; #if __cplusplus > 201703L @@ -6704,42 +6921,42 @@ CypherParser::OC_MatchContext* CypherParser::oC_Match() { }); try { enterOuterAlt(_localctx, 1); - setState(1162); + setState(1183); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::OPTIONAL) { - setState(1160); + setState(1181); match(CypherParser::OPTIONAL); - setState(1161); + setState(1182); match(CypherParser::SP); } - setState(1164); + setState(1185); match(CypherParser::MATCH); - setState(1166); + setState(1187); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1165); + setState(1186); match(CypherParser::SP); } - setState(1168); + setState(1189); oC_Pattern(); - setState(1173); + setState(1194); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 163, _ctx)) { case 1: { - setState(1170); + setState(1191); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1169); + setState(1190); match(CypherParser::SP); } - setState(1172); + setState(1193); oC_Where(); break; } @@ -6796,7 +7013,7 @@ size_t CypherParser::OC_UnwindContext::getRuleIndex() const { CypherParser::OC_UnwindContext* CypherParser::oC_Unwind() { OC_UnwindContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 110, CypherParser::RuleOC_Unwind); + enterRule(_localctx, 116, CypherParser::RuleOC_Unwind); size_t _la = 0; #if __cplusplus > 201703L @@ -6808,25 +7025,25 @@ CypherParser::OC_UnwindContext* CypherParser::oC_Unwind() { }); try { enterOuterAlt(_localctx, 1); - setState(1175); + setState(1196); match(CypherParser::UNWIND); - setState(1177); + setState(1198); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1176); + setState(1197); match(CypherParser::SP); } - setState(1179); + setState(1200); oC_Expression(); - setState(1180); + setState(1201); match(CypherParser::SP); - setState(1181); + setState(1202); match(CypherParser::AS); - setState(1182); + setState(1203); match(CypherParser::SP); - setState(1183); + setState(1204); oC_Variable(); } @@ -6865,7 +7082,7 @@ size_t CypherParser::OC_CreateContext::getRuleIndex() const { CypherParser::OC_CreateContext* CypherParser::oC_Create() { OC_CreateContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 112, CypherParser::RuleOC_Create); + enterRule(_localctx, 118, CypherParser::RuleOC_Create); size_t _la = 0; #if __cplusplus > 201703L @@ -6877,17 +7094,17 @@ CypherParser::OC_CreateContext* CypherParser::oC_Create() { }); try { enterOuterAlt(_localctx, 1); - setState(1185); + setState(1206); match(CypherParser::CREATE); - setState(1187); + setState(1208); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1186); + setState(1207); match(CypherParser::SP); } - setState(1189); + setState(1210); oC_Pattern(); } @@ -6938,7 +7155,7 @@ size_t CypherParser::OC_MergeContext::getRuleIndex() const { CypherParser::OC_MergeContext* CypherParser::oC_Merge() { OC_MergeContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 114, CypherParser::RuleOC_Merge); + enterRule(_localctx, 120, CypherParser::RuleOC_Merge); size_t _la = 0; #if __cplusplus > 201703L @@ -6951,29 +7168,29 @@ CypherParser::OC_MergeContext* CypherParser::oC_Merge() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1191); + setState(1212); match(CypherParser::MERGE); - setState(1193); + setState(1214); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1192); + setState(1213); match(CypherParser::SP); } - setState(1195); + setState(1216); oC_Pattern(); - setState(1200); + setState(1221); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 167, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1196); + setState(1217); match(CypherParser::SP); - setState(1197); + setState(1218); oC_MergeAction(); } - setState(1202); + setState(1223); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 167, _ctx); } @@ -7026,7 +7243,7 @@ size_t CypherParser::OC_MergeActionContext::getRuleIndex() const { CypherParser::OC_MergeActionContext* CypherParser::oC_MergeAction() { OC_MergeActionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 116, CypherParser::RuleOC_MergeAction); + enterRule(_localctx, 122, CypherParser::RuleOC_MergeAction); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7036,35 +7253,35 @@ CypherParser::OC_MergeActionContext* CypherParser::oC_MergeAction() { exitRule(); }); try { - setState(1213); + setState(1234); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 168, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1203); + setState(1224); match(CypherParser::ON); - setState(1204); + setState(1225); match(CypherParser::SP); - setState(1205); + setState(1226); match(CypherParser::MATCH); - setState(1206); + setState(1227); match(CypherParser::SP); - setState(1207); + setState(1228); oC_Set(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1208); + setState(1229); match(CypherParser::ON); - setState(1209); + setState(1230); match(CypherParser::SP); - setState(1210); + setState(1231); match(CypherParser::CREATE); - setState(1211); + setState(1232); match(CypherParser::SP); - setState(1212); + setState(1233); oC_Set(); break; } @@ -7117,7 +7334,7 @@ size_t CypherParser::OC_SetContext::getRuleIndex() const { CypherParser::OC_SetContext* CypherParser::oC_Set() { OC_SetContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 118, CypherParser::RuleOC_Set); + enterRule(_localctx, 124, CypherParser::RuleOC_Set); size_t _la = 0; #if __cplusplus > 201703L @@ -7130,45 +7347,45 @@ CypherParser::OC_SetContext* CypherParser::oC_Set() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1215); + setState(1236); match(CypherParser::SET); - setState(1217); + setState(1238); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1216); + setState(1237); match(CypherParser::SP); } - setState(1219); + setState(1240); oC_SetItem(); - setState(1230); + setState(1251); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 172, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1221); + setState(1242); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1220); + setState(1241); match(CypherParser::SP); } - setState(1223); - match(CypherParser::T__3); - setState(1225); + setState(1244); + match(CypherParser::T__2); + setState(1246); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1224); + setState(1245); match(CypherParser::SP); } - setState(1227); + setState(1248); oC_SetItem(); } - setState(1232); + setState(1253); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 172, _ctx); } @@ -7213,7 +7430,7 @@ size_t CypherParser::OC_SetItemContext::getRuleIndex() const { CypherParser::OC_SetItemContext* CypherParser::oC_SetItem() { OC_SetItemContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 120, CypherParser::RuleOC_SetItem); + enterRule(_localctx, 126, CypherParser::RuleOC_SetItem); size_t _la = 0; #if __cplusplus > 201703L @@ -7225,27 +7442,27 @@ CypherParser::OC_SetItemContext* CypherParser::oC_SetItem() { }); try { enterOuterAlt(_localctx, 1); - setState(1233); + setState(1254); oC_PropertyExpression(); - setState(1235); + setState(1256); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1234); + setState(1255); match(CypherParser::SP); } - setState(1237); + setState(1258); match(CypherParser::T__4); - setState(1239); + setState(1260); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1238); + setState(1259); match(CypherParser::SP); } - setState(1241); + setState(1262); oC_Expression(); } @@ -7296,7 +7513,7 @@ size_t CypherParser::OC_DeleteContext::getRuleIndex() const { CypherParser::OC_DeleteContext* CypherParser::oC_Delete() { OC_DeleteContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 122, CypherParser::RuleOC_Delete); + enterRule(_localctx, 128, CypherParser::RuleOC_Delete); size_t _la = 0; #if __cplusplus > 201703L @@ -7309,55 +7526,55 @@ CypherParser::OC_DeleteContext* CypherParser::oC_Delete() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1245); + setState(1266); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::DETACH) { - setState(1243); + setState(1264); match(CypherParser::DETACH); - setState(1244); + setState(1265); match(CypherParser::SP); } - setState(1247); + setState(1268); match(CypherParser::DELETE); - setState(1249); + setState(1270); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1248); + setState(1269); match(CypherParser::SP); } - setState(1251); + setState(1272); oC_Expression(); - setState(1262); + setState(1283); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 179, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1253); + setState(1274); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1252); + setState(1273); match(CypherParser::SP); } - setState(1255); - match(CypherParser::T__3); - setState(1257); + setState(1276); + match(CypherParser::T__2); + setState(1278); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1256); + setState(1277); match(CypherParser::SP); } - setState(1259); + setState(1280); oC_Expression(); } - setState(1264); + setState(1285); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 179, _ctx); } @@ -7402,7 +7619,7 @@ size_t CypherParser::OC_WithContext::getRuleIndex() const { CypherParser::OC_WithContext* CypherParser::oC_With() { OC_WithContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 124, CypherParser::RuleOC_With); + enterRule(_localctx, 130, CypherParser::RuleOC_With); size_t _la = 0; #if __cplusplus > 201703L @@ -7414,24 +7631,24 @@ CypherParser::OC_WithContext* CypherParser::oC_With() { }); try { enterOuterAlt(_localctx, 1); - setState(1265); + setState(1286); match(CypherParser::WITH); - setState(1266); + setState(1287); oC_ProjectionBody(); - setState(1271); + setState(1292); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 181, _ctx)) { case 1: { - setState(1268); + setState(1289); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1267); + setState(1288); match(CypherParser::SP); } - setState(1270); + setState(1291); oC_Where(); break; } @@ -7472,7 +7689,7 @@ size_t CypherParser::OC_ReturnContext::getRuleIndex() const { CypherParser::OC_ReturnContext* CypherParser::oC_Return() { OC_ReturnContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 126, CypherParser::RuleOC_Return); + enterRule(_localctx, 132, CypherParser::RuleOC_Return); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7483,9 +7700,9 @@ CypherParser::OC_ReturnContext* CypherParser::oC_Return() { }); try { enterOuterAlt(_localctx, 1); - setState(1273); + setState(1294); match(CypherParser::RETURN); - setState(1274); + setState(1295); oC_ProjectionBody(); } @@ -7540,7 +7757,7 @@ size_t CypherParser::OC_ProjectionBodyContext::getRuleIndex() const { CypherParser::OC_ProjectionBodyContext* CypherParser::oC_ProjectionBody() { OC_ProjectionBodyContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 128, CypherParser::RuleOC_ProjectionBody); + enterRule(_localctx, 134, CypherParser::RuleOC_ProjectionBody); size_t _la = 0; #if __cplusplus > 201703L @@ -7552,20 +7769,20 @@ CypherParser::OC_ProjectionBodyContext* CypherParser::oC_ProjectionBody() { }); try { enterOuterAlt(_localctx, 1); - setState(1280); + setState(1301); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 183, _ctx)) { case 1: { - setState(1277); + setState(1298); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1276); + setState(1297); match(CypherParser::SP); } - setState(1279); + setState(1300); match(CypherParser::DISTINCT); break; } @@ -7573,18 +7790,18 @@ CypherParser::OC_ProjectionBodyContext* CypherParser::oC_ProjectionBody() { default: break; } - setState(1282); + setState(1303); match(CypherParser::SP); - setState(1283); + setState(1304); oC_ProjectionItems(); - setState(1286); + setState(1307); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 184, _ctx)) { case 1: { - setState(1284); + setState(1305); match(CypherParser::SP); - setState(1285); + setState(1306); oC_Order(); break; } @@ -7592,14 +7809,14 @@ CypherParser::OC_ProjectionBodyContext* CypherParser::oC_ProjectionBody() { default: break; } - setState(1290); + setState(1311); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 185, _ctx)) { case 1: { - setState(1288); + setState(1309); match(CypherParser::SP); - setState(1289); + setState(1310); oC_Skip(); break; } @@ -7607,14 +7824,14 @@ CypherParser::OC_ProjectionBodyContext* CypherParser::oC_ProjectionBody() { default: break; } - setState(1294); + setState(1315); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 186, _ctx)) { case 1: { - setState(1292); + setState(1313); match(CypherParser::SP); - setState(1293); + setState(1314); oC_Limit(); break; } @@ -7667,7 +7884,7 @@ size_t CypherParser::OC_ProjectionItemsContext::getRuleIndex() const { CypherParser::OC_ProjectionItemsContext* CypherParser::oC_ProjectionItems() { OC_ProjectionItemsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 130, CypherParser::RuleOC_ProjectionItems); + enterRule(_localctx, 136, CypherParser::RuleOC_ProjectionItems); size_t _la = 0; #if __cplusplus > 201703L @@ -7679,40 +7896,40 @@ CypherParser::OC_ProjectionItemsContext* CypherParser::oC_ProjectionItems() { }); try { size_t alt; - setState(1324); + setState(1345); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::STAR: { enterOuterAlt(_localctx, 1); - setState(1296); + setState(1317); match(CypherParser::STAR); - setState(1307); + setState(1328); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 189, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1298); + setState(1319); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1297); + setState(1318); match(CypherParser::SP); } - setState(1300); - match(CypherParser::T__3); - setState(1302); + setState(1321); + match(CypherParser::T__2); + setState(1323); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1301); + setState(1322); match(CypherParser::SP); } - setState(1304); + setState(1325); oC_ProjectionItem(); } - setState(1309); + setState(1330); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 189, _ctx); } @@ -7723,7 +7940,7 @@ CypherParser::OC_ProjectionItemsContext* CypherParser::oC_ProjectionItems() { case CypherParser::T__5: case CypherParser::T__7: case CypherParser::T__25: - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -7747,35 +7964,35 @@ CypherParser::OC_ProjectionItemsContext* CypherParser::oC_ProjectionItems() { case CypherParser::UnescapedSymbolicName: case CypherParser::EscapedSymbolicName: { enterOuterAlt(_localctx, 2); - setState(1310); + setState(1331); oC_ProjectionItem(); - setState(1321); + setState(1342); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 192, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1312); + setState(1333); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1311); + setState(1332); match(CypherParser::SP); } - setState(1314); - match(CypherParser::T__3); - setState(1316); + setState(1335); + match(CypherParser::T__2); + setState(1337); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1315); + setState(1336); match(CypherParser::SP); } - setState(1318); + setState(1339); oC_ProjectionItem(); } - setState(1323); + setState(1344); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 192, _ctx); } @@ -7830,7 +8047,7 @@ size_t CypherParser::OC_ProjectionItemContext::getRuleIndex() const { CypherParser::OC_ProjectionItemContext* CypherParser::oC_ProjectionItem() { OC_ProjectionItemContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 132, CypherParser::RuleOC_ProjectionItem); + enterRule(_localctx, 138, CypherParser::RuleOC_ProjectionItem); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -7840,27 +8057,27 @@ CypherParser::OC_ProjectionItemContext* CypherParser::oC_ProjectionItem() { exitRule(); }); try { - setState(1333); + setState(1354); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 194, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1326); + setState(1347); oC_Expression(); - setState(1327); + setState(1348); match(CypherParser::SP); - setState(1328); + setState(1349); match(CypherParser::AS); - setState(1329); + setState(1350); match(CypherParser::SP); - setState(1330); + setState(1351); oC_Variable(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1332); + setState(1353); oC_Expression(); break; } @@ -7917,7 +8134,7 @@ size_t CypherParser::OC_OrderContext::getRuleIndex() const { CypherParser::OC_OrderContext* CypherParser::oC_Order() { OC_OrderContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 134, CypherParser::RuleOC_Order); + enterRule(_localctx, 140, CypherParser::RuleOC_Order); size_t _la = 0; #if __cplusplus > 201703L @@ -7929,33 +8146,33 @@ CypherParser::OC_OrderContext* CypherParser::oC_Order() { }); try { enterOuterAlt(_localctx, 1); - setState(1335); + setState(1356); match(CypherParser::ORDER); - setState(1336); + setState(1357); match(CypherParser::SP); - setState(1337); + setState(1358); match(CypherParser::BY); - setState(1338); + setState(1359); match(CypherParser::SP); - setState(1339); + setState(1360); oC_SortItem(); - setState(1347); + setState(1368); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3) { - setState(1340); - match(CypherParser::T__3); - setState(1342); + while (_la == CypherParser::T__2) { + setState(1361); + match(CypherParser::T__2); + setState(1363); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1341); + setState(1362); match(CypherParser::SP); } - setState(1344); + setState(1365); oC_SortItem(); - setState(1349); + setState(1370); _errHandler->sync(this); _la = _input->LA(1); } @@ -7996,7 +8213,7 @@ size_t CypherParser::OC_SkipContext::getRuleIndex() const { CypherParser::OC_SkipContext* CypherParser::oC_Skip() { OC_SkipContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 136, CypherParser::RuleOC_Skip); + enterRule(_localctx, 142, CypherParser::RuleOC_Skip); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8007,11 +8224,11 @@ CypherParser::OC_SkipContext* CypherParser::oC_Skip() { }); try { enterOuterAlt(_localctx, 1); - setState(1350); + setState(1371); match(CypherParser::L_SKIP); - setState(1351); + setState(1372); match(CypherParser::SP); - setState(1352); + setState(1373); oC_Expression(); } @@ -8050,7 +8267,7 @@ size_t CypherParser::OC_LimitContext::getRuleIndex() const { CypherParser::OC_LimitContext* CypherParser::oC_Limit() { OC_LimitContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 138, CypherParser::RuleOC_Limit); + enterRule(_localctx, 144, CypherParser::RuleOC_Limit); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8061,11 +8278,11 @@ CypherParser::OC_LimitContext* CypherParser::oC_Limit() { }); try { enterOuterAlt(_localctx, 1); - setState(1354); + setState(1375); match(CypherParser::LIMIT); - setState(1355); + setState(1376); match(CypherParser::SP); - setState(1356); + setState(1377); oC_Expression(); } @@ -8116,7 +8333,7 @@ size_t CypherParser::OC_SortItemContext::getRuleIndex() const { CypherParser::OC_SortItemContext* CypherParser::oC_SortItem() { OC_SortItemContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 140, CypherParser::RuleOC_SortItem); + enterRule(_localctx, 146, CypherParser::RuleOC_SortItem); size_t _la = 0; #if __cplusplus > 201703L @@ -8128,25 +8345,25 @@ CypherParser::OC_SortItemContext* CypherParser::oC_SortItem() { }); try { enterOuterAlt(_localctx, 1); - setState(1358); + setState(1379); oC_Expression(); - setState(1363); + setState(1384); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 198, _ctx)) { case 1: { - setState(1360); + setState(1381); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1359); + setState(1380); match(CypherParser::SP); } - setState(1362); + setState(1383); _la = _input->LA(1); - if (!(((((_la - 104) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 104)) & 15) != 0))) { + if (!(((((_la - 106) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 106)) & 15) != 0))) { _errHandler->recoverInline(this); } else { @@ -8196,7 +8413,7 @@ size_t CypherParser::OC_WhereContext::getRuleIndex() const { CypherParser::OC_WhereContext* CypherParser::oC_Where() { OC_WhereContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 142, CypherParser::RuleOC_Where); + enterRule(_localctx, 148, CypherParser::RuleOC_Where); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8207,11 +8424,11 @@ CypherParser::OC_WhereContext* CypherParser::oC_Where() { }); try { enterOuterAlt(_localctx, 1); - setState(1365); + setState(1386); match(CypherParser::WHERE); - setState(1366); + setState(1387); match(CypherParser::SP); - setState(1367); + setState(1388); oC_Expression(); } @@ -8254,7 +8471,7 @@ size_t CypherParser::OC_PatternContext::getRuleIndex() const { CypherParser::OC_PatternContext* CypherParser::oC_Pattern() { OC_PatternContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 144, CypherParser::RuleOC_Pattern); + enterRule(_localctx, 150, CypherParser::RuleOC_Pattern); size_t _la = 0; #if __cplusplus > 201703L @@ -8267,35 +8484,35 @@ CypherParser::OC_PatternContext* CypherParser::oC_Pattern() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1369); + setState(1390); oC_PatternPart(); - setState(1380); + setState(1401); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 201, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1371); + setState(1392); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1370); + setState(1391); match(CypherParser::SP); } - setState(1373); - match(CypherParser::T__3); - setState(1375); + setState(1394); + match(CypherParser::T__2); + setState(1396); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1374); + setState(1395); match(CypherParser::SP); } - setState(1377); + setState(1398); oC_PatternPart(); } - setState(1382); + setState(1403); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 201, _ctx); } @@ -8340,7 +8557,7 @@ size_t CypherParser::OC_PatternPartContext::getRuleIndex() const { CypherParser::OC_PatternPartContext* CypherParser::oC_PatternPart() { OC_PatternPartContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 146, CypherParser::RuleOC_PatternPart); + enterRule(_localctx, 152, CypherParser::RuleOC_PatternPart); size_t _la = 0; #if __cplusplus > 201703L @@ -8351,10 +8568,10 @@ CypherParser::OC_PatternPartContext* CypherParser::oC_PatternPart() { exitRule(); }); try { - setState(1394); + setState(1415); _errHandler->sync(this); switch (_input->LA(1)) { - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -8368,34 +8585,34 @@ CypherParser::OC_PatternPartContext* CypherParser::oC_PatternPart() { case CypherParser::UnescapedSymbolicName: case CypherParser::EscapedSymbolicName: { enterOuterAlt(_localctx, 1); - setState(1383); + setState(1404); oC_Variable(); - setState(1385); + setState(1406); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1384); + setState(1405); match(CypherParser::SP); } - setState(1387); + setState(1408); match(CypherParser::T__4); - setState(1389); + setState(1410); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1388); + setState(1409); match(CypherParser::SP); } - setState(1391); + setState(1412); oC_AnonymousPatternPart(); break; } case CypherParser::T__1: { enterOuterAlt(_localctx, 2); - setState(1393); + setState(1414); oC_AnonymousPatternPart(); break; } @@ -8432,7 +8649,7 @@ size_t CypherParser::OC_AnonymousPatternPartContext::getRuleIndex() const { CypherParser::OC_AnonymousPatternPartContext* CypherParser::oC_AnonymousPatternPart() { OC_AnonymousPatternPartContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 148, CypherParser::RuleOC_AnonymousPatternPart); + enterRule(_localctx, 154, CypherParser::RuleOC_AnonymousPatternPart); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -8443,7 +8660,7 @@ CypherParser::OC_AnonymousPatternPartContext* CypherParser::oC_AnonymousPatternP }); try { enterOuterAlt(_localctx, 1); - setState(1396); + setState(1417); oC_PatternElement(); } @@ -8494,7 +8711,7 @@ size_t CypherParser::OC_PatternElementContext::getRuleIndex() const { CypherParser::OC_PatternElementContext* CypherParser::oC_PatternElement() { OC_PatternElementContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 150, CypherParser::RuleOC_PatternElement); + enterRule(_localctx, 156, CypherParser::RuleOC_PatternElement); size_t _la = 0; #if __cplusplus > 201703L @@ -8506,30 +8723,30 @@ CypherParser::OC_PatternElementContext* CypherParser::oC_PatternElement() { }); try { size_t alt; - setState(1412); + setState(1433); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 207, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1398); + setState(1419); oC_NodePattern(); - setState(1405); + setState(1426); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 206, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1400); + setState(1421); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1399); + setState(1420); match(CypherParser::SP); } - setState(1402); + setState(1423); oC_PatternElementChain(); } - setState(1407); + setState(1428); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 206, _ctx); } @@ -8538,12 +8755,12 @@ CypherParser::OC_PatternElementContext* CypherParser::oC_PatternElement() { case 2: { enterOuterAlt(_localctx, 2); - setState(1408); + setState(1429); match(CypherParser::T__1); - setState(1409); + setState(1430); oC_PatternElement(); - setState(1410); - match(CypherParser::T__2); + setState(1431); + match(CypherParser::T__3); break; } @@ -8595,7 +8812,7 @@ size_t CypherParser::OC_NodePatternContext::getRuleIndex() const { CypherParser::OC_NodePatternContext* CypherParser::oC_NodePattern() { OC_NodePatternContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 152, CypherParser::RuleOC_NodePattern); + enterRule(_localctx, 158, CypherParser::RuleOC_NodePattern); size_t _la = 0; #if __cplusplus > 201703L @@ -8607,68 +8824,68 @@ CypherParser::OC_NodePatternContext* CypherParser::oC_NodePattern() { }); try { enterOuterAlt(_localctx, 1); - setState(1414); + setState(1435); match(CypherParser::T__1); - setState(1416); + setState(1437); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1415); + setState(1436); match(CypherParser::SP); } - setState(1422); + setState(1443); _errHandler->sync(this); _la = _input->LA(1); - if (((((_la - 47) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 47)) & 17826753) != 0) || ((((_la - 118) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 118)) & 302256385) != 0)) { - setState(1418); + if (((((_la - 49) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 49)) & 17826753) != 0) || ((((_la - 120) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 120)) & 302256385) != 0)) { + setState(1439); oC_Variable(); - setState(1420); + setState(1441); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1419); + setState(1440); match(CypherParser::SP); } } - setState(1428); + setState(1449); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::COLON) { - setState(1424); + setState(1445); oC_NodeLabels(); - setState(1426); + setState(1447); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1425); + setState(1446); match(CypherParser::SP); } } - setState(1434); + setState(1455); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::T__7) { - setState(1430); + setState(1451); kU_Properties(); - setState(1432); + setState(1453); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1431); + setState(1452); match(CypherParser::SP); } } - setState(1436); - match(CypherParser::T__2); + setState(1457); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -8706,7 +8923,7 @@ size_t CypherParser::OC_PatternElementChainContext::getRuleIndex() const { CypherParser::OC_PatternElementChainContext* CypherParser::oC_PatternElementChain() { OC_PatternElementChainContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 154, CypherParser::RuleOC_PatternElementChain); + enterRule(_localctx, 160, CypherParser::RuleOC_PatternElementChain); size_t _la = 0; #if __cplusplus > 201703L @@ -8718,17 +8935,17 @@ CypherParser::OC_PatternElementChainContext* CypherParser::oC_PatternElementChai }); try { enterOuterAlt(_localctx, 1); - setState(1438); + setState(1459); oC_RelationshipPattern(); - setState(1440); + setState(1461); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1439); + setState(1460); match(CypherParser::SP); } - setState(1442); + setState(1463); oC_NodePattern(); } @@ -8783,7 +9000,7 @@ size_t CypherParser::OC_RelationshipPatternContext::getRuleIndex() const { CypherParser::OC_RelationshipPatternContext* CypherParser::oC_RelationshipPattern() { OC_RelationshipPatternContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 156, CypherParser::RuleOC_RelationshipPattern); + enterRule(_localctx, 162, CypherParser::RuleOC_RelationshipPattern); size_t _la = 0; #if __cplusplus > 201703L @@ -8794,29 +9011,29 @@ CypherParser::OC_RelationshipPatternContext* CypherParser::oC_RelationshipPatter exitRule(); }); try { - setState(1488); + setState(1509); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 227, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1444); + setState(1465); oC_LeftArrowHead(); - setState(1446); + setState(1467); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1445); + setState(1466); match(CypherParser::SP); } - setState(1448); + setState(1469); oC_Dash(); - setState(1450); + setState(1471); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 217, _ctx)) { case 1: { - setState(1449); + setState(1470); match(CypherParser::SP); break; } @@ -8824,37 +9041,37 @@ CypherParser::OC_RelationshipPatternContext* CypherParser::oC_RelationshipPatter default: break; } - setState(1453); + setState(1474); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::T__5) { - setState(1452); + setState(1473); oC_RelationshipDetail(); } - setState(1456); + setState(1477); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1455); + setState(1476); match(CypherParser::SP); } - setState(1458); + setState(1479); oC_Dash(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1460); + setState(1481); oC_Dash(); - setState(1462); + setState(1483); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 220, _ctx)) { case 1: { - setState(1461); + setState(1482); match(CypherParser::SP); break; } @@ -8862,47 +9079,47 @@ CypherParser::OC_RelationshipPatternContext* CypherParser::oC_RelationshipPatter default: break; } - setState(1465); + setState(1486); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::T__5) { - setState(1464); + setState(1485); oC_RelationshipDetail(); } - setState(1468); + setState(1489); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1467); + setState(1488); match(CypherParser::SP); } - setState(1470); + setState(1491); oC_Dash(); - setState(1472); + setState(1493); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1471); + setState(1492); match(CypherParser::SP); } - setState(1474); + setState(1495); oC_RightArrowHead(); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(1476); + setState(1497); oC_Dash(); - setState(1478); + setState(1499); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 224, _ctx)) { case 1: { - setState(1477); + setState(1498); match(CypherParser::SP); break; } @@ -8910,23 +9127,23 @@ CypherParser::OC_RelationshipPatternContext* CypherParser::oC_RelationshipPatter default: break; } - setState(1481); + setState(1502); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::T__5) { - setState(1480); + setState(1501); oC_RelationshipDetail(); } - setState(1484); + setState(1505); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1483); + setState(1504); match(CypherParser::SP); } - setState(1486); + setState(1507); oC_Dash(); break; } @@ -8983,7 +9200,7 @@ size_t CypherParser::OC_RelationshipDetailContext::getRuleIndex() const { CypherParser::OC_RelationshipDetailContext* CypherParser::oC_RelationshipDetail() { OC_RelationshipDetailContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 158, CypherParser::RuleOC_RelationshipDetail); + enterRule(_localctx, 164, CypherParser::RuleOC_RelationshipDetail); size_t _la = 0; #if __cplusplus > 201703L @@ -8995,83 +9212,83 @@ CypherParser::OC_RelationshipDetailContext* CypherParser::oC_RelationshipDetail( }); try { enterOuterAlt(_localctx, 1); - setState(1490); + setState(1511); match(CypherParser::T__5); - setState(1492); + setState(1513); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1491); + setState(1512); match(CypherParser::SP); } - setState(1498); + setState(1519); _errHandler->sync(this); _la = _input->LA(1); - if (((((_la - 47) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 47)) & 17826753) != 0) || ((((_la - 118) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 118)) & 302256385) != 0)) { - setState(1494); + if (((((_la - 49) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 49)) & 17826753) != 0) || ((((_la - 120) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 120)) & 302256385) != 0)) { + setState(1515); oC_Variable(); - setState(1496); + setState(1517); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1495); + setState(1516); match(CypherParser::SP); } } - setState(1504); + setState(1525); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::COLON) { - setState(1500); + setState(1521); oC_RelationshipTypes(); - setState(1502); + setState(1523); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1501); + setState(1522); match(CypherParser::SP); } } - setState(1510); + setState(1531); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::STAR) { - setState(1506); + setState(1527); oC_RangeLiteral(); - setState(1508); + setState(1529); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1507); + setState(1528); match(CypherParser::SP); } } - setState(1516); + setState(1537); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::T__7) { - setState(1512); + setState(1533); kU_Properties(); - setState(1514); + setState(1535); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1513); + setState(1534); match(CypherParser::SP); } } - setState(1518); + setState(1539); match(CypherParser::T__6); } @@ -9130,7 +9347,7 @@ size_t CypherParser::KU_PropertiesContext::getRuleIndex() const { CypherParser::KU_PropertiesContext* CypherParser::kU_Properties() { KU_PropertiesContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 160, CypherParser::RuleKU_Properties); + enterRule(_localctx, 166, CypherParser::RuleKU_Properties); size_t _la = 0; #if __cplusplus > 201703L @@ -9142,103 +9359,103 @@ CypherParser::KU_PropertiesContext* CypherParser::kU_Properties() { }); try { enterOuterAlt(_localctx, 1); - setState(1520); + setState(1541); match(CypherParser::T__7); - setState(1522); + setState(1543); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1521); + setState(1542); match(CypherParser::SP); } - setState(1557); + setState(1578); _errHandler->sync(this); _la = _input->LA(1); - if (((((_la - 47) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 47)) & 17826753) != 0) || ((((_la - 118) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 118)) & 302256385) != 0)) { - setState(1524); + if (((((_la - 49) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 49)) & 17826753) != 0) || ((((_la - 120) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 120)) & 302256385) != 0)) { + setState(1545); oC_PropertyKeyName(); - setState(1526); + setState(1547); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1525); + setState(1546); match(CypherParser::SP); } - setState(1528); + setState(1549); match(CypherParser::COLON); - setState(1530); + setState(1551); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1529); + setState(1550); match(CypherParser::SP); } - setState(1532); + setState(1553); oC_Expression(); - setState(1534); + setState(1555); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1533); + setState(1554); match(CypherParser::SP); } - setState(1554); + setState(1575); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3) { - setState(1536); - match(CypherParser::T__3); - setState(1538); + while (_la == CypherParser::T__2) { + setState(1557); + match(CypherParser::T__2); + setState(1559); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1537); + setState(1558); match(CypherParser::SP); } - setState(1540); + setState(1561); oC_PropertyKeyName(); - setState(1542); + setState(1563); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1541); + setState(1562); match(CypherParser::SP); } - setState(1544); + setState(1565); match(CypherParser::COLON); - setState(1546); + setState(1567); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1545); + setState(1566); match(CypherParser::SP); } - setState(1548); + setState(1569); oC_Expression(); - setState(1550); + setState(1571); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1549); + setState(1570); match(CypherParser::SP); } - setState(1556); + setState(1577); _errHandler->sync(this); _la = _input->LA(1); } } - setState(1559); + setState(1580); match(CypherParser::T__8); } @@ -9289,7 +9506,7 @@ size_t CypherParser::OC_RelationshipTypesContext::getRuleIndex() const { CypherParser::OC_RelationshipTypesContext* CypherParser::oC_RelationshipTypes() { OC_RelationshipTypesContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 162, CypherParser::RuleOC_RelationshipTypes); + enterRule(_localctx, 168, CypherParser::RuleOC_RelationshipTypes); size_t _la = 0; #if __cplusplus > 201703L @@ -9302,53 +9519,53 @@ CypherParser::OC_RelationshipTypesContext* CypherParser::oC_RelationshipTypes() try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1561); + setState(1582); match(CypherParser::COLON); - setState(1563); + setState(1584); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1562); + setState(1583); match(CypherParser::SP); } - setState(1565); + setState(1586); oC_RelTypeName(); - setState(1579); + setState(1600); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 251, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1567); + setState(1588); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1566); + setState(1587); match(CypherParser::SP); } - setState(1569); + setState(1590); match(CypherParser::T__9); - setState(1571); + setState(1592); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::COLON) { - setState(1570); + setState(1591); match(CypherParser::COLON); } - setState(1574); + setState(1595); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1573); + setState(1594); match(CypherParser::SP); } - setState(1576); + setState(1597); oC_RelTypeName(); } - setState(1581); + setState(1602); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 251, _ctx); } @@ -9393,7 +9610,7 @@ size_t CypherParser::OC_NodeLabelsContext::getRuleIndex() const { CypherParser::OC_NodeLabelsContext* CypherParser::oC_NodeLabels() { OC_NodeLabelsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 164, CypherParser::RuleOC_NodeLabels); + enterRule(_localctx, 170, CypherParser::RuleOC_NodeLabels); size_t _la = 0; #if __cplusplus > 201703L @@ -9406,25 +9623,25 @@ CypherParser::OC_NodeLabelsContext* CypherParser::oC_NodeLabels() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1582); + setState(1603); oC_NodeLabel(); - setState(1589); + setState(1610); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 253, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1584); + setState(1605); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1583); + setState(1604); match(CypherParser::SP); } - setState(1586); + setState(1607); oC_NodeLabel(); } - setState(1591); + setState(1612); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 253, _ctx); } @@ -9465,7 +9682,7 @@ size_t CypherParser::OC_NodeLabelContext::getRuleIndex() const { CypherParser::OC_NodeLabelContext* CypherParser::oC_NodeLabel() { OC_NodeLabelContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 166, CypherParser::RuleOC_NodeLabel); + enterRule(_localctx, 172, CypherParser::RuleOC_NodeLabel); size_t _la = 0; #if __cplusplus > 201703L @@ -9477,17 +9694,17 @@ CypherParser::OC_NodeLabelContext* CypherParser::oC_NodeLabel() { }); try { enterOuterAlt(_localctx, 1); - setState(1592); + setState(1613); match(CypherParser::COLON); - setState(1594); + setState(1615); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1593); + setState(1614); match(CypherParser::SP); } - setState(1596); + setState(1617); oC_LabelName(); } @@ -9550,7 +9767,7 @@ size_t CypherParser::OC_RangeLiteralContext::getRuleIndex() const { CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { OC_RangeLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 168, CypherParser::RuleOC_RangeLiteral); + enterRule(_localctx, 174, CypherParser::RuleOC_RangeLiteral); size_t _la = 0; #if __cplusplus > 201703L @@ -9562,14 +9779,14 @@ CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(1598); + setState(1619); match(CypherParser::STAR); - setState(1600); + setState(1621); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 255, _ctx)) { case 1: { - setState(1599); + setState(1620); match(CypherParser::SP); break; } @@ -9577,21 +9794,21 @@ CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { default: break; } - setState(1606); + setState(1627); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::SHORTEST: { - setState(1602); + setState(1623); match(CypherParser::SHORTEST); break; } case CypherParser::ALL: { - setState(1603); + setState(1624); match(CypherParser::ALL); - setState(1604); + setState(1625); match(CypherParser::SP); - setState(1605); + setState(1626); match(CypherParser::SHORTEST); break; } @@ -9608,12 +9825,12 @@ CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { default: break; } - setState(1609); + setState(1630); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 257, _ctx)) { case 1: { - setState(1608); + setState(1629); match(CypherParser::SP); break; } @@ -9621,35 +9838,35 @@ CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { default: break; } - setState(1625); + setState(1646); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 262, _ctx)) { case 1: { - setState(1612); + setState(1633); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::DecimalInteger) { - setState(1611); + setState(1632); oC_LowerBound(); } - setState(1615); + setState(1636); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1614); + setState(1635); match(CypherParser::SP); } - setState(1617); + setState(1638); match(CypherParser::T__10); - setState(1619); + setState(1640); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 260, _ctx)) { case 1: { - setState(1618); + setState(1639); match(CypherParser::SP); break; } @@ -9657,19 +9874,19 @@ CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { default: break; } - setState(1622); + setState(1643); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::DecimalInteger) { - setState(1621); + setState(1642); oC_UpperBound(); } break; } case 2: { - setState(1624); + setState(1645); oC_IntegerLiteral(); break; } @@ -9677,20 +9894,20 @@ CypherParser::OC_RangeLiteralContext* CypherParser::oC_RangeLiteral() { default: break; } - setState(1631); + setState(1652); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 264, _ctx)) { case 1: { - setState(1628); + setState(1649); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1627); + setState(1648); match(CypherParser::SP); } - setState(1630); + setState(1651); kU_RecursiveRelationshipComprehension(); break; } @@ -9751,7 +9968,7 @@ size_t CypherParser::KU_RecursiveRelationshipComprehensionContext::getRuleIndex( CypherParser::KU_RecursiveRelationshipComprehensionContext* CypherParser::kU_RecursiveRelationshipComprehension() { KU_RecursiveRelationshipComprehensionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 170, CypherParser::RuleKU_RecursiveRelationshipComprehension); + enterRule(_localctx, 176, CypherParser::RuleKU_RecursiveRelationshipComprehension); size_t _la = 0; #if __cplusplus > 201703L @@ -9763,62 +9980,62 @@ CypherParser::KU_RecursiveRelationshipComprehensionContext* CypherParser::kU_Rec }); try { enterOuterAlt(_localctx, 1); - setState(1633); + setState(1654); match(CypherParser::T__1); - setState(1635); + setState(1656); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1634); + setState(1655); match(CypherParser::SP); } - setState(1637); + setState(1658); oC_Variable(); - setState(1639); + setState(1660); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1638); + setState(1659); match(CypherParser::SP); } - setState(1641); - match(CypherParser::T__3); - setState(1643); + setState(1662); + match(CypherParser::T__2); + setState(1664); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1642); + setState(1663); match(CypherParser::SP); } - setState(1645); + setState(1666); oC_Variable(); - setState(1654); + setState(1675); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 270, _ctx)) { case 1: { - setState(1647); + setState(1668); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1646); + setState(1667); match(CypherParser::SP); } - setState(1649); + setState(1670); match(CypherParser::T__9); - setState(1651); + setState(1672); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1650); + setState(1671); match(CypherParser::SP); } - setState(1653); + setState(1674); oC_Where(); break; } @@ -9826,62 +10043,62 @@ CypherParser::KU_RecursiveRelationshipComprehensionContext* CypherParser::kU_Rec default: break; } - setState(1675); + setState(1696); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::T__9 || _la == CypherParser::SP) { - setState(1657); + setState(1678); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1656); + setState(1677); match(CypherParser::SP); } - setState(1659); + setState(1680); match(CypherParser::T__9); - setState(1661); + setState(1682); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1660); + setState(1681); match(CypherParser::SP); } - setState(1663); + setState(1684); kU_IntermediateRelProjectionItems(); - setState(1665); + setState(1686); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1664); + setState(1685); match(CypherParser::SP); } - setState(1667); - match(CypherParser::T__3); - setState(1669); + setState(1688); + match(CypherParser::T__2); + setState(1690); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1668); + setState(1689); match(CypherParser::SP); } - setState(1671); + setState(1692); kU_IntermediateNodeProjectionItems(); - setState(1673); + setState(1694); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1672); + setState(1693); match(CypherParser::SP); } } - setState(1677); - match(CypherParser::T__2); + setState(1698); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -9919,7 +10136,7 @@ size_t CypherParser::KU_IntermediateNodeProjectionItemsContext::getRuleIndex() c CypherParser::KU_IntermediateNodeProjectionItemsContext* CypherParser::kU_IntermediateNodeProjectionItems() { KU_IntermediateNodeProjectionItemsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 172, CypherParser::RuleKU_IntermediateNodeProjectionItems); + enterRule(_localctx, 178, CypherParser::RuleKU_IntermediateNodeProjectionItems); size_t _la = 0; #if __cplusplus > 201703L @@ -9931,14 +10148,14 @@ CypherParser::KU_IntermediateNodeProjectionItemsContext* CypherParser::kU_Interm }); try { enterOuterAlt(_localctx, 1); - setState(1679); + setState(1700); match(CypherParser::T__7); - setState(1681); + setState(1702); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 277, _ctx)) { case 1: { - setState(1680); + setState(1701); match(CypherParser::SP); break; } @@ -9946,26 +10163,26 @@ CypherParser::KU_IntermediateNodeProjectionItemsContext* CypherParser::kU_Interm default: break; } - setState(1684); + setState(1705); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139966783258607) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(1683); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139966783258607) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(1704); oC_ProjectionItems(); } - setState(1687); + setState(1708); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1686); + setState(1707); match(CypherParser::SP); } - setState(1689); + setState(1710); match(CypherParser::T__8); } @@ -10004,7 +10221,7 @@ size_t CypherParser::KU_IntermediateRelProjectionItemsContext::getRuleIndex() co CypherParser::KU_IntermediateRelProjectionItemsContext* CypherParser::kU_IntermediateRelProjectionItems() { KU_IntermediateRelProjectionItemsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 174, CypherParser::RuleKU_IntermediateRelProjectionItems); + enterRule(_localctx, 180, CypherParser::RuleKU_IntermediateRelProjectionItems); size_t _la = 0; #if __cplusplus > 201703L @@ -10016,14 +10233,14 @@ CypherParser::KU_IntermediateRelProjectionItemsContext* CypherParser::kU_Interme }); try { enterOuterAlt(_localctx, 1); - setState(1691); + setState(1712); match(CypherParser::T__7); - setState(1693); + setState(1714); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 280, _ctx)) { case 1: { - setState(1692); + setState(1713); match(CypherParser::SP); break; } @@ -10031,26 +10248,26 @@ CypherParser::KU_IntermediateRelProjectionItemsContext* CypherParser::kU_Interme default: break; } - setState(1696); + setState(1717); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139966783258607) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(1695); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139966783258607) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(1716); oC_ProjectionItems(); } - setState(1699); + setState(1720); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1698); + setState(1719); match(CypherParser::SP); } - setState(1701); + setState(1722); match(CypherParser::T__8); } @@ -10081,7 +10298,7 @@ size_t CypherParser::OC_LowerBoundContext::getRuleIndex() const { CypherParser::OC_LowerBoundContext* CypherParser::oC_LowerBound() { OC_LowerBoundContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 176, CypherParser::RuleOC_LowerBound); + enterRule(_localctx, 182, CypherParser::RuleOC_LowerBound); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10092,7 +10309,7 @@ CypherParser::OC_LowerBoundContext* CypherParser::oC_LowerBound() { }); try { enterOuterAlt(_localctx, 1); - setState(1703); + setState(1724); match(CypherParser::DecimalInteger); } @@ -10123,7 +10340,7 @@ size_t CypherParser::OC_UpperBoundContext::getRuleIndex() const { CypherParser::OC_UpperBoundContext* CypherParser::oC_UpperBound() { OC_UpperBoundContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 178, CypherParser::RuleOC_UpperBound); + enterRule(_localctx, 184, CypherParser::RuleOC_UpperBound); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10134,7 +10351,7 @@ CypherParser::OC_UpperBoundContext* CypherParser::oC_UpperBound() { }); try { enterOuterAlt(_localctx, 1); - setState(1705); + setState(1726); match(CypherParser::DecimalInteger); } @@ -10165,7 +10382,7 @@ size_t CypherParser::OC_LabelNameContext::getRuleIndex() const { CypherParser::OC_LabelNameContext* CypherParser::oC_LabelName() { OC_LabelNameContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 180, CypherParser::RuleOC_LabelName); + enterRule(_localctx, 186, CypherParser::RuleOC_LabelName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10176,7 +10393,7 @@ CypherParser::OC_LabelNameContext* CypherParser::oC_LabelName() { }); try { enterOuterAlt(_localctx, 1); - setState(1707); + setState(1728); oC_SchemaName(); } @@ -10207,7 +10424,7 @@ size_t CypherParser::OC_RelTypeNameContext::getRuleIndex() const { CypherParser::OC_RelTypeNameContext* CypherParser::oC_RelTypeName() { OC_RelTypeNameContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 182, CypherParser::RuleOC_RelTypeName); + enterRule(_localctx, 188, CypherParser::RuleOC_RelTypeName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10218,7 +10435,7 @@ CypherParser::OC_RelTypeNameContext* CypherParser::oC_RelTypeName() { }); try { enterOuterAlt(_localctx, 1); - setState(1709); + setState(1730); oC_SchemaName(); } @@ -10249,7 +10466,7 @@ size_t CypherParser::OC_ExpressionContext::getRuleIndex() const { CypherParser::OC_ExpressionContext* CypherParser::oC_Expression() { OC_ExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 184, CypherParser::RuleOC_Expression); + enterRule(_localctx, 190, CypherParser::RuleOC_Expression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10260,7 +10477,7 @@ CypherParser::OC_ExpressionContext* CypherParser::oC_Expression() { }); try { enterOuterAlt(_localctx, 1); - setState(1711); + setState(1732); oC_OrExpression(); } @@ -10311,7 +10528,7 @@ size_t CypherParser::OC_OrExpressionContext::getRuleIndex() const { CypherParser::OC_OrExpressionContext* CypherParser::oC_OrExpression() { OC_OrExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 186, CypherParser::RuleOC_OrExpression); + enterRule(_localctx, 192, CypherParser::RuleOC_OrExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10323,23 +10540,23 @@ CypherParser::OC_OrExpressionContext* CypherParser::oC_OrExpression() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1713); + setState(1734); oC_XorExpression(); - setState(1720); + setState(1741); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 283, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1714); + setState(1735); match(CypherParser::SP); - setState(1715); + setState(1736); match(CypherParser::OR); - setState(1716); + setState(1737); match(CypherParser::SP); - setState(1717); + setState(1738); oC_XorExpression(); } - setState(1722); + setState(1743); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 283, _ctx); } @@ -10392,7 +10609,7 @@ size_t CypherParser::OC_XorExpressionContext::getRuleIndex() const { CypherParser::OC_XorExpressionContext* CypherParser::oC_XorExpression() { OC_XorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 188, CypherParser::RuleOC_XorExpression); + enterRule(_localctx, 194, CypherParser::RuleOC_XorExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10404,23 +10621,23 @@ CypherParser::OC_XorExpressionContext* CypherParser::oC_XorExpression() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1723); + setState(1744); oC_AndExpression(); - setState(1730); + setState(1751); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 284, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1724); + setState(1745); match(CypherParser::SP); - setState(1725); + setState(1746); match(CypherParser::XOR); - setState(1726); + setState(1747); match(CypherParser::SP); - setState(1727); + setState(1748); oC_AndExpression(); } - setState(1732); + setState(1753); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 284, _ctx); } @@ -10473,7 +10690,7 @@ size_t CypherParser::OC_AndExpressionContext::getRuleIndex() const { CypherParser::OC_AndExpressionContext* CypherParser::oC_AndExpression() { OC_AndExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 190, CypherParser::RuleOC_AndExpression); + enterRule(_localctx, 196, CypherParser::RuleOC_AndExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -10485,23 +10702,23 @@ CypherParser::OC_AndExpressionContext* CypherParser::oC_AndExpression() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1733); + setState(1754); oC_NotExpression(); - setState(1740); + setState(1761); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 285, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1734); + setState(1755); match(CypherParser::SP); - setState(1735); + setState(1756); match(CypherParser::AND); - setState(1736); + setState(1757); match(CypherParser::SP); - setState(1737); + setState(1758); oC_NotExpression(); } - setState(1742); + setState(1763); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 285, _ctx); } @@ -10550,7 +10767,7 @@ size_t CypherParser::OC_NotExpressionContext::getRuleIndex() const { CypherParser::OC_NotExpressionContext* CypherParser::oC_NotExpression() { OC_NotExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 192, CypherParser::RuleOC_NotExpression); + enterRule(_localctx, 198, CypherParser::RuleOC_NotExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -10562,25 +10779,25 @@ CypherParser::OC_NotExpressionContext* CypherParser::oC_NotExpression() { }); try { enterOuterAlt(_localctx, 1); - setState(1749); + setState(1770); _errHandler->sync(this); _la = _input->LA(1); while (_la == CypherParser::NOT) { - setState(1743); + setState(1764); match(CypherParser::NOT); - setState(1745); + setState(1766); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1744); + setState(1765); match(CypherParser::SP); } - setState(1751); + setState(1772); _errHandler->sync(this); _la = _input->LA(1); } - setState(1752); + setState(1773); oC_ComparisonExpression(); } @@ -10635,7 +10852,7 @@ size_t CypherParser::OC_ComparisonExpressionContext::getRuleIndex() const { CypherParser::OC_ComparisonExpressionContext* CypherParser::oC_ComparisonExpression() { OC_ComparisonExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 194, CypherParser::RuleOC_ComparisonExpression); + enterRule(_localctx, 200, CypherParser::RuleOC_ComparisonExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -10647,37 +10864,37 @@ CypherParser::OC_ComparisonExpressionContext* CypherParser::oC_ComparisonExpress }); try { size_t alt; - setState(1802); + setState(1823); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 298, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1754); + setState(1775); kU_BitwiseOrOperatorExpression(); - setState(1764); + setState(1785); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 290, _ctx)) { case 1: { - setState(1756); + setState(1777); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1755); + setState(1776); match(CypherParser::SP); } - setState(1758); + setState(1779); kU_ComparisonOperator(); - setState(1760); + setState(1781); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1759); + setState(1780); match(CypherParser::SP); } - setState(1762); + setState(1783); kU_BitwiseOrOperatorExpression(); break; } @@ -10690,28 +10907,28 @@ CypherParser::OC_ComparisonExpressionContext* CypherParser::oC_ComparisonExpress case 2: { enterOuterAlt(_localctx, 2); - setState(1766); + setState(1787); kU_BitwiseOrOperatorExpression(); - setState(1768); + setState(1789); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1767); + setState(1788); match(CypherParser::SP); } - setState(1770); + setState(1791); antlrcpp::downCast(_localctx)->invalid_not_equalToken = match(CypherParser::INVALID_NOT_EQUAL); - setState(1772); + setState(1793); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1771); + setState(1792); match(CypherParser::SP); } - setState(1774); + setState(1795); kU_BitwiseOrOperatorExpression(); notifyInvalidNotEqualOperator(antlrcpp::downCast(_localctx)->invalid_not_equalToken); break; @@ -10719,53 +10936,53 @@ CypherParser::OC_ComparisonExpressionContext* CypherParser::oC_ComparisonExpress case 3: { enterOuterAlt(_localctx, 3); - setState(1778); + setState(1799); kU_BitwiseOrOperatorExpression(); - setState(1780); + setState(1801); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1779); + setState(1800); match(CypherParser::SP); } - setState(1782); + setState(1803); kU_ComparisonOperator(); - setState(1784); + setState(1805); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1783); + setState(1804); match(CypherParser::SP); } - setState(1786); + setState(1807); kU_BitwiseOrOperatorExpression(); - setState(1796); + setState(1817); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(1788); + setState(1809); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1787); + setState(1808); match(CypherParser::SP); } - setState(1790); + setState(1811); kU_ComparisonOperator(); - setState(1792); + setState(1813); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1791); + setState(1812); match(CypherParser::SP); } - setState(1794); + setState(1815); kU_BitwiseOrOperatorExpression(); break; } @@ -10773,7 +10990,7 @@ CypherParser::OC_ComparisonExpressionContext* CypherParser::oC_ComparisonExpress default: throw NoViableAltException(this); } - setState(1798); + setState(1819); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 297, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); @@ -10809,7 +11026,7 @@ size_t CypherParser::KU_ComparisonOperatorContext::getRuleIndex() const { CypherParser::KU_ComparisonOperatorContext* CypherParser::kU_ComparisonOperator() { KU_ComparisonOperatorContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 196, CypherParser::RuleKU_ComparisonOperator); + enterRule(_localctx, 202, CypherParser::RuleKU_ComparisonOperator); size_t _la = 0; #if __cplusplus > 201703L @@ -10821,7 +11038,7 @@ CypherParser::KU_ComparisonOperatorContext* CypherParser::kU_ComparisonOperator( }); try { enterOuterAlt(_localctx, 1); - setState(1804); + setState(1825); _la = _input->LA(1); if (!((((_la & ~ 0x3fULL) == 0) && ((1ULL << _la) & 127008) != 0))) { @@ -10872,7 +11089,7 @@ size_t CypherParser::KU_BitwiseOrOperatorExpressionContext::getRuleIndex() const CypherParser::KU_BitwiseOrOperatorExpressionContext* CypherParser::kU_BitwiseOrOperatorExpression() { KU_BitwiseOrOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 198, CypherParser::RuleKU_BitwiseOrOperatorExpression); + enterRule(_localctx, 204, CypherParser::RuleKU_BitwiseOrOperatorExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -10885,35 +11102,35 @@ CypherParser::KU_BitwiseOrOperatorExpressionContext* CypherParser::kU_BitwiseOrO try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1806); + setState(1827); kU_BitwiseAndOperatorExpression(); - setState(1817); + setState(1838); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 301, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1808); + setState(1829); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1807); + setState(1828); match(CypherParser::SP); } - setState(1810); + setState(1831); match(CypherParser::T__9); - setState(1812); + setState(1833); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1811); + setState(1832); match(CypherParser::SP); } - setState(1814); + setState(1835); kU_BitwiseAndOperatorExpression(); } - setState(1819); + setState(1840); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 301, _ctx); } @@ -10958,7 +11175,7 @@ size_t CypherParser::KU_BitwiseAndOperatorExpressionContext::getRuleIndex() cons CypherParser::KU_BitwiseAndOperatorExpressionContext* CypherParser::kU_BitwiseAndOperatorExpression() { KU_BitwiseAndOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 200, CypherParser::RuleKU_BitwiseAndOperatorExpression); + enterRule(_localctx, 206, CypherParser::RuleKU_BitwiseAndOperatorExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -10971,35 +11188,35 @@ CypherParser::KU_BitwiseAndOperatorExpressionContext* CypherParser::kU_BitwiseAn try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1820); + setState(1841); kU_BitShiftOperatorExpression(); - setState(1831); + setState(1852); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 304, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1822); + setState(1843); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1821); + setState(1842); match(CypherParser::SP); } - setState(1824); + setState(1845); match(CypherParser::T__16); - setState(1826); + setState(1847); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1825); + setState(1846); match(CypherParser::SP); } - setState(1828); + setState(1849); kU_BitShiftOperatorExpression(); } - setState(1833); + setState(1854); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 304, _ctx); } @@ -11052,7 +11269,7 @@ size_t CypherParser::KU_BitShiftOperatorExpressionContext::getRuleIndex() const CypherParser::KU_BitShiftOperatorExpressionContext* CypherParser::kU_BitShiftOperatorExpression() { KU_BitShiftOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 202, CypherParser::RuleKU_BitShiftOperatorExpression); + enterRule(_localctx, 208, CypherParser::RuleKU_BitShiftOperatorExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11065,35 +11282,35 @@ CypherParser::KU_BitShiftOperatorExpressionContext* CypherParser::kU_BitShiftOpe try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1834); + setState(1855); oC_AddOrSubtractExpression(); - setState(1846); + setState(1867); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 307, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1836); + setState(1857); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1835); + setState(1856); match(CypherParser::SP); } - setState(1838); + setState(1859); kU_BitShiftOperator(); - setState(1840); + setState(1861); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1839); + setState(1860); match(CypherParser::SP); } - setState(1842); + setState(1863); oC_AddOrSubtractExpression(); } - setState(1848); + setState(1869); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 307, _ctx); } @@ -11122,7 +11339,7 @@ size_t CypherParser::KU_BitShiftOperatorContext::getRuleIndex() const { CypherParser::KU_BitShiftOperatorContext* CypherParser::kU_BitShiftOperator() { KU_BitShiftOperatorContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 204, CypherParser::RuleKU_BitShiftOperator); + enterRule(_localctx, 210, CypherParser::RuleKU_BitShiftOperator); size_t _la = 0; #if __cplusplus > 201703L @@ -11134,7 +11351,7 @@ CypherParser::KU_BitShiftOperatorContext* CypherParser::kU_BitShiftOperator() { }); try { enterOuterAlt(_localctx, 1); - setState(1849); + setState(1870); _la = _input->LA(1); if (!(_la == CypherParser::T__17 @@ -11194,7 +11411,7 @@ size_t CypherParser::OC_AddOrSubtractExpressionContext::getRuleIndex() const { CypherParser::OC_AddOrSubtractExpressionContext* CypherParser::oC_AddOrSubtractExpression() { OC_AddOrSubtractExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 206, CypherParser::RuleOC_AddOrSubtractExpression); + enterRule(_localctx, 212, CypherParser::RuleOC_AddOrSubtractExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11207,35 +11424,35 @@ CypherParser::OC_AddOrSubtractExpressionContext* CypherParser::oC_AddOrSubtractE try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1851); + setState(1872); oC_MultiplyDivideModuloExpression(); - setState(1863); + setState(1884); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 310, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1853); + setState(1874); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1852); + setState(1873); match(CypherParser::SP); } - setState(1855); + setState(1876); kU_AddOrSubtractOperator(); - setState(1857); + setState(1878); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1856); + setState(1877); match(CypherParser::SP); } - setState(1859); + setState(1880); oC_MultiplyDivideModuloExpression(); } - setState(1865); + setState(1886); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 310, _ctx); } @@ -11268,7 +11485,7 @@ size_t CypherParser::KU_AddOrSubtractOperatorContext::getRuleIndex() const { CypherParser::KU_AddOrSubtractOperatorContext* CypherParser::kU_AddOrSubtractOperator() { KU_AddOrSubtractOperatorContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 208, CypherParser::RuleKU_AddOrSubtractOperator); + enterRule(_localctx, 214, CypherParser::RuleKU_AddOrSubtractOperator); size_t _la = 0; #if __cplusplus > 201703L @@ -11280,7 +11497,7 @@ CypherParser::KU_AddOrSubtractOperatorContext* CypherParser::kU_AddOrSubtractOpe }); try { enterOuterAlt(_localctx, 1); - setState(1866); + setState(1887); _la = _input->LA(1); if (!(_la == CypherParser::T__19 || _la == CypherParser::MINUS)) { _errHandler->recoverInline(this); @@ -11338,7 +11555,7 @@ size_t CypherParser::OC_MultiplyDivideModuloExpressionContext::getRuleIndex() co CypherParser::OC_MultiplyDivideModuloExpressionContext* CypherParser::oC_MultiplyDivideModuloExpression() { OC_MultiplyDivideModuloExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 210, CypherParser::RuleOC_MultiplyDivideModuloExpression); + enterRule(_localctx, 216, CypherParser::RuleOC_MultiplyDivideModuloExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11351,35 +11568,35 @@ CypherParser::OC_MultiplyDivideModuloExpressionContext* CypherParser::oC_Multipl try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1868); + setState(1889); oC_PowerOfExpression(); - setState(1880); + setState(1901); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 313, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1870); + setState(1891); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1869); + setState(1890); match(CypherParser::SP); } - setState(1872); + setState(1893); kU_MultiplyDivideModuloOperator(); - setState(1874); + setState(1895); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1873); + setState(1894); match(CypherParser::SP); } - setState(1876); + setState(1897); oC_PowerOfExpression(); } - setState(1882); + setState(1903); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 313, _ctx); } @@ -11412,7 +11629,7 @@ size_t CypherParser::KU_MultiplyDivideModuloOperatorContext::getRuleIndex() cons CypherParser::KU_MultiplyDivideModuloOperatorContext* CypherParser::kU_MultiplyDivideModuloOperator() { KU_MultiplyDivideModuloOperatorContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 212, CypherParser::RuleKU_MultiplyDivideModuloOperator); + enterRule(_localctx, 218, CypherParser::RuleKU_MultiplyDivideModuloOperator); size_t _la = 0; #if __cplusplus > 201703L @@ -11424,7 +11641,7 @@ CypherParser::KU_MultiplyDivideModuloOperatorContext* CypherParser::kU_MultiplyD }); try { enterOuterAlt(_localctx, 1); - setState(1883); + setState(1904); _la = _input->LA(1); if (!(_la == CypherParser::T__20 @@ -11476,7 +11693,7 @@ size_t CypherParser::OC_PowerOfExpressionContext::getRuleIndex() const { CypherParser::OC_PowerOfExpressionContext* CypherParser::oC_PowerOfExpression() { OC_PowerOfExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 214, CypherParser::RuleOC_PowerOfExpression); + enterRule(_localctx, 220, CypherParser::RuleOC_PowerOfExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11489,35 +11706,35 @@ CypherParser::OC_PowerOfExpressionContext* CypherParser::oC_PowerOfExpression() try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1885); + setState(1906); oC_UnaryAddSubtractOrFactorialExpression(); - setState(1896); + setState(1917); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 316, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1887); + setState(1908); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1886); + setState(1907); match(CypherParser::SP); } - setState(1889); + setState(1910); match(CypherParser::T__22); - setState(1891); + setState(1912); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1890); + setState(1911); match(CypherParser::SP); } - setState(1893); + setState(1914); oC_UnaryAddSubtractOrFactorialExpression(); } - setState(1898); + setState(1919); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 316, _ctx); } @@ -11570,7 +11787,7 @@ size_t CypherParser::OC_UnaryAddSubtractOrFactorialExpressionContext::getRuleInd CypherParser::OC_UnaryAddSubtractOrFactorialExpressionContext* CypherParser::oC_UnaryAddSubtractOrFactorialExpression() { OC_UnaryAddSubtractOrFactorialExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 216, CypherParser::RuleOC_UnaryAddSubtractOrFactorialExpression); + enterRule(_localctx, 222, CypherParser::RuleOC_UnaryAddSubtractOrFactorialExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11582,40 +11799,40 @@ CypherParser::OC_UnaryAddSubtractOrFactorialExpressionContext* CypherParser::oC_ }); try { enterOuterAlt(_localctx, 1); - setState(1905); + setState(1926); _errHandler->sync(this); _la = _input->LA(1); while (_la == CypherParser::MINUS) { - setState(1899); + setState(1920); match(CypherParser::MINUS); - setState(1901); + setState(1922); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1900); + setState(1921); match(CypherParser::SP); } - setState(1907); + setState(1928); _errHandler->sync(this); _la = _input->LA(1); } - setState(1908); + setState(1929); oC_StringListNullOperatorExpression(); - setState(1913); + setState(1934); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 320, _ctx)) { case 1: { - setState(1910); + setState(1931); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1909); + setState(1930); match(CypherParser::SP); } - setState(1912); + setState(1933); match(CypherParser::FACTORIAL); break; } @@ -11668,7 +11885,7 @@ size_t CypherParser::OC_StringListNullOperatorExpressionContext::getRuleIndex() CypherParser::OC_StringListNullOperatorExpressionContext* CypherParser::oC_StringListNullOperatorExpression() { OC_StringListNullOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 218, CypherParser::RuleOC_StringListNullOperatorExpression); + enterRule(_localctx, 224, CypherParser::RuleOC_StringListNullOperatorExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -11680,26 +11897,26 @@ CypherParser::OC_StringListNullOperatorExpressionContext* CypherParser::oC_Strin try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1915); + setState(1936); oC_PropertyOrLabelsExpression(); - setState(1923); + setState(1944); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 322, _ctx)) { case 1: { - setState(1916); + setState(1937); oC_StringOperatorExpression(); break; } case 2: { - setState(1918); + setState(1939); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(1917); + setState(1938); oC_ListOperatorExpression(); break; } @@ -11707,7 +11924,7 @@ CypherParser::OC_StringListNullOperatorExpressionContext* CypherParser::oC_Strin default: throw NoViableAltException(this); } - setState(1920); + setState(1941); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 321, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); @@ -11715,7 +11932,7 @@ CypherParser::OC_StringListNullOperatorExpressionContext* CypherParser::oC_Strin } case 3: { - setState(1922); + setState(1943); oC_NullOperatorExpression(); break; } @@ -11776,7 +11993,7 @@ size_t CypherParser::OC_ListOperatorExpressionContext::getRuleIndex() const { CypherParser::OC_ListOperatorExpressionContext* CypherParser::oC_ListOperatorExpression() { OC_ListOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 220, CypherParser::RuleOC_ListOperatorExpression); + enterRule(_localctx, 226, CypherParser::RuleOC_ListOperatorExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11787,68 +12004,68 @@ CypherParser::OC_ListOperatorExpressionContext* CypherParser::oC_ListOperatorExp exitRule(); }); try { - setState(1944); + setState(1965); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 326, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1925); + setState(1946); match(CypherParser::SP); - setState(1926); + setState(1947); match(CypherParser::IN); - setState(1928); + setState(1949); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1927); + setState(1948); match(CypherParser::SP); } - setState(1930); + setState(1951); oC_PropertyOrLabelsExpression(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1931); + setState(1952); match(CypherParser::T__5); - setState(1932); + setState(1953); oC_Expression(); - setState(1933); + setState(1954); match(CypherParser::T__6); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(1935); + setState(1956); match(CypherParser::T__5); - setState(1937); + setState(1958); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139968930742255) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(1936); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139968930742255) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(1957); oC_Expression(); } - setState(1939); + setState(1960); match(CypherParser::COLON); - setState(1941); + setState(1962); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139968930742255) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(1940); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139968930742255) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(1961); oC_Expression(); } - setState(1943); + setState(1964); match(CypherParser::T__6); break; } @@ -11913,7 +12130,7 @@ size_t CypherParser::OC_StringOperatorExpressionContext::getRuleIndex() const { CypherParser::OC_StringOperatorExpressionContext* CypherParser::oC_StringOperatorExpression() { OC_StringOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 222, CypherParser::RuleOC_StringOperatorExpression); + enterRule(_localctx, 228, CypherParser::RuleOC_StringOperatorExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -11925,43 +12142,43 @@ CypherParser::OC_StringOperatorExpressionContext* CypherParser::oC_StringOperato }); try { enterOuterAlt(_localctx, 1); - setState(1957); + setState(1978); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 327, _ctx)) { case 1: { - setState(1946); + setState(1967); oC_RegularExpression(); break; } case 2: { - setState(1947); + setState(1968); match(CypherParser::SP); - setState(1948); + setState(1969); match(CypherParser::STARTS); - setState(1949); + setState(1970); match(CypherParser::SP); - setState(1950); + setState(1971); match(CypherParser::WITH); break; } case 3: { - setState(1951); + setState(1972); match(CypherParser::SP); - setState(1952); + setState(1973); match(CypherParser::ENDS); - setState(1953); + setState(1974); match(CypherParser::SP); - setState(1954); + setState(1975); match(CypherParser::WITH); break; } case 4: { - setState(1955); + setState(1976); match(CypherParser::SP); - setState(1956); + setState(1977); match(CypherParser::CONTAINS); break; } @@ -11969,15 +12186,15 @@ CypherParser::OC_StringOperatorExpressionContext* CypherParser::oC_StringOperato default: break; } - setState(1960); + setState(1981); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1959); + setState(1980); match(CypherParser::SP); } - setState(1962); + setState(1983); oC_PropertyOrLabelsExpression(); } @@ -12008,7 +12225,7 @@ size_t CypherParser::OC_RegularExpressionContext::getRuleIndex() const { CypherParser::OC_RegularExpressionContext* CypherParser::oC_RegularExpression() { OC_RegularExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 224, CypherParser::RuleOC_RegularExpression); + enterRule(_localctx, 230, CypherParser::RuleOC_RegularExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -12020,15 +12237,15 @@ CypherParser::OC_RegularExpressionContext* CypherParser::oC_RegularExpression() }); try { enterOuterAlt(_localctx, 1); - setState(1965); + setState(1986); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1964); + setState(1985); match(CypherParser::SP); } - setState(1967); + setState(1988); match(CypherParser::T__23); } @@ -12075,7 +12292,7 @@ size_t CypherParser::OC_NullOperatorExpressionContext::getRuleIndex() const { CypherParser::OC_NullOperatorExpressionContext* CypherParser::oC_NullOperatorExpression() { OC_NullOperatorExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 226, CypherParser::RuleOC_NullOperatorExpression); + enterRule(_localctx, 232, CypherParser::RuleOC_NullOperatorExpression); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -12085,35 +12302,35 @@ CypherParser::OC_NullOperatorExpressionContext* CypherParser::oC_NullOperatorExp exitRule(); }); try { - setState(1979); + setState(2000); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 330, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1969); + setState(1990); match(CypherParser::SP); - setState(1970); + setState(1991); match(CypherParser::IS); - setState(1971); + setState(1992); match(CypherParser::SP); - setState(1972); + setState(1993); match(CypherParser::NULL_); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1973); + setState(1994); match(CypherParser::SP); - setState(1974); + setState(1995); match(CypherParser::IS); - setState(1975); + setState(1996); match(CypherParser::SP); - setState(1976); + setState(1997); match(CypherParser::NOT); - setState(1977); + setState(1998); match(CypherParser::SP); - setState(1978); + setState(1999); match(CypherParser::NULL_); break; } @@ -12166,7 +12383,7 @@ size_t CypherParser::OC_PropertyOrLabelsExpressionContext::getRuleIndex() const CypherParser::OC_PropertyOrLabelsExpressionContext* CypherParser::oC_PropertyOrLabelsExpression() { OC_PropertyOrLabelsExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 228, CypherParser::RuleOC_PropertyOrLabelsExpression); + enterRule(_localctx, 234, CypherParser::RuleOC_PropertyOrLabelsExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -12179,25 +12396,25 @@ CypherParser::OC_PropertyOrLabelsExpressionContext* CypherParser::oC_PropertyOrL try { size_t alt; enterOuterAlt(_localctx, 1); - setState(1981); + setState(2002); oC_Atom(); - setState(1988); + setState(2009); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 332, _ctx); while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) { if (alt == 1) { - setState(1983); + setState(2004); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(1982); + setState(2003); match(CypherParser::SP); } - setState(1985); + setState(2006); oC_PropertyLookup(); } - setState(1990); + setState(2011); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 332, _ctx); } @@ -12262,7 +12479,7 @@ size_t CypherParser::OC_AtomContext::getRuleIndex() const { CypherParser::OC_AtomContext* CypherParser::oC_Atom() { OC_AtomContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 230, CypherParser::RuleOC_Atom); + enterRule(_localctx, 236, CypherParser::RuleOC_Atom); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -12272,68 +12489,68 @@ CypherParser::OC_AtomContext* CypherParser::oC_Atom() { exitRule(); }); try { - setState(2000); + setState(2021); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 333, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(1991); + setState(2012); oC_Literal(); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(1992); + setState(2013); oC_Parameter(); break; } case 3: { enterOuterAlt(_localctx, 3); - setState(1993); + setState(2014); oC_CaseExpression(); break; } case 4: { enterOuterAlt(_localctx, 4); - setState(1994); + setState(2015); oC_ParenthesizedExpression(); break; } case 5: { enterOuterAlt(_localctx, 5); - setState(1995); + setState(2016); oC_FunctionInvocation(); break; } case 6: { enterOuterAlt(_localctx, 6); - setState(1996); + setState(2017); oC_PathPatterns(); break; } case 7: { enterOuterAlt(_localctx, 7); - setState(1997); + setState(2018); oC_ExistSubquery(); break; } case 8: { enterOuterAlt(_localctx, 8); - setState(1998); + setState(2019); kU_CountSubquery(); break; } case 9: { enterOuterAlt(_localctx, 9); - setState(1999); + setState(2020); oC_Variable(); break; } @@ -12390,7 +12607,7 @@ size_t CypherParser::OC_LiteralContext::getRuleIndex() const { CypherParser::OC_LiteralContext* CypherParser::oC_Literal() { OC_LiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 232, CypherParser::RuleOC_Literal); + enterRule(_localctx, 238, CypherParser::RuleOC_Literal); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -12400,20 +12617,20 @@ CypherParser::OC_LiteralContext* CypherParser::oC_Literal() { exitRule(); }); try { - setState(2008); + setState(2029); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::DecimalInteger: case CypherParser::RegularDecimalReal: { enterOuterAlt(_localctx, 1); - setState(2002); + setState(2023); oC_NumberLiteral(); break; } case CypherParser::StringLiteral: { enterOuterAlt(_localctx, 2); - setState(2003); + setState(2024); match(CypherParser::StringLiteral); break; } @@ -12421,28 +12638,28 @@ CypherParser::OC_LiteralContext* CypherParser::oC_Literal() { case CypherParser::TRUE: case CypherParser::FALSE: { enterOuterAlt(_localctx, 3); - setState(2004); + setState(2025); oC_BooleanLiteral(); break; } case CypherParser::NULL_: { enterOuterAlt(_localctx, 4); - setState(2005); + setState(2026); match(CypherParser::NULL_); break; } case CypherParser::T__5: { enterOuterAlt(_localctx, 5); - setState(2006); + setState(2027); oC_ListLiteral(); break; } case CypherParser::T__7: { enterOuterAlt(_localctx, 6); - setState(2007); + setState(2028); kU_StructLiteral(); break; } @@ -12483,7 +12700,7 @@ size_t CypherParser::OC_BooleanLiteralContext::getRuleIndex() const { CypherParser::OC_BooleanLiteralContext* CypherParser::oC_BooleanLiteral() { OC_BooleanLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 234, CypherParser::RuleOC_BooleanLiteral); + enterRule(_localctx, 240, CypherParser::RuleOC_BooleanLiteral); size_t _la = 0; #if __cplusplus > 201703L @@ -12495,7 +12712,7 @@ CypherParser::OC_BooleanLiteralContext* CypherParser::oC_BooleanLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(2010); + setState(2031); _la = _input->LA(1); if (!(_la == CypherParser::TRUE @@ -12551,7 +12768,7 @@ size_t CypherParser::OC_ListLiteralContext::getRuleIndex() const { CypherParser::OC_ListLiteralContext* CypherParser::oC_ListLiteral() { OC_ListLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 236, CypherParser::RuleOC_ListLiteral); + enterRule(_localctx, 242, CypherParser::RuleOC_ListLiteral); size_t _la = 0; #if __cplusplus > 201703L @@ -12563,54 +12780,54 @@ CypherParser::OC_ListLiteralContext* CypherParser::oC_ListLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(2012); + setState(2033); match(CypherParser::T__5); - setState(2014); + setState(2035); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2013); + setState(2034); match(CypherParser::SP); } - setState(2029); + setState(2050); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139968930742255) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(2016); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139968930742255) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(2037); oC_Expression(); - setState(2018); + setState(2039); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2017); + setState(2038); match(CypherParser::SP); } - setState(2026); + setState(2047); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3) { - setState(2020); + while (_la == CypherParser::T__2) { + setState(2041); kU_ListEntry(); - setState(2022); + setState(2043); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2021); + setState(2042); match(CypherParser::SP); } - setState(2028); + setState(2049); _errHandler->sync(this); _la = _input->LA(1); } } - setState(2031); + setState(2052); match(CypherParser::T__6); } @@ -12645,7 +12862,7 @@ size_t CypherParser::KU_ListEntryContext::getRuleIndex() const { CypherParser::KU_ListEntryContext* CypherParser::kU_ListEntry() { KU_ListEntryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 238, CypherParser::RuleKU_ListEntry); + enterRule(_localctx, 244, CypherParser::RuleKU_ListEntry); size_t _la = 0; #if __cplusplus > 201703L @@ -12657,14 +12874,14 @@ CypherParser::KU_ListEntryContext* CypherParser::kU_ListEntry() { }); try { enterOuterAlt(_localctx, 1); - setState(2033); - match(CypherParser::T__3); - setState(2035); + setState(2054); + match(CypherParser::T__2); + setState(2056); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 340, _ctx)) { case 1: { - setState(2034); + setState(2055); match(CypherParser::SP); break; } @@ -12672,15 +12889,15 @@ CypherParser::KU_ListEntryContext* CypherParser::kU_ListEntry() { default: break; } - setState(2038); + setState(2059); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139968930742255) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(2037); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139968930742255) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(2058); oC_Expression(); } @@ -12724,7 +12941,7 @@ size_t CypherParser::KU_StructLiteralContext::getRuleIndex() const { CypherParser::KU_StructLiteralContext* CypherParser::kU_StructLiteral() { KU_StructLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 240, CypherParser::RuleKU_StructLiteral); + enterRule(_localctx, 246, CypherParser::RuleKU_StructLiteral); size_t _la = 0; #if __cplusplus > 201703L @@ -12736,55 +12953,55 @@ CypherParser::KU_StructLiteralContext* CypherParser::kU_StructLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(2040); + setState(2061); match(CypherParser::T__7); - setState(2042); + setState(2063); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2041); + setState(2062); match(CypherParser::SP); } - setState(2044); + setState(2065); kU_StructField(); - setState(2046); + setState(2067); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2045); + setState(2066); match(CypherParser::SP); } - setState(2058); + setState(2079); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3) { - setState(2048); - match(CypherParser::T__3); - setState(2050); + while (_la == CypherParser::T__2) { + setState(2069); + match(CypherParser::T__2); + setState(2071); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2049); + setState(2070); match(CypherParser::SP); } - setState(2052); + setState(2073); kU_StructField(); - setState(2054); + setState(2075); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2053); + setState(2074); match(CypherParser::SP); } - setState(2060); + setState(2081); _errHandler->sync(this); _la = _input->LA(1); } - setState(2061); + setState(2082); match(CypherParser::T__8); } @@ -12835,7 +13052,7 @@ size_t CypherParser::KU_StructFieldContext::getRuleIndex() const { CypherParser::KU_StructFieldContext* CypherParser::kU_StructField() { KU_StructFieldContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 242, CypherParser::RuleKU_StructField); + enterRule(_localctx, 248, CypherParser::RuleKU_StructField); size_t _la = 0; #if __cplusplus > 201703L @@ -12847,10 +13064,10 @@ CypherParser::KU_StructFieldContext* CypherParser::kU_StructField() { }); try { enterOuterAlt(_localctx, 1); - setState(2065); + setState(2086); _errHandler->sync(this); switch (_input->LA(1)) { - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -12863,13 +13080,13 @@ CypherParser::KU_StructFieldContext* CypherParser::kU_StructField() { case CypherParser::HexLetter: case CypherParser::UnescapedSymbolicName: case CypherParser::EscapedSymbolicName: { - setState(2063); + setState(2084); oC_SymbolicName(); break; } case CypherParser::StringLiteral: { - setState(2064); + setState(2085); match(CypherParser::StringLiteral); break; } @@ -12877,25 +13094,25 @@ CypherParser::KU_StructFieldContext* CypherParser::kU_StructField() { default: throw NoViableAltException(this); } - setState(2068); + setState(2089); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2067); + setState(2088); match(CypherParser::SP); } - setState(2070); + setState(2091); match(CypherParser::COLON); - setState(2072); + setState(2093); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2071); + setState(2092); match(CypherParser::SP); } - setState(2074); + setState(2095); oC_Expression(); } @@ -12934,7 +13151,7 @@ size_t CypherParser::OC_ParenthesizedExpressionContext::getRuleIndex() const { CypherParser::OC_ParenthesizedExpressionContext* CypherParser::oC_ParenthesizedExpression() { OC_ParenthesizedExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 244, CypherParser::RuleOC_ParenthesizedExpression); + enterRule(_localctx, 250, CypherParser::RuleOC_ParenthesizedExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -12946,28 +13163,28 @@ CypherParser::OC_ParenthesizedExpressionContext* CypherParser::oC_ParenthesizedE }); try { enterOuterAlt(_localctx, 1); - setState(2076); + setState(2097); match(CypherParser::T__1); - setState(2078); + setState(2099); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2077); + setState(2098); match(CypherParser::SP); } - setState(2080); + setState(2101); oC_Expression(); - setState(2082); + setState(2103); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2081); + setState(2102); match(CypherParser::SP); } - setState(2084); - match(CypherParser::T__2); + setState(2105); + match(CypherParser::T__3); } catch (RecognitionException &e) { @@ -13025,7 +13242,7 @@ size_t CypherParser::OC_FunctionInvocationContext::getRuleIndex() const { CypherParser::OC_FunctionInvocationContext* CypherParser::oC_FunctionInvocation() { OC_FunctionInvocationContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 246, CypherParser::RuleOC_FunctionInvocation); + enterRule(_localctx, 252, CypherParser::RuleOC_FunctionInvocation); size_t _la = 0; #if __cplusplus > 201703L @@ -13036,133 +13253,133 @@ CypherParser::OC_FunctionInvocationContext* CypherParser::oC_FunctionInvocation( exitRule(); }); try { - setState(2134); + setState(2155); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 364, _ctx)) { case 1: { enterOuterAlt(_localctx, 1); - setState(2086); + setState(2107); match(CypherParser::COUNT); - setState(2088); + setState(2109); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2087); + setState(2108); match(CypherParser::SP); } - setState(2090); + setState(2111); match(CypherParser::T__1); - setState(2092); + setState(2113); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2091); + setState(2112); match(CypherParser::SP); } - setState(2094); + setState(2115); match(CypherParser::STAR); - setState(2096); + setState(2117); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2095); + setState(2116); match(CypherParser::SP); } - setState(2098); - match(CypherParser::T__2); + setState(2119); + match(CypherParser::T__3); break; } case 2: { enterOuterAlt(_localctx, 2); - setState(2099); + setState(2120); oC_FunctionName(); - setState(2101); + setState(2122); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2100); + setState(2121); match(CypherParser::SP); } - setState(2103); + setState(2124); match(CypherParser::T__1); - setState(2105); + setState(2126); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2104); + setState(2125); match(CypherParser::SP); } - setState(2111); + setState(2132); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::DISTINCT) { - setState(2107); + setState(2128); match(CypherParser::DISTINCT); - setState(2109); + setState(2130); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2108); + setState(2129); match(CypherParser::SP); } } - setState(2130); + setState(2151); _errHandler->sync(this); _la = _input->LA(1); if ((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726376579396) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -4681139968930742255) != 0) || ((((_la - 133) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 133)) & 9741) != 0)) { - setState(2113); + ((1ULL << _la) & 540994905304990020) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -4681139968930742255) != 0) || ((((_la - 135) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 135)) & 9741) != 0)) { + setState(2134); kU_FunctionParameter(); - setState(2115); + setState(2136); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2114); + setState(2135); match(CypherParser::SP); } - setState(2127); + setState(2148); _errHandler->sync(this); _la = _input->LA(1); - while (_la == CypherParser::T__3) { - setState(2117); - match(CypherParser::T__3); - setState(2119); + while (_la == CypherParser::T__2) { + setState(2138); + match(CypherParser::T__2); + setState(2140); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2118); + setState(2139); match(CypherParser::SP); } - setState(2121); + setState(2142); kU_FunctionParameter(); - setState(2123); + setState(2144); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2122); + setState(2143); match(CypherParser::SP); } - setState(2129); + setState(2150); _errHandler->sync(this); _la = _input->LA(1); } } - setState(2132); - match(CypherParser::T__2); + setState(2153); + match(CypherParser::T__3); break; } @@ -13198,7 +13415,7 @@ size_t CypherParser::OC_FunctionNameContext::getRuleIndex() const { CypherParser::OC_FunctionNameContext* CypherParser::oC_FunctionName() { OC_FunctionNameContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 248, CypherParser::RuleOC_FunctionName); + enterRule(_localctx, 254, CypherParser::RuleOC_FunctionName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -13209,7 +13426,7 @@ CypherParser::OC_FunctionNameContext* CypherParser::oC_FunctionName() { }); try { enterOuterAlt(_localctx, 1); - setState(2136); + setState(2157); oC_SymbolicName(); } @@ -13256,7 +13473,7 @@ size_t CypherParser::KU_FunctionParameterContext::getRuleIndex() const { CypherParser::KU_FunctionParameterContext* CypherParser::kU_FunctionParameter() { KU_FunctionParameterContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 250, CypherParser::RuleKU_FunctionParameter); + enterRule(_localctx, 256, CypherParser::RuleKU_FunctionParameter); size_t _la = 0; #if __cplusplus > 201703L @@ -13268,31 +13485,31 @@ CypherParser::KU_FunctionParameterContext* CypherParser::kU_FunctionParameter() }); try { enterOuterAlt(_localctx, 1); - setState(2147); + setState(2168); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 367, _ctx)) { case 1: { - setState(2138); + setState(2159); oC_SymbolicName(); - setState(2140); + setState(2161); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2139); + setState(2160); match(CypherParser::SP); } - setState(2142); + setState(2163); match(CypherParser::COLON); - setState(2143); + setState(2164); match(CypherParser::T__4); - setState(2145); + setState(2166); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2144); + setState(2165); match(CypherParser::SP); } break; @@ -13301,7 +13518,7 @@ CypherParser::KU_FunctionParameterContext* CypherParser::kU_FunctionParameter() default: break; } - setState(2149); + setState(2170); oC_Expression(); } @@ -13348,7 +13565,7 @@ size_t CypherParser::OC_PathPatternsContext::getRuleIndex() const { CypherParser::OC_PathPatternsContext* CypherParser::oC_PathPatterns() { OC_PathPatternsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 252, CypherParser::RuleOC_PathPatterns); + enterRule(_localctx, 258, CypherParser::RuleOC_PathPatterns); size_t _la = 0; #if __cplusplus > 201703L @@ -13361,23 +13578,23 @@ CypherParser::OC_PathPatternsContext* CypherParser::oC_PathPatterns() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(2151); + setState(2172); oC_NodePattern(); - setState(2156); + setState(2177); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(2153); + setState(2174); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2152); + setState(2173); match(CypherParser::SP); } - setState(2155); + setState(2176); oC_PatternElementChain(); break; } @@ -13385,7 +13602,7 @@ CypherParser::OC_PathPatternsContext* CypherParser::oC_PathPatterns() { default: throw NoViableAltException(this); } - setState(2158); + setState(2179); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 369, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); @@ -13438,7 +13655,7 @@ size_t CypherParser::OC_ExistSubqueryContext::getRuleIndex() const { CypherParser::OC_ExistSubqueryContext* CypherParser::oC_ExistSubquery() { OC_ExistSubqueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 254, CypherParser::RuleOC_ExistSubquery); + enterRule(_localctx, 260, CypherParser::RuleOC_ExistSubquery); size_t _la = 0; #if __cplusplus > 201703L @@ -13450,52 +13667,52 @@ CypherParser::OC_ExistSubqueryContext* CypherParser::oC_ExistSubquery() { }); try { enterOuterAlt(_localctx, 1); - setState(2160); + setState(2181); match(CypherParser::EXISTS); - setState(2162); + setState(2183); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2161); + setState(2182); match(CypherParser::SP); } - setState(2164); + setState(2185); match(CypherParser::T__7); - setState(2166); + setState(2187); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2165); + setState(2186); match(CypherParser::SP); } - setState(2168); + setState(2189); match(CypherParser::MATCH); - setState(2170); + setState(2191); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2169); + setState(2190); match(CypherParser::SP); } - setState(2172); + setState(2193); oC_Pattern(); - setState(2177); + setState(2198); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 374, _ctx)) { case 1: { - setState(2174); + setState(2195); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2173); + setState(2194); match(CypherParser::SP); } - setState(2176); + setState(2197); oC_Where(); break; } @@ -13503,15 +13720,15 @@ CypherParser::OC_ExistSubqueryContext* CypherParser::oC_ExistSubquery() { default: break; } - setState(2180); + setState(2201); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2179); + setState(2200); match(CypherParser::SP); } - setState(2182); + setState(2203); match(CypherParser::T__8); } @@ -13562,7 +13779,7 @@ size_t CypherParser::KU_CountSubqueryContext::getRuleIndex() const { CypherParser::KU_CountSubqueryContext* CypherParser::kU_CountSubquery() { KU_CountSubqueryContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 256, CypherParser::RuleKU_CountSubquery); + enterRule(_localctx, 262, CypherParser::RuleKU_CountSubquery); size_t _la = 0; #if __cplusplus > 201703L @@ -13574,52 +13791,52 @@ CypherParser::KU_CountSubqueryContext* CypherParser::kU_CountSubquery() { }); try { enterOuterAlt(_localctx, 1); - setState(2184); + setState(2205); match(CypherParser::COUNT); - setState(2186); + setState(2207); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2185); + setState(2206); match(CypherParser::SP); } - setState(2188); + setState(2209); match(CypherParser::T__7); - setState(2190); + setState(2211); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2189); + setState(2210); match(CypherParser::SP); } - setState(2192); + setState(2213); match(CypherParser::MATCH); - setState(2194); + setState(2215); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2193); + setState(2214); match(CypherParser::SP); } - setState(2196); + setState(2217); oC_Pattern(); - setState(2201); + setState(2222); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 380, _ctx)) { case 1: { - setState(2198); + setState(2219); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2197); + setState(2218); match(CypherParser::SP); } - setState(2200); + setState(2221); oC_Where(); break; } @@ -13627,15 +13844,15 @@ CypherParser::KU_CountSubqueryContext* CypherParser::kU_CountSubquery() { default: break; } - setState(2204); + setState(2225); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2203); + setState(2224); match(CypherParser::SP); } - setState(2206); + setState(2227); match(CypherParser::T__8); } @@ -13674,7 +13891,7 @@ size_t CypherParser::OC_PropertyLookupContext::getRuleIndex() const { CypherParser::OC_PropertyLookupContext* CypherParser::oC_PropertyLookup() { OC_PropertyLookupContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 258, CypherParser::RuleOC_PropertyLookup); + enterRule(_localctx, 264, CypherParser::RuleOC_PropertyLookup); size_t _la = 0; #if __cplusplus > 201703L @@ -13686,20 +13903,20 @@ CypherParser::OC_PropertyLookupContext* CypherParser::oC_PropertyLookup() { }); try { enterOuterAlt(_localctx, 1); - setState(2208); + setState(2229); match(CypherParser::T__24); - setState(2210); + setState(2231); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2209); + setState(2230); match(CypherParser::SP); } - setState(2214); + setState(2235); _errHandler->sync(this); switch (_input->LA(1)) { - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -13712,13 +13929,13 @@ CypherParser::OC_PropertyLookupContext* CypherParser::oC_PropertyLookup() { case CypherParser::HexLetter: case CypherParser::UnescapedSymbolicName: case CypherParser::EscapedSymbolicName: { - setState(2212); + setState(2233); oC_PropertyKeyName(); break; } case CypherParser::STAR: { - setState(2213); + setState(2234); match(CypherParser::STAR); break; } @@ -13787,7 +14004,7 @@ size_t CypherParser::OC_CaseExpressionContext::getRuleIndex() const { CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { OC_CaseExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 260, CypherParser::RuleOC_CaseExpression); + enterRule(_localctx, 266, CypherParser::RuleOC_CaseExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -13800,27 +14017,27 @@ CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { try { size_t alt; enterOuterAlt(_localctx, 1); - setState(2238); + setState(2259); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 389, _ctx)) { case 1: { - setState(2216); + setState(2237); match(CypherParser::CASE); - setState(2221); + setState(2242); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(2218); + setState(2239); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2217); + setState(2238); match(CypherParser::SP); } - setState(2220); + setState(2241); oC_CaseAlternative(); break; } @@ -13828,7 +14045,7 @@ CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { default: throw NoViableAltException(this); } - setState(2223); + setState(2244); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 385, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); @@ -13836,33 +14053,33 @@ CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { } case 2: { - setState(2225); + setState(2246); match(CypherParser::CASE); - setState(2227); + setState(2248); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2226); + setState(2247); match(CypherParser::SP); } - setState(2229); + setState(2250); oC_Expression(); - setState(2234); + setState(2255); _errHandler->sync(this); alt = 1; do { switch (alt) { case 1: { - setState(2231); + setState(2252); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2230); + setState(2251); match(CypherParser::SP); } - setState(2233); + setState(2254); oC_CaseAlternative(); break; } @@ -13870,7 +14087,7 @@ CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { default: throw NoViableAltException(this); } - setState(2236); + setState(2257); _errHandler->sync(this); alt = getInterpreter()->adaptivePredict(_input, 388, _ctx); } while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER); @@ -13880,30 +14097,30 @@ CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { default: break; } - setState(2248); + setState(2269); _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 392, _ctx)) { case 1: { - setState(2241); + setState(2262); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2240); + setState(2261); match(CypherParser::SP); } - setState(2243); + setState(2264); match(CypherParser::ELSE); - setState(2245); + setState(2266); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2244); + setState(2265); match(CypherParser::SP); } - setState(2247); + setState(2268); oC_Expression(); break; } @@ -13911,15 +14128,15 @@ CypherParser::OC_CaseExpressionContext* CypherParser::oC_CaseExpression() { default: break; } - setState(2251); + setState(2272); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2250); + setState(2271); match(CypherParser::SP); } - setState(2253); + setState(2274); match(CypherParser::END); } @@ -13970,7 +14187,7 @@ size_t CypherParser::OC_CaseAlternativeContext::getRuleIndex() const { CypherParser::OC_CaseAlternativeContext* CypherParser::oC_CaseAlternative() { OC_CaseAlternativeContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 262, CypherParser::RuleOC_CaseAlternative); + enterRule(_localctx, 268, CypherParser::RuleOC_CaseAlternative); size_t _la = 0; #if __cplusplus > 201703L @@ -13982,37 +14199,37 @@ CypherParser::OC_CaseAlternativeContext* CypherParser::oC_CaseAlternative() { }); try { enterOuterAlt(_localctx, 1); - setState(2255); + setState(2276); match(CypherParser::WHEN); - setState(2257); + setState(2278); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2256); + setState(2277); match(CypherParser::SP); } - setState(2259); + setState(2280); oC_Expression(); - setState(2261); + setState(2282); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2260); + setState(2281); match(CypherParser::SP); } - setState(2263); + setState(2284); match(CypherParser::THEN); - setState(2265); + setState(2286); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2264); + setState(2285); match(CypherParser::SP); } - setState(2267); + setState(2288); oC_Expression(); } @@ -14043,7 +14260,7 @@ size_t CypherParser::OC_VariableContext::getRuleIndex() const { CypherParser::OC_VariableContext* CypherParser::oC_Variable() { OC_VariableContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 264, CypherParser::RuleOC_Variable); + enterRule(_localctx, 270, CypherParser::RuleOC_Variable); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14054,7 +14271,7 @@ CypherParser::OC_VariableContext* CypherParser::oC_Variable() { }); try { enterOuterAlt(_localctx, 1); - setState(2269); + setState(2290); oC_SymbolicName(); } @@ -14089,7 +14306,7 @@ size_t CypherParser::OC_NumberLiteralContext::getRuleIndex() const { CypherParser::OC_NumberLiteralContext* CypherParser::oC_NumberLiteral() { OC_NumberLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 266, CypherParser::RuleOC_NumberLiteral); + enterRule(_localctx, 272, CypherParser::RuleOC_NumberLiteral); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14099,19 +14316,19 @@ CypherParser::OC_NumberLiteralContext* CypherParser::oC_NumberLiteral() { exitRule(); }); try { - setState(2273); + setState(2294); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::RegularDecimalReal: { enterOuterAlt(_localctx, 1); - setState(2271); + setState(2292); oC_DoubleLiteral(); break; } case CypherParser::DecimalInteger: { enterOuterAlt(_localctx, 2); - setState(2272); + setState(2293); oC_IntegerLiteral(); break; } @@ -14152,7 +14369,7 @@ size_t CypherParser::OC_ParameterContext::getRuleIndex() const { CypherParser::OC_ParameterContext* CypherParser::oC_Parameter() { OC_ParameterContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 268, CypherParser::RuleOC_Parameter); + enterRule(_localctx, 274, CypherParser::RuleOC_Parameter); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14163,12 +14380,12 @@ CypherParser::OC_ParameterContext* CypherParser::oC_Parameter() { }); try { enterOuterAlt(_localctx, 1); - setState(2275); + setState(2296); match(CypherParser::T__25); - setState(2278); + setState(2299); _errHandler->sync(this); switch (_input->LA(1)) { - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -14181,13 +14398,13 @@ CypherParser::OC_ParameterContext* CypherParser::oC_Parameter() { case CypherParser::HexLetter: case CypherParser::UnescapedSymbolicName: case CypherParser::EscapedSymbolicName: { - setState(2276); + setState(2297); oC_SymbolicName(); break; } case CypherParser::DecimalInteger: { - setState(2277); + setState(2298); match(CypherParser::DecimalInteger); break; } @@ -14232,7 +14449,7 @@ size_t CypherParser::OC_PropertyExpressionContext::getRuleIndex() const { CypherParser::OC_PropertyExpressionContext* CypherParser::oC_PropertyExpression() { OC_PropertyExpressionContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 270, CypherParser::RuleOC_PropertyExpression); + enterRule(_localctx, 276, CypherParser::RuleOC_PropertyExpression); size_t _la = 0; #if __cplusplus > 201703L @@ -14244,17 +14461,17 @@ CypherParser::OC_PropertyExpressionContext* CypherParser::oC_PropertyExpression( }); try { enterOuterAlt(_localctx, 1); - setState(2280); + setState(2301); oC_Atom(); - setState(2282); + setState(2303); _errHandler->sync(this); _la = _input->LA(1); if (_la == CypherParser::SP) { - setState(2281); + setState(2302); match(CypherParser::SP); } - setState(2284); + setState(2305); oC_PropertyLookup(); } @@ -14285,7 +14502,7 @@ size_t CypherParser::OC_PropertyKeyNameContext::getRuleIndex() const { CypherParser::OC_PropertyKeyNameContext* CypherParser::oC_PropertyKeyName() { OC_PropertyKeyNameContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 272, CypherParser::RuleOC_PropertyKeyName); + enterRule(_localctx, 278, CypherParser::RuleOC_PropertyKeyName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14296,7 +14513,7 @@ CypherParser::OC_PropertyKeyNameContext* CypherParser::oC_PropertyKeyName() { }); try { enterOuterAlt(_localctx, 1); - setState(2286); + setState(2307); oC_SchemaName(); } @@ -14327,7 +14544,7 @@ size_t CypherParser::OC_IntegerLiteralContext::getRuleIndex() const { CypherParser::OC_IntegerLiteralContext* CypherParser::oC_IntegerLiteral() { OC_IntegerLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 274, CypherParser::RuleOC_IntegerLiteral); + enterRule(_localctx, 280, CypherParser::RuleOC_IntegerLiteral); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14338,7 +14555,7 @@ CypherParser::OC_IntegerLiteralContext* CypherParser::oC_IntegerLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(2288); + setState(2309); match(CypherParser::DecimalInteger); } @@ -14369,7 +14586,7 @@ size_t CypherParser::OC_DoubleLiteralContext::getRuleIndex() const { CypherParser::OC_DoubleLiteralContext* CypherParser::oC_DoubleLiteral() { OC_DoubleLiteralContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 276, CypherParser::RuleOC_DoubleLiteral); + enterRule(_localctx, 282, CypherParser::RuleOC_DoubleLiteral); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14380,7 +14597,7 @@ CypherParser::OC_DoubleLiteralContext* CypherParser::oC_DoubleLiteral() { }); try { enterOuterAlt(_localctx, 1); - setState(2290); + setState(2311); match(CypherParser::RegularDecimalReal); } @@ -14411,7 +14628,7 @@ size_t CypherParser::OC_SchemaNameContext::getRuleIndex() const { CypherParser::OC_SchemaNameContext* CypherParser::oC_SchemaName() { OC_SchemaNameContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 278, CypherParser::RuleOC_SchemaName); + enterRule(_localctx, 284, CypherParser::RuleOC_SchemaName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14422,7 +14639,7 @@ CypherParser::OC_SchemaNameContext* CypherParser::oC_SchemaName() { }); try { enterOuterAlt(_localctx, 1); - setState(2292); + setState(2313); oC_SymbolicName(); } @@ -14465,7 +14682,7 @@ size_t CypherParser::OC_SymbolicNameContext::getRuleIndex() const { CypherParser::OC_SymbolicNameContext* CypherParser::oC_SymbolicName() { OC_SymbolicNameContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 280, CypherParser::RuleOC_SymbolicName); + enterRule(_localctx, 286, CypherParser::RuleOC_SymbolicName); #if __cplusplus > 201703L auto onExit = finally([=, this] { @@ -14475,19 +14692,19 @@ CypherParser::OC_SymbolicNameContext* CypherParser::oC_SymbolicName() { exitRule(); }); try { - setState(2299); + setState(2320); _errHandler->sync(this); switch (_input->LA(1)) { case CypherParser::UnescapedSymbolicName: { enterOuterAlt(_localctx, 1); - setState(2294); + setState(2315); match(CypherParser::UnescapedSymbolicName); break; } case CypherParser::EscapedSymbolicName: { enterOuterAlt(_localctx, 2); - setState(2295); + setState(2316); antlrcpp::downCast(_localctx)->escapedsymbolicnameToken = match(CypherParser::EscapedSymbolicName); if ((antlrcpp::downCast(_localctx)->escapedsymbolicnameToken != nullptr ? antlrcpp::downCast(_localctx)->escapedsymbolicnameToken->getText() : "") == "``") { notifyEmptyToken(antlrcpp::downCast(_localctx)->escapedsymbolicnameToken); } break; @@ -14495,12 +14712,12 @@ CypherParser::OC_SymbolicNameContext* CypherParser::oC_SymbolicName() { case CypherParser::HexLetter: { enterOuterAlt(_localctx, 3); - setState(2297); + setState(2318); match(CypherParser::HexLetter); break; } - case CypherParser::COMMENT: + case CypherParser::COMMENT_: case CypherParser::EXPORT: case CypherParser::IMPORT: case CypherParser::DATABASE: @@ -14511,7 +14728,7 @@ CypherParser::OC_SymbolicNameContext* CypherParser::oC_SymbolicName() { case CypherParser::COUNT: case CypherParser::END: { enterOuterAlt(_localctx, 4); - setState(2298); + setState(2319); kU_NonReservedKeywords(); break; } @@ -14536,8 +14753,8 @@ CypherParser::KU_NonReservedKeywordsContext::KU_NonReservedKeywordsContext(Parse : ParserRuleContext(parent, invokingState) { } -tree::TerminalNode* CypherParser::KU_NonReservedKeywordsContext::COMMENT() { - return getToken(CypherParser::COMMENT, 0); +tree::TerminalNode* CypherParser::KU_NonReservedKeywordsContext::COMMENT_() { + return getToken(CypherParser::COMMENT_, 0); } tree::TerminalNode* CypherParser::KU_NonReservedKeywordsContext::COUNT() { @@ -14584,7 +14801,7 @@ size_t CypherParser::KU_NonReservedKeywordsContext::getRuleIndex() const { CypherParser::KU_NonReservedKeywordsContext* CypherParser::kU_NonReservedKeywords() { KU_NonReservedKeywordsContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 282, CypherParser::RuleKU_NonReservedKeywords); + enterRule(_localctx, 288, CypherParser::RuleKU_NonReservedKeywords); size_t _la = 0; #if __cplusplus > 201703L @@ -14596,11 +14813,11 @@ CypherParser::KU_NonReservedKeywordsContext* CypherParser::kU_NonReservedKeyword }); try { enterOuterAlt(_localctx, 1); - setState(2301); + setState(2322); _la = _input->LA(1); if (!((((_la & ~ 0x3fULL) == 0) && - ((1ULL << _la) & 135248726309470208) != 0) || ((((_la - 67) & ~ 0x3fULL) == 0) && - ((1ULL << (_la - 67)) & -8644659484737667055) != 0))) { + ((1ULL << _la) & 540994905237880832) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) && + ((1ULL << (_la - 69)) & -8644659484737667055) != 0))) { _errHandler->recoverInline(this); } else { @@ -14632,7 +14849,7 @@ size_t CypherParser::OC_LeftArrowHeadContext::getRuleIndex() const { CypherParser::OC_LeftArrowHeadContext* CypherParser::oC_LeftArrowHead() { OC_LeftArrowHeadContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 284, CypherParser::RuleOC_LeftArrowHead); + enterRule(_localctx, 290, CypherParser::RuleOC_LeftArrowHead); size_t _la = 0; #if __cplusplus > 201703L @@ -14644,7 +14861,7 @@ CypherParser::OC_LeftArrowHeadContext* CypherParser::oC_LeftArrowHead() { }); try { enterOuterAlt(_localctx, 1); - setState(2303); + setState(2324); _la = _input->LA(1); if (!((((_la & ~ 0x3fULL) == 0) && ((1ULL << _la) & 2013274112) != 0))) { @@ -14679,7 +14896,7 @@ size_t CypherParser::OC_RightArrowHeadContext::getRuleIndex() const { CypherParser::OC_RightArrowHeadContext* CypherParser::oC_RightArrowHead() { OC_RightArrowHeadContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 286, CypherParser::RuleOC_RightArrowHead); + enterRule(_localctx, 292, CypherParser::RuleOC_RightArrowHead); size_t _la = 0; #if __cplusplus > 201703L @@ -14691,7 +14908,7 @@ CypherParser::OC_RightArrowHeadContext* CypherParser::oC_RightArrowHead() { }); try { enterOuterAlt(_localctx, 1); - setState(2305); + setState(2326); _la = _input->LA(1); if (!((((_la & ~ 0x3fULL) == 0) && ((1ULL << _la) & 32212287488) != 0))) { @@ -14730,7 +14947,7 @@ size_t CypherParser::OC_DashContext::getRuleIndex() const { CypherParser::OC_DashContext* CypherParser::oC_Dash() { OC_DashContext *_localctx = _tracker.createInstance(_ctx, getState()); - enterRule(_localctx, 288, CypherParser::RuleOC_Dash); + enterRule(_localctx, 294, CypherParser::RuleOC_Dash); size_t _la = 0; #if __cplusplus > 201703L @@ -14742,7 +14959,7 @@ CypherParser::OC_DashContext* CypherParser::oC_Dash() { }); try { enterOuterAlt(_localctx, 1); - setState(2307); + setState(2328); _la = _input->LA(1); if (!((((_la & ~ 0x3fULL) == 0) && ((1ULL << _la) & 70334384439296) != 0) || _la == CypherParser::MINUS)) { @@ -14765,7 +14982,7 @@ CypherParser::OC_DashContext* CypherParser::oC_Dash() { bool CypherParser::sempred(RuleContext *context, size_t ruleIndex, size_t predicateIndex) { switch (ruleIndex) { - case 33: return kU_DataTypeSempred(antlrcpp::downCast(context), predicateIndex); + case 36: return kU_DataTypeSempred(antlrcpp::downCast(context), predicateIndex); default: break; diff --git a/third_party/antlr4_cypher/include/cypher_lexer.h b/third_party/antlr4_cypher/include/cypher_lexer.h index ef7e9367f06..d34c0d3a312 100644 --- a/third_party/antlr4_cypher/include/cypher_lexer.h +++ b/third_party/antlr4_cypher/include/cypher_lexer.h @@ -19,26 +19,27 @@ class CypherLexer : public antlr4::Lexer { T__26 = 27, T__27 = 28, T__28 = 29, T__29 = 30, T__30 = 31, T__31 = 32, T__32 = 33, T__33 = 34, T__34 = 35, T__35 = 36, T__36 = 37, T__37 = 38, T__38 = 39, T__39 = 40, T__40 = 41, T__41 = 42, T__42 = 43, T__43 = 44, - T__44 = 45, CALL = 46, COMMENT = 47, MACRO = 48, GLOB = 49, COPY = 50, - FROM = 51, COLUMN = 52, EXPORT = 53, IMPORT = 54, DATABASE = 55, NODE = 56, - TABLE = 57, GROUP = 58, RDFGRAPH = 59, DROP = 60, ALTER = 61, DEFAULT = 62, - RENAME = 63, ADD = 64, PRIMARY = 65, KEY = 66, REL = 67, TO = 68, EXPLAIN = 69, - PROFILE = 70, BEGIN = 71, TRANSACTION = 72, READ = 73, ONLY = 74, WRITE = 75, - COMMIT = 76, COMMIT_SKIP_CHECKPOINT = 77, ROLLBACK = 78, ROLLBACK_SKIP_CHECKPOINT = 79, - INSTALL = 80, EXTENSION = 81, UNION = 82, ALL = 83, LOAD = 84, HEADERS = 85, - OPTIONAL = 86, MATCH = 87, UNWIND = 88, CREATE = 89, MERGE = 90, ON = 91, - SET = 92, DETACH = 93, DELETE = 94, WITH = 95, RETURN = 96, DISTINCT = 97, - STAR = 98, AS = 99, ORDER = 100, BY = 101, L_SKIP = 102, LIMIT = 103, - ASCENDING = 104, ASC = 105, DESCENDING = 106, DESC = 107, WHERE = 108, - SHORTEST = 109, OR = 110, XOR = 111, AND = 112, NOT = 113, INVALID_NOT_EQUAL = 114, - MINUS = 115, FACTORIAL = 116, COLON = 117, IN = 118, STARTS = 119, ENDS = 120, - CONTAINS = 121, IS = 122, NULL_ = 123, TRUE = 124, FALSE = 125, COUNT = 126, - EXISTS = 127, CASE = 128, ELSE = 129, END = 130, WHEN = 131, THEN = 132, - StringLiteral = 133, EscapedChar = 134, DecimalInteger = 135, HexLetter = 136, - HexDigit = 137, Digit = 138, NonZeroDigit = 139, NonZeroOctDigit = 140, - ZeroDigit = 141, RegularDecimalReal = 142, UnescapedSymbolicName = 143, - IdentifierStart = 144, IdentifierPart = 145, EscapedSymbolicName = 146, - SP = 147, WHITESPACE = 148, Comment = 149, Unknown = 150 + T__44 = 45, ATTACH = 46, DBTYPE = 47, CALL = 48, COMMENT_ = 49, MACRO = 50, + GLOB = 51, COPY = 52, FROM = 53, COLUMN = 54, EXPORT = 55, IMPORT = 56, + DATABASE = 57, NODE = 58, TABLE = 59, GROUP = 60, RDFGRAPH = 61, DROP = 62, + ALTER = 63, DEFAULT = 64, RENAME = 65, ADD = 66, PRIMARY = 67, KEY = 68, + REL = 69, TO = 70, EXPLAIN = 71, PROFILE = 72, BEGIN = 73, TRANSACTION = 74, + READ = 75, ONLY = 76, WRITE = 77, COMMIT = 78, COMMIT_SKIP_CHECKPOINT = 79, + ROLLBACK = 80, ROLLBACK_SKIP_CHECKPOINT = 81, INSTALL = 82, EXTENSION = 83, + UNION = 84, ALL = 85, LOAD = 86, HEADERS = 87, OPTIONAL = 88, MATCH = 89, + UNWIND = 90, CREATE = 91, MERGE = 92, ON = 93, SET = 94, DETACH = 95, + DELETE = 96, WITH = 97, RETURN = 98, DISTINCT = 99, STAR = 100, AS = 101, + ORDER = 102, BY = 103, L_SKIP = 104, LIMIT = 105, ASCENDING = 106, ASC = 107, + DESCENDING = 108, DESC = 109, WHERE = 110, SHORTEST = 111, OR = 112, + XOR = 113, AND = 114, NOT = 115, INVALID_NOT_EQUAL = 116, MINUS = 117, + FACTORIAL = 118, COLON = 119, IN = 120, STARTS = 121, ENDS = 122, CONTAINS = 123, + IS = 124, NULL_ = 125, TRUE = 126, FALSE = 127, COUNT = 128, EXISTS = 129, + CASE = 130, ELSE = 131, END = 132, WHEN = 133, THEN = 134, StringLiteral = 135, + EscapedChar = 136, DecimalInteger = 137, HexLetter = 138, HexDigit = 139, + Digit = 140, NonZeroDigit = 141, NonZeroOctDigit = 142, ZeroDigit = 143, + RegularDecimalReal = 144, UnescapedSymbolicName = 145, IdentifierStart = 146, + IdentifierPart = 147, EscapedSymbolicName = 148, SP = 149, WHITESPACE = 150, + Comment = 151, Unknown = 152 }; explicit CypherLexer(antlr4::CharStream *input); diff --git a/third_party/antlr4_cypher/include/cypher_parser.h b/third_party/antlr4_cypher/include/cypher_parser.h index 7b1e2a803ff..64ea634c38a 100644 --- a/third_party/antlr4_cypher/include/cypher_parser.h +++ b/third_party/antlr4_cypher/include/cypher_parser.h @@ -19,79 +19,81 @@ class CypherParser : public antlr4::Parser { T__26 = 27, T__27 = 28, T__28 = 29, T__29 = 30, T__30 = 31, T__31 = 32, T__32 = 33, T__33 = 34, T__34 = 35, T__35 = 36, T__36 = 37, T__37 = 38, T__38 = 39, T__39 = 40, T__40 = 41, T__41 = 42, T__42 = 43, T__43 = 44, - T__44 = 45, CALL = 46, COMMENT = 47, MACRO = 48, GLOB = 49, COPY = 50, - FROM = 51, COLUMN = 52, EXPORT = 53, IMPORT = 54, DATABASE = 55, NODE = 56, - TABLE = 57, GROUP = 58, RDFGRAPH = 59, DROP = 60, ALTER = 61, DEFAULT = 62, - RENAME = 63, ADD = 64, PRIMARY = 65, KEY = 66, REL = 67, TO = 68, EXPLAIN = 69, - PROFILE = 70, BEGIN = 71, TRANSACTION = 72, READ = 73, ONLY = 74, WRITE = 75, - COMMIT = 76, COMMIT_SKIP_CHECKPOINT = 77, ROLLBACK = 78, ROLLBACK_SKIP_CHECKPOINT = 79, - INSTALL = 80, EXTENSION = 81, UNION = 82, ALL = 83, LOAD = 84, HEADERS = 85, - OPTIONAL = 86, MATCH = 87, UNWIND = 88, CREATE = 89, MERGE = 90, ON = 91, - SET = 92, DETACH = 93, DELETE = 94, WITH = 95, RETURN = 96, DISTINCT = 97, - STAR = 98, AS = 99, ORDER = 100, BY = 101, L_SKIP = 102, LIMIT = 103, - ASCENDING = 104, ASC = 105, DESCENDING = 106, DESC = 107, WHERE = 108, - SHORTEST = 109, OR = 110, XOR = 111, AND = 112, NOT = 113, INVALID_NOT_EQUAL = 114, - MINUS = 115, FACTORIAL = 116, COLON = 117, IN = 118, STARTS = 119, ENDS = 120, - CONTAINS = 121, IS = 122, NULL_ = 123, TRUE = 124, FALSE = 125, COUNT = 126, - EXISTS = 127, CASE = 128, ELSE = 129, END = 130, WHEN = 131, THEN = 132, - StringLiteral = 133, EscapedChar = 134, DecimalInteger = 135, HexLetter = 136, - HexDigit = 137, Digit = 138, NonZeroDigit = 139, NonZeroOctDigit = 140, - ZeroDigit = 141, RegularDecimalReal = 142, UnescapedSymbolicName = 143, - IdentifierStart = 144, IdentifierPart = 145, EscapedSymbolicName = 146, - SP = 147, WHITESPACE = 148, Comment = 149, Unknown = 150 + T__44 = 45, ATTACH = 46, DBTYPE = 47, CALL = 48, COMMENT_ = 49, MACRO = 50, + GLOB = 51, COPY = 52, FROM = 53, COLUMN = 54, EXPORT = 55, IMPORT = 56, + DATABASE = 57, NODE = 58, TABLE = 59, GROUP = 60, RDFGRAPH = 61, DROP = 62, + ALTER = 63, DEFAULT = 64, RENAME = 65, ADD = 66, PRIMARY = 67, KEY = 68, + REL = 69, TO = 70, EXPLAIN = 71, PROFILE = 72, BEGIN = 73, TRANSACTION = 74, + READ = 75, ONLY = 76, WRITE = 77, COMMIT = 78, COMMIT_SKIP_CHECKPOINT = 79, + ROLLBACK = 80, ROLLBACK_SKIP_CHECKPOINT = 81, INSTALL = 82, EXTENSION = 83, + UNION = 84, ALL = 85, LOAD = 86, HEADERS = 87, OPTIONAL = 88, MATCH = 89, + UNWIND = 90, CREATE = 91, MERGE = 92, ON = 93, SET = 94, DETACH = 95, + DELETE = 96, WITH = 97, RETURN = 98, DISTINCT = 99, STAR = 100, AS = 101, + ORDER = 102, BY = 103, L_SKIP = 104, LIMIT = 105, ASCENDING = 106, ASC = 107, + DESCENDING = 108, DESC = 109, WHERE = 110, SHORTEST = 111, OR = 112, + XOR = 113, AND = 114, NOT = 115, INVALID_NOT_EQUAL = 116, MINUS = 117, + FACTORIAL = 118, COLON = 119, IN = 120, STARTS = 121, ENDS = 122, CONTAINS = 123, + IS = 124, NULL_ = 125, TRUE = 126, FALSE = 127, COUNT = 128, EXISTS = 129, + CASE = 130, ELSE = 131, END = 132, WHEN = 133, THEN = 134, StringLiteral = 135, + EscapedChar = 136, DecimalInteger = 137, HexLetter = 138, HexDigit = 139, + Digit = 140, NonZeroDigit = 141, NonZeroOctDigit = 142, ZeroDigit = 143, + RegularDecimalReal = 144, UnescapedSymbolicName = 145, IdentifierStart = 146, + IdentifierPart = 147, EscapedSymbolicName = 148, SP = 149, WHITESPACE = 150, + Comment = 151, Unknown = 152 }; enum { RuleKu_Statements = 0, RuleOC_Cypher = 1, RuleOC_Statement = 2, RuleKU_CopyFrom = 3, - RuleKU_ColumnNames = 4, RuleKU_CopyFromByColumn = 5, RuleKU_CopyTO = 6, - RuleKU_ExportDatabase = 7, RuleKU_ImportDatabase = 8, RuleKU_StandaloneCall = 9, - RuleKU_CommentOn = 10, RuleKU_CreateMacro = 11, RuleKU_PositionalArgs = 12, - RuleKU_DefaultArg = 13, RuleKU_FilePaths = 14, RuleKU_ParsingOptions = 15, - RuleKU_ParsingOption = 16, RuleKU_DDL = 17, RuleKU_CreateNodeTable = 18, - RuleKU_CreateRelTable = 19, RuleKU_CreateRelTableGroup = 20, RuleKU_RelTableConnection = 21, - RuleKU_CreateRdfGraph = 22, RuleKU_DropTable = 23, RuleKU_AlterTable = 24, - RuleKU_AlterOptions = 25, RuleKU_AddProperty = 26, RuleKU_DropProperty = 27, - RuleKU_RenameTable = 28, RuleKU_RenameProperty = 29, RuleKU_PropertyDefinitions = 30, - RuleKU_PropertyDefinition = 31, RuleKU_CreateNodeConstraint = 32, RuleKU_DataType = 33, - RuleKU_ListIdentifiers = 34, RuleKU_ListIdentifier = 35, RuleOC_AnyCypherOption = 36, - RuleOC_Explain = 37, RuleOC_Profile = 38, RuleKU_Transaction = 39, RuleKU_Extension = 40, - RuleKU_LoadExtension = 41, RuleKU_InstallExtension = 42, RuleOC_Query = 43, - RuleOC_RegularQuery = 44, RuleOC_Union = 45, RuleOC_SingleQuery = 46, - RuleOC_SinglePartQuery = 47, RuleOC_MultiPartQuery = 48, RuleKU_QueryPart = 49, - RuleOC_UpdatingClause = 50, RuleOC_ReadingClause = 51, RuleKU_LoadFrom = 52, - RuleKU_InQueryCall = 53, RuleOC_Match = 54, RuleOC_Unwind = 55, RuleOC_Create = 56, - RuleOC_Merge = 57, RuleOC_MergeAction = 58, RuleOC_Set = 59, RuleOC_SetItem = 60, - RuleOC_Delete = 61, RuleOC_With = 62, RuleOC_Return = 63, RuleOC_ProjectionBody = 64, - RuleOC_ProjectionItems = 65, RuleOC_ProjectionItem = 66, RuleOC_Order = 67, - RuleOC_Skip = 68, RuleOC_Limit = 69, RuleOC_SortItem = 70, RuleOC_Where = 71, - RuleOC_Pattern = 72, RuleOC_PatternPart = 73, RuleOC_AnonymousPatternPart = 74, - RuleOC_PatternElement = 75, RuleOC_NodePattern = 76, RuleOC_PatternElementChain = 77, - RuleOC_RelationshipPattern = 78, RuleOC_RelationshipDetail = 79, RuleKU_Properties = 80, - RuleOC_RelationshipTypes = 81, RuleOC_NodeLabels = 82, RuleOC_NodeLabel = 83, - RuleOC_RangeLiteral = 84, RuleKU_RecursiveRelationshipComprehension = 85, - RuleKU_IntermediateNodeProjectionItems = 86, RuleKU_IntermediateRelProjectionItems = 87, - RuleOC_LowerBound = 88, RuleOC_UpperBound = 89, RuleOC_LabelName = 90, - RuleOC_RelTypeName = 91, RuleOC_Expression = 92, RuleOC_OrExpression = 93, - RuleOC_XorExpression = 94, RuleOC_AndExpression = 95, RuleOC_NotExpression = 96, - RuleOC_ComparisonExpression = 97, RuleKU_ComparisonOperator = 98, RuleKU_BitwiseOrOperatorExpression = 99, - RuleKU_BitwiseAndOperatorExpression = 100, RuleKU_BitShiftOperatorExpression = 101, - RuleKU_BitShiftOperator = 102, RuleOC_AddOrSubtractExpression = 103, - RuleKU_AddOrSubtractOperator = 104, RuleOC_MultiplyDivideModuloExpression = 105, - RuleKU_MultiplyDivideModuloOperator = 106, RuleOC_PowerOfExpression = 107, - RuleOC_UnaryAddSubtractOrFactorialExpression = 108, RuleOC_StringListNullOperatorExpression = 109, - RuleOC_ListOperatorExpression = 110, RuleOC_StringOperatorExpression = 111, - RuleOC_RegularExpression = 112, RuleOC_NullOperatorExpression = 113, - RuleOC_PropertyOrLabelsExpression = 114, RuleOC_Atom = 115, RuleOC_Literal = 116, - RuleOC_BooleanLiteral = 117, RuleOC_ListLiteral = 118, RuleKU_ListEntry = 119, - RuleKU_StructLiteral = 120, RuleKU_StructField = 121, RuleOC_ParenthesizedExpression = 122, - RuleOC_FunctionInvocation = 123, RuleOC_FunctionName = 124, RuleKU_FunctionParameter = 125, - RuleOC_PathPatterns = 126, RuleOC_ExistSubquery = 127, RuleKU_CountSubquery = 128, - RuleOC_PropertyLookup = 129, RuleOC_CaseExpression = 130, RuleOC_CaseAlternative = 131, - RuleOC_Variable = 132, RuleOC_NumberLiteral = 133, RuleOC_Parameter = 134, - RuleOC_PropertyExpression = 135, RuleOC_PropertyKeyName = 136, RuleOC_IntegerLiteral = 137, - RuleOC_DoubleLiteral = 138, RuleOC_SchemaName = 139, RuleOC_SymbolicName = 140, - RuleKU_NonReservedKeywords = 141, RuleOC_LeftArrowHead = 142, RuleOC_RightArrowHead = 143, - RuleOC_Dash = 144 + RuleKU_ColumnNames = 4, RuleKU_ScanSource = 5, RuleKU_CopyFromByColumn = 6, + RuleKU_CopyTO = 7, RuleKU_ExportDatabase = 8, RuleKU_ImportDatabase = 9, + RuleKU_AttachDatabase = 10, RuleKU_DetachDatabase = 11, RuleKU_StandaloneCall = 12, + RuleKU_CommentOn = 13, RuleKU_CreateMacro = 14, RuleKU_PositionalArgs = 15, + RuleKU_DefaultArg = 16, RuleKU_FilePaths = 17, RuleKU_ParsingOptions = 18, + RuleKU_ParsingOption = 19, RuleKU_DDL = 20, RuleKU_CreateNodeTable = 21, + RuleKU_CreateRelTable = 22, RuleKU_CreateRelTableGroup = 23, RuleKU_RelTableConnection = 24, + RuleKU_CreateRdfGraph = 25, RuleKU_DropTable = 26, RuleKU_AlterTable = 27, + RuleKU_AlterOptions = 28, RuleKU_AddProperty = 29, RuleKU_DropProperty = 30, + RuleKU_RenameTable = 31, RuleKU_RenameProperty = 32, RuleKU_PropertyDefinitions = 33, + RuleKU_PropertyDefinition = 34, RuleKU_CreateNodeConstraint = 35, RuleKU_DataType = 36, + RuleKU_ListIdentifiers = 37, RuleKU_ListIdentifier = 38, RuleOC_AnyCypherOption = 39, + RuleOC_Explain = 40, RuleOC_Profile = 41, RuleKU_Transaction = 42, RuleKU_Extension = 43, + RuleKU_LoadExtension = 44, RuleKU_InstallExtension = 45, RuleOC_Query = 46, + RuleOC_RegularQuery = 47, RuleOC_Union = 48, RuleOC_SingleQuery = 49, + RuleOC_SinglePartQuery = 50, RuleOC_MultiPartQuery = 51, RuleKU_QueryPart = 52, + RuleOC_UpdatingClause = 53, RuleOC_ReadingClause = 54, RuleKU_LoadFrom = 55, + RuleKU_InQueryCall = 56, RuleOC_Match = 57, RuleOC_Unwind = 58, RuleOC_Create = 59, + RuleOC_Merge = 60, RuleOC_MergeAction = 61, RuleOC_Set = 62, RuleOC_SetItem = 63, + RuleOC_Delete = 64, RuleOC_With = 65, RuleOC_Return = 66, RuleOC_ProjectionBody = 67, + RuleOC_ProjectionItems = 68, RuleOC_ProjectionItem = 69, RuleOC_Order = 70, + RuleOC_Skip = 71, RuleOC_Limit = 72, RuleOC_SortItem = 73, RuleOC_Where = 74, + RuleOC_Pattern = 75, RuleOC_PatternPart = 76, RuleOC_AnonymousPatternPart = 77, + RuleOC_PatternElement = 78, RuleOC_NodePattern = 79, RuleOC_PatternElementChain = 80, + RuleOC_RelationshipPattern = 81, RuleOC_RelationshipDetail = 82, RuleKU_Properties = 83, + RuleOC_RelationshipTypes = 84, RuleOC_NodeLabels = 85, RuleOC_NodeLabel = 86, + RuleOC_RangeLiteral = 87, RuleKU_RecursiveRelationshipComprehension = 88, + RuleKU_IntermediateNodeProjectionItems = 89, RuleKU_IntermediateRelProjectionItems = 90, + RuleOC_LowerBound = 91, RuleOC_UpperBound = 92, RuleOC_LabelName = 93, + RuleOC_RelTypeName = 94, RuleOC_Expression = 95, RuleOC_OrExpression = 96, + RuleOC_XorExpression = 97, RuleOC_AndExpression = 98, RuleOC_NotExpression = 99, + RuleOC_ComparisonExpression = 100, RuleKU_ComparisonOperator = 101, + RuleKU_BitwiseOrOperatorExpression = 102, RuleKU_BitwiseAndOperatorExpression = 103, + RuleKU_BitShiftOperatorExpression = 104, RuleKU_BitShiftOperator = 105, + RuleOC_AddOrSubtractExpression = 106, RuleKU_AddOrSubtractOperator = 107, + RuleOC_MultiplyDivideModuloExpression = 108, RuleKU_MultiplyDivideModuloOperator = 109, + RuleOC_PowerOfExpression = 110, RuleOC_UnaryAddSubtractOrFactorialExpression = 111, + RuleOC_StringListNullOperatorExpression = 112, RuleOC_ListOperatorExpression = 113, + RuleOC_StringOperatorExpression = 114, RuleOC_RegularExpression = 115, + RuleOC_NullOperatorExpression = 116, RuleOC_PropertyOrLabelsExpression = 117, + RuleOC_Atom = 118, RuleOC_Literal = 119, RuleOC_BooleanLiteral = 120, + RuleOC_ListLiteral = 121, RuleKU_ListEntry = 122, RuleKU_StructLiteral = 123, + RuleKU_StructField = 124, RuleOC_ParenthesizedExpression = 125, RuleOC_FunctionInvocation = 126, + RuleOC_FunctionName = 127, RuleKU_FunctionParameter = 128, RuleOC_PathPatterns = 129, + RuleOC_ExistSubquery = 130, RuleKU_CountSubquery = 131, RuleOC_PropertyLookup = 132, + RuleOC_CaseExpression = 133, RuleOC_CaseAlternative = 134, RuleOC_Variable = 135, + RuleOC_NumberLiteral = 136, RuleOC_Parameter = 137, RuleOC_PropertyExpression = 138, + RuleOC_PropertyKeyName = 139, RuleOC_IntegerLiteral = 140, RuleOC_DoubleLiteral = 141, + RuleOC_SchemaName = 142, RuleOC_SymbolicName = 143, RuleKU_NonReservedKeywords = 144, + RuleOC_LeftArrowHead = 145, RuleOC_RightArrowHead = 146, RuleOC_Dash = 147 }; explicit CypherParser(antlr4::TokenStream *input); @@ -116,10 +118,13 @@ class CypherParser : public antlr4::Parser { class OC_StatementContext; class KU_CopyFromContext; class KU_ColumnNamesContext; + class KU_ScanSourceContext; class KU_CopyFromByColumnContext; class KU_CopyTOContext; class KU_ExportDatabaseContext; class KU_ImportDatabaseContext; + class KU_AttachDatabaseContext; + class KU_DetachDatabaseContext; class KU_StandaloneCallContext; class KU_CommentOnContext; class KU_CreateMacroContext; @@ -302,6 +307,8 @@ class CypherParser : public antlr4::Parser { KU_ExtensionContext *kU_Extension(); KU_ExportDatabaseContext *kU_ExportDatabase(); KU_ImportDatabaseContext *kU_ImportDatabase(); + KU_AttachDatabaseContext *kU_AttachDatabase(); + KU_DetachDatabaseContext *kU_DetachDatabase(); }; @@ -317,8 +324,7 @@ class CypherParser : public antlr4::Parser { antlr4::tree::TerminalNode* SP(size_t i); OC_SchemaNameContext *oC_SchemaName(); antlr4::tree::TerminalNode *FROM(); - KU_FilePathsContext *kU_FilePaths(); - OC_VariableContext *oC_Variable(); + KU_ScanSourceContext *kU_ScanSource(); KU_ParsingOptionsContext *kU_ParsingOptions(); KU_ColumnNamesContext *kU_ColumnNames(); @@ -341,6 +347,21 @@ class CypherParser : public antlr4::Parser { KU_ColumnNamesContext* kU_ColumnNames(); + class KU_ScanSourceContext : public antlr4::ParserRuleContext { + public: + KU_ScanSourceContext(antlr4::ParserRuleContext *parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + KU_FilePathsContext *kU_FilePaths(); + OC_QueryContext *oC_Query(); + std::vector SP(); + antlr4::tree::TerminalNode* SP(size_t i); + OC_VariableContext *oC_Variable(); + + + }; + + KU_ScanSourceContext* kU_ScanSource(); + class KU_CopyFromByColumnContext : public antlr4::ParserRuleContext { public: KU_CopyFromByColumnContext(antlr4::ParserRuleContext *parent, size_t invokingState); @@ -408,6 +429,37 @@ class CypherParser : public antlr4::Parser { KU_ImportDatabaseContext* kU_ImportDatabase(); + class KU_AttachDatabaseContext : public antlr4::ParserRuleContext { + public: + KU_AttachDatabaseContext(antlr4::ParserRuleContext *parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode *ATTACH(); + std::vector SP(); + antlr4::tree::TerminalNode* SP(size_t i); + std::vector StringLiteral(); + antlr4::tree::TerminalNode* StringLiteral(size_t i); + antlr4::tree::TerminalNode *AS(); + OC_SchemaNameContext *oC_SchemaName(); + antlr4::tree::TerminalNode *DBTYPE(); + + + }; + + KU_AttachDatabaseContext* kU_AttachDatabase(); + + class KU_DetachDatabaseContext : public antlr4::ParserRuleContext { + public: + KU_DetachDatabaseContext(antlr4::ParserRuleContext *parent, size_t invokingState); + virtual size_t getRuleIndex() const override; + antlr4::tree::TerminalNode *DETACH(); + antlr4::tree::TerminalNode *SP(); + OC_SchemaNameContext *oC_SchemaName(); + + + }; + + KU_DetachDatabaseContext* kU_DetachDatabase(); + class KU_StandaloneCallContext : public antlr4::ParserRuleContext { public: KU_StandaloneCallContext(antlr4::ParserRuleContext *parent, size_t invokingState); @@ -427,7 +479,7 @@ class CypherParser : public antlr4::Parser { public: KU_CommentOnContext(antlr4::ParserRuleContext *parent, size_t invokingState); virtual size_t getRuleIndex() const override; - antlr4::tree::TerminalNode *COMMENT(); + antlr4::tree::TerminalNode *COMMENT_(); std::vector SP(); antlr4::tree::TerminalNode* SP(size_t i); antlr4::tree::TerminalNode *ON(); @@ -1063,13 +1115,12 @@ class CypherParser : public antlr4::Parser { std::vector SP(); antlr4::tree::TerminalNode* SP(size_t i); antlr4::tree::TerminalNode *FROM(); - KU_FilePathsContext *kU_FilePaths(); - OC_VariableContext *oC_Variable(); + KU_ScanSourceContext *kU_ScanSource(); antlr4::tree::TerminalNode *WITH(); antlr4::tree::TerminalNode *HEADERS(); KU_PropertyDefinitionsContext *kU_PropertyDefinitions(); - OC_WhereContext *oC_Where(); KU_ParsingOptionsContext *kU_ParsingOptions(); + OC_WhereContext *oC_Where(); }; @@ -2338,7 +2389,7 @@ class CypherParser : public antlr4::Parser { public: KU_NonReservedKeywordsContext(antlr4::ParserRuleContext *parent, size_t invokingState); virtual size_t getRuleIndex() const override; - antlr4::tree::TerminalNode *COMMENT(); + antlr4::tree::TerminalNode *COMMENT_(); antlr4::tree::TerminalNode *COUNT(); antlr4::tree::TerminalNode *NODE(); antlr4::tree::TerminalNode *REL(); diff --git a/tools/java_api/src/jni/kuzu_java.cpp b/tools/java_api/src/jni/kuzu_java.cpp index 40c234ec450..4f7418cd988 100644 --- a/tools/java_api/src/jni/kuzu_java.cpp +++ b/tools/java_api/src/jni/kuzu_java.cpp @@ -530,7 +530,7 @@ struct JavaAPIHelper { } // namespace kuzu::common JNIEXPORT jlong JNICALL Java_com_kuzudb_KuzuNative_kuzu_1data_1type_1create( - JNIEnv* env, jclass, jobject id, jobject child_type, jlong fixed_num_elements_in_list) { + JNIEnv* env, jclass, jobject id, jobject child_type, jlong num_elements_in_array) { jclass javaIDClass = env->GetObjectClass(id); jfieldID fieldID = env->GetFieldID(javaIDClass, "value", "I"); jint fieldValue = env->GetIntField(id, fieldID); @@ -542,10 +542,10 @@ JNIEXPORT jlong JNICALL Java_com_kuzudb_KuzuNative_kuzu_1data_1type_1create( data_type = new LogicalType(logicalTypeID); } else { auto child_type_pty = std::make_unique(*getDataType(env, child_type)); - auto extraTypeInfo = fixed_num_elements_in_list > 0 ? - std::make_unique( - std::move(child_type_pty), fixed_num_elements_in_list) : - std::make_unique(std::move(child_type_pty)); + auto extraTypeInfo = num_elements_in_array > 0 ? + std::make_unique( + std::move(child_type_pty), num_elements_in_array) : + std::make_unique(std::move(child_type_pty)); data_type = JavaAPIHelper::createLogicalType(logicalTypeID, std::move(extraTypeInfo)); } uint64_t address = reinterpret_cast(data_type); @@ -591,10 +591,10 @@ JNIEXPORT jobject JNICALL Java_com_kuzudb_KuzuNative_kuzu_1data_1type_1get_1chil JNIEnv* env, jclass, jobject thisDT) { auto* parent_type = getDataType(env, thisDT); LogicalType* child_type; - if (parent_type->getLogicalTypeID() == LogicalTypeID::FIXED_LIST) { - child_type = FixedListType::getChildType(parent_type); - } else if (parent_type->getLogicalTypeID() == LogicalTypeID::VAR_LIST) { - child_type = VarListType::getChildType(parent_type); + if (parent_type->getLogicalTypeID() == LogicalTypeID::ARRAY) { + child_type = ArrayType::getChildType(parent_type); + } else if (parent_type->getLogicalTypeID() == LogicalTypeID::LIST) { + child_type = ListType::getChildType(parent_type); } else { return nullptr; } @@ -604,13 +604,13 @@ JNIEXPORT jobject JNICALL Java_com_kuzudb_KuzuNative_kuzu_1data_1type_1get_1chil } JNIEXPORT jlong JNICALL -Java_com_kuzudb_KuzuNative_kuzu_1data_1type_1get_1fixed_1num_1elements_1in_1list( +Java_com_kuzudb_KuzuNative_kuzu_1data_1type_1get_1num_1elements_1in_1array( JNIEnv* env, jclass, jobject thisDT) { auto* dt = getDataType(env, thisDT); - if (dt->getLogicalTypeID() != LogicalTypeID::FIXED_LIST) { + if (dt->getLogicalTypeID() != LogicalTypeID::ARRAY) { return 0; } - return static_cast(FixedListType::getNumValuesInList(dt)); + return static_cast(ArrayType::getNumElements(dt)); } /** diff --git a/tools/java_api/src/main/java/com/kuzudb/KuzuDataType.java b/tools/java_api/src/main/java/com/kuzudb/KuzuDataType.java index b45e110b232..e3c4aba08fd 100644 --- a/tools/java_api/src/main/java/com/kuzudb/KuzuDataType.java +++ b/tools/java_api/src/main/java/com/kuzudb/KuzuDataType.java @@ -16,8 +16,8 @@ public KuzuDataType(KuzuDataTypeID id) { } public KuzuDataType - (KuzuDataTypeID id, KuzuDataType child_type, long fixed_num_elements_in_list) { - dt_ref = KuzuNative.kuzu_data_type_create(id, child_type, fixed_num_elements_in_list); + (KuzuDataTypeID id, KuzuDataType child_type, long num_elements_in_array) { + dt_ref = KuzuNative.kuzu_data_type_create(id, child_type, num_elements_in_array); } /** @@ -97,7 +97,7 @@ public KuzuDataType getChildType() throws KuzuObjectRefDestroyedException { */ public long getFixedNumElementsInList() throws KuzuObjectRefDestroyedException { checkNotDestroyed(); - return KuzuNative.kuzu_data_type_get_fixed_num_elements_in_list(this); + return KuzuNative.kuzu_data_type_get_num_elements_in_array(this); } } diff --git a/tools/java_api/src/main/java/com/kuzudb/KuzuDataTypeID.java b/tools/java_api/src/main/java/com/kuzudb/KuzuDataTypeID.java index dcf21faf692..20e94b971d2 100644 --- a/tools/java_api/src/main/java/com/kuzudb/KuzuDataTypeID.java +++ b/tools/java_api/src/main/java/com/kuzudb/KuzuDataTypeID.java @@ -28,15 +28,15 @@ public enum KuzuDataTypeID { TIMESTAMP_NS(38), TIMESTAMP_TZ(39), INTERVAL(40), - FIXED_LIST(41), INTERNAL_ID(42), STRING(50), BLOB(51), - VAR_LIST(52), - STRUCT(53), - MAP(54), - UNION(55), - UUID(56),; + LIST(52), + ARRAY(53), + STRUCT(54), + MAP(55), + UNION(56), + UUID(59),; public final int value; diff --git a/tools/java_api/src/main/java/com/kuzudb/KuzuNative.java b/tools/java_api/src/main/java/com/kuzudb/KuzuNative.java index b6d68610dab..44a0d4d62b7 100644 --- a/tools/java_api/src/main/java/com/kuzudb/KuzuNative.java +++ b/tools/java_api/src/main/java/com/kuzudb/KuzuNative.java @@ -145,7 +145,7 @@ protected static native KuzuDataType kuzu_query_result_get_column_data_type( // DataType protected static native long kuzu_data_type_create( - KuzuDataTypeID id, KuzuDataType child_type, long fixed_num_elements_in_list); + KuzuDataTypeID id, KuzuDataType child_type, long num_elements_in_array); protected static native KuzuDataType kuzu_data_type_clone(KuzuDataType data_type); @@ -157,7 +157,7 @@ protected static native long kuzu_data_type_create( protected static native KuzuDataType kuzu_data_type_get_child_type(KuzuDataType data_type); - protected static native long kuzu_data_type_get_fixed_num_elements_in_list(KuzuDataType data_type); + protected static native long kuzu_data_type_get_num_elements_in_array(KuzuDataType data_type); // Value protected static native KuzuValue kuzu_value_create_null(); diff --git a/tools/java_api/src/test/java/com/kuzudb/test/DataTypeTest.java b/tools/java_api/src/test/java/com/kuzudb/test/DataTypeTest.java index 7977aa7fe1d..6829ff50fe3 100644 --- a/tools/java_api/src/test/java/com/kuzudb/test/DataTypeTest.java +++ b/tools/java_api/src/test/java/com/kuzudb/test/DataTypeTest.java @@ -16,18 +16,18 @@ void DataTypeClone() throws KuzuObjectRefDestroyedException { assertNotNull(dataTypeClone); assertEquals(dataTypeClone.getID(), KuzuDataTypeID.INT64); - KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.VAR_LIST, dataType, 0); + KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.LIST, dataType, 0); assertNotNull(dataType2); KuzuDataType dataTypeClone2 = dataType2.clone(); assertNotNull(dataTypeClone2); - assertEquals(dataTypeClone2.getID(), KuzuDataTypeID.VAR_LIST); + assertEquals(dataTypeClone2.getID(), KuzuDataTypeID.LIST); assertEquals(dataTypeClone2.getChildType().getID(), KuzuDataTypeID.INT64); - KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.FIXED_LIST, dataType, 100); + KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.ARRAY, dataType, 100); assertNotNull(dataType3); KuzuDataType dataTypeClone3 = dataType3.clone(); assertNotNull(dataTypeClone3); - assertEquals(dataTypeClone3.getID(), KuzuDataTypeID.FIXED_LIST); + assertEquals(dataTypeClone3.getID(), KuzuDataTypeID.ARRAY); assertEquals(dataTypeClone3.getChildType().getID(), KuzuDataTypeID.INT64); assertEquals(dataTypeClone3.getFixedNumElementsInList(), 100); @@ -49,13 +49,13 @@ void DataTypeEquals() throws KuzuObjectRefDestroyedException { assertNotNull(dataTypeClone); assertTrue(dataType.equals(dataTypeClone)); - KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.VAR_LIST, dataType, 0); + KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.LIST, dataType, 0); assertNotNull(dataType2); KuzuDataType dataTypeClone2 = dataType2.clone(); assertNotNull(dataTypeClone2); assertTrue(dataType2.equals(dataTypeClone2)); - KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.FIXED_LIST, dataType, 100); + KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.ARRAY, dataType, 100); assertNotNull(dataType3); KuzuDataType dataTypeClone3 = dataType3.clone(); assertNotNull(dataTypeClone3); @@ -80,13 +80,13 @@ void DataTypeGetID() throws KuzuObjectRefDestroyedException { assertNotNull(dataType); assertEquals(dataType.getID(), KuzuDataTypeID.INT64); - KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.VAR_LIST, dataType, 0); + KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.LIST, dataType, 0); assertNotNull(dataType2); - assertEquals(dataType2.getID(), KuzuDataTypeID.VAR_LIST); + assertEquals(dataType2.getID(), KuzuDataTypeID.LIST); - KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.FIXED_LIST, dataType, 100); + KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.ARRAY, dataType, 100); assertNotNull(dataType3); - assertEquals(dataType3.getID(), KuzuDataTypeID.FIXED_LIST); + assertEquals(dataType3.getID(), KuzuDataTypeID.ARRAY); dataType.destroy(); dataType2.destroy(); @@ -98,11 +98,11 @@ void DataTypeGetChildType() throws KuzuObjectRefDestroyedException { KuzuDataType dataType = new KuzuDataType(KuzuDataTypeID.INT64, null, 0); assertNotNull(dataType); - KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.VAR_LIST, dataType, 0); + KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.LIST, dataType, 0); assertNotNull(dataType2); assertEquals(dataType2.getChildType().getID(), KuzuDataTypeID.INT64); - KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.FIXED_LIST, dataType, 100); + KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.ARRAY, dataType, 100); assertNotNull(dataType3); assertEquals(dataType3.getChildType().getID(), KuzuDataTypeID.INT64); @@ -117,11 +117,11 @@ void DataTypeGetFixedNumElementsInList() throws KuzuObjectRefDestroyedException assertNotNull(dataType); assertEquals(dataType.getFixedNumElementsInList(), 0); - KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.VAR_LIST, dataType, 0); + KuzuDataType dataType2 = new KuzuDataType(KuzuDataTypeID.LIST, dataType, 0); assertNotNull(dataType2); assertEquals(dataType.getFixedNumElementsInList(), 0); - KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.FIXED_LIST, dataType, 100); + KuzuDataType dataType3 = new KuzuDataType(KuzuDataTypeID.ARRAY, dataType, 100); assertNotNull(dataType3); assertEquals(dataType3.getFixedNumElementsInList(), 100); diff --git a/tools/java_api/src/test/java/com/kuzudb/test/ValueTest.java b/tools/java_api/src/test/java/com/kuzudb/test/ValueTest.java index 00338caf143..4e1c057885e 100644 --- a/tools/java_api/src/test/java/com/kuzudb/test/ValueTest.java +++ b/tools/java_api/src/test/java/com/kuzudb/test/ValueTest.java @@ -323,7 +323,7 @@ void ValueGetDatatype() throws KuzuObjectRefDestroyedException { value = flatTuple.getValue(2); dataType = value.getDataType(); - assertEquals(dataType.getID(), KuzuDataTypeID.VAR_LIST); + assertEquals(dataType.getID(), KuzuDataTypeID.LIST); KuzuDataType childDataType = dataType.getChildType(); assertEquals(childDataType.getID(), KuzuDataTypeID.INT64); childDataType.destroy(); diff --git a/tools/nodejs_api/src_cpp/node_util.cpp b/tools/nodejs_api/src_cpp/node_util.cpp index c4573778d51..fd676a9fc34 100644 --- a/tools/nodejs_api/src_cpp/node_util.cpp +++ b/tools/nodejs_api/src_cpp/node_util.cpp @@ -184,8 +184,8 @@ Napi::Value Util::ConvertToNapiObject(const Value& value, Napi::Env env) { auto milliseconds = microseconds / Interval::MICROS_PER_MSEC; return Napi::Number::New(env, milliseconds); } - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: { + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: { auto size = NestedVal::getChildrenSize(&value); auto napiArray = Napi::Array::New(env, size); for (auto i = 0u; i < size; ++i) { @@ -310,11 +310,11 @@ Value Util::TransformNapiValue( case LogicalTypeID::BOOL: { return Value(napiValue.ToBoolean().Value()); } - case LogicalTypeID::INT16: { + case LogicalTypeID::INT64: { if (!napiValue.IsNumber()) { throw Exception("Expected a number for parameter " + key + "."); } - int16_t val = napiValue.ToNumber().Int32Value(); + int64_t val = napiValue.ToNumber().Int64Value(); return Value(val); } case LogicalTypeID::INT32: { @@ -324,18 +324,65 @@ Value Util::TransformNapiValue( int32_t val = napiValue.ToNumber().Int32Value(); return Value(val); } - case LogicalTypeID::INT64: { + case LogicalTypeID::INT16: { if (!napiValue.IsNumber()) { throw Exception("Expected a number for parameter " + key + "."); } - int64_t val = napiValue.ToNumber().Int64Value(); + int16_t val = napiValue.ToNumber().Int32Value(); return Value(val); } - case LogicalTypeID::FLOAT: { + case LogicalTypeID::INT8: { if (!napiValue.IsNumber()) { throw Exception("Expected a number for parameter " + key + "."); } - float val = napiValue.ToNumber().FloatValue(); + int8_t val = napiValue.ToNumber().Int32Value(); + return Value(val); + } + case LogicalTypeID::UINT64: { + if (!napiValue.IsNumber()) { + throw Exception("Expected a number for parameter " + key + "."); + } + auto valStr = napiValue.ToNumber().ToString(); + uint64_t val = std::stoull(valStr); + return Value(val); + } + case LogicalTypeID::UINT32: { + if (!napiValue.IsNumber()) { + throw Exception("Expected a number for parameter " + key + "."); + } + uint32_t val = napiValue.ToNumber().Uint32Value(); + return Value(val); + } + case LogicalTypeID::UINT16: { + if (!napiValue.IsNumber()) { + throw Exception("Expected a number for parameter " + key + "."); + } + uint16_t val = napiValue.ToNumber().Uint32Value(); + return Value(val); + } + case LogicalTypeID::UINT8: { + if (!napiValue.IsNumber()) { + throw Exception("Expected a number for parameter " + key + "."); + } + uint8_t val = napiValue.ToNumber().Uint32Value(); + return Value(val); + } + case LogicalTypeID::INT128: { + if (!napiValue.IsBigInt()) { + throw Exception("Expected a BigInt for parameter " + key + "."); + } + auto bigInt = napiValue.As(); + size_t wordsCount = bigInt.WordCount(); + std::unique_ptr words(new uint64_t[wordsCount]); + int signBit; + bigInt.ToWords(&signBit, &wordsCount, words.get()); + kuzu::common::int128_t val; + val.low = words[0]; + val.high = words[1]; + // Ignore words[2] and beyond as we only support 128-bit integers but BigInt can be larger. + if (signBit) { + kuzu::common::Int128_t::negateInPlace(val); + } return Value(val); } case LogicalTypeID::DOUBLE: { @@ -345,9 +392,12 @@ Value Util::TransformNapiValue( double val = napiValue.ToNumber().DoubleValue(); return Value(val); } - case LogicalTypeID::STRING: { - std::string val = napiValue.ToString().Utf8Value(); - return Value(LogicalType::STRING(), val); + case LogicalTypeID::FLOAT: { + if (!napiValue.IsNumber()) { + throw Exception("Expected a number for parameter " + key + "."); + } + float val = napiValue.ToNumber().FloatValue(); + return Value(val); } case LogicalTypeID::DATE: { if (!napiValue.IsDate()) { @@ -416,6 +466,15 @@ Value Util::TransformNapiValue( auto normalizedInterval = interval_t(normalizedMonths, normalizedDays, normalizedMicros); return Value(normalizedInterval); } + case LogicalTypeID::STRING: { + std::string val = napiValue.ToString().Utf8Value(); + return Value(LogicalType::STRING(), val); + } + case LogicalTypeID::UUID: { + std::string stringVal = napiValue.ToString().Utf8Value(); + auto val = UUID::fromString(stringVal); + return Value(val); + } default: throw Exception( "Unsupported type " + expectedDataType->toString() + " for parameter: " + key); diff --git a/tools/nodejs_api/src_js/connection.js b/tools/nodejs_api/src_js/connection.js index 56f92ef2d36..05ff41ccf14 100644 --- a/tools/nodejs_api/src_js/connection.js +++ b/tools/nodejs_api/src_js/connection.js @@ -116,13 +116,14 @@ class Connection { typeof value === "boolean" || typeof value === "number" || typeof value === "string" || - (typeof value === "object" && value.constructor.name === "Date") + (typeof value === "object" && value.constructor.name === "Date") || + typeof value === "bigint" ) { paramArray.push([key, value]); } else { return reject( new Error( - "The value of each parameter must be a boolean, number, string, or Date object." + "The value of each parameter must be a boolean, number, string, Date or BigInt." ) ); } diff --git a/tools/nodejs_api/test/test_connection.js b/tools/nodejs_api/test/test_connection.js index 3454ba51262..3f2a4628001 100644 --- a/tools/nodejs_api/test/test_connection.js +++ b/tools/nodejs_api/test/test_connection.js @@ -133,7 +133,7 @@ describe("Execute", function () { } catch (e) { assert.equal( e.message, - "The value of each parameter must be a boolean, number, string, or Date object." + "The value of each parameter must be a boolean, number, string, Date or BigInt." ); } }); diff --git a/tools/nodejs_api/test/test_data_type.js b/tools/nodejs_api/test/test_data_type.js index eaaefa8d63c..033eb107e95 100644 --- a/tools/nodejs_api/test/test_data_type.js +++ b/tools/nodejs_api/test/test_data_type.js @@ -339,8 +339,8 @@ describe("INTERVAL", function () { }); }); -describe("VAR_LIST", function () { - it("should convert VAR_LIST type", async function () { +describe("LIST", function () { + it("should convert LIST type", async function () { const queryResult = await conn.query( "MATCH (a:person) WHERE a.ID = 0 RETURN a.courseScoresPerTerm;" ); @@ -359,8 +359,8 @@ describe("VAR_LIST", function () { }); }); -describe("FIXED_LIST", function () { - it("should convert FIXED_LIST type", async function () { +describe("ARRAY", function () { + it("should convert ARRAY type", async function () { const queryResult = await conn.query( "MATCH (a:person) -[m:meets]-> (b:person) WHERE a.ID = 0 AND b.ID = 2 RETURN m.location" ); diff --git a/tools/nodejs_api/test/test_parameter.js b/tools/nodejs_api/test/test_parameter.js index 1db1276683c..afba5b5b146 100644 --- a/tools/nodejs_api/test/test_parameter.js +++ b/tools/nodejs_api/test/test_parameter.js @@ -152,6 +152,170 @@ describe("INT16", function () { }); }); +describe("INT8", function () { + it("should transform number as INT8 parameter", async function () { + const preparedStatement = await conn.prepare( + "MATCH (m:movies) WHERE m.description.stars > $1 RETURN COUNT(*)" + ); + const queryResult = await conn.execute(preparedStatement, { + 1: 10, + }); + const result = await queryResult.getAll(); + assert.equal(result[0]["COUNT_STAR()"], 1); + }); + + it("should reject other type as INT8 parameter", async function () { + const preparedStatement = await conn.prepare( + "MATCH (m:movies) WHERE m.description.stars > $1 RETURN COUNT(*)" + ); + try { + await conn.execute(preparedStatement, { + 1: "4", + }); + } catch (e) { + assert.equal(e.message, "Expected a number for parameter 1."); + } + }); +}); + +describe("UINT64", function () { + it("should transform number as UINT64 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT64')"); + const queryResult = await conn.execute(preparedStatement, { + 1: 10000000000000000000, + }); + const result = await queryResult.getAll(); + assert.equal(result[0]["CAST($1, UINT64)"], "10000000000000000000"); + }); + + it("should reject other type as UINT64 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT64')"); + try { + await conn.execute(preparedStatement, { + 1: "10000000000000000000", + }); + } catch (e) { + assert.equal(e.message, "Expected a number for parameter 1."); + } + }); +}); + +describe("UINT32", function () { + it("should transform number as UINT32 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT32')"); + const queryResult = await conn.execute(preparedStatement, { + 1: 4294967295, + }); + const result = await queryResult.getAll(); + assert.equal(result[0]["CAST($1, UINT32)"], "4294967295"); + }); + + it("should reject other type as UINT32 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT32')"); + try { + await conn.execute(preparedStatement, { + 1: "4294967295", + }); + } catch (e) { + assert.equal(e.message, "Expected a number for parameter 1."); + } + }); +}); + +describe("UINT16", function () { + it("should transform number as UINT16 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT16')"); + const queryResult = await conn.execute(preparedStatement, { + 1: 65535, + }); + const result = await queryResult.getAll(); + assert.equal(result[0]["CAST($1, UINT16)"], "65535"); + }); + + it("should reject other type as UINT16 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT16')"); + try { + await conn.execute(preparedStatement, { + 1: "65535", + }); + } catch (e) { + assert.equal(e.message, "Expected a number for parameter 1."); + } + }); +}); + +describe("UINT8", function () { + it("should transform number as UINT8 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT8')"); + const queryResult = await conn.execute(preparedStatement, { + 1: 255, + }); + const result = await queryResult.getAll(); + assert.equal(result[0]["CAST($1, UINT8)"], "255"); + }); + + it("should reject other type as UINT8 parameter", async function () { + const preparedStatement = await conn.prepare("RETURN CAST($1, 'UINT8')"); + try { + await conn.execute(preparedStatement, { + 1: "255", + }); + } catch (e) { + assert.equal(e.message, "Expected a number for parameter 1."); + } + }); +}); + +//TODO(Chang): fix me +// describe("INT128", function () { +// it("should transform single-word positive BigInt as INT128 parameter", async function () { +// const preparedStatement = await conn.prepare("RETURN CAST($1, 'STRING')"); +// const queryResult = await conn.execute(preparedStatement, { +// 1: BigInt("123456789"), +// }); +// const result = await queryResult.getAll(); +// assert.equal(result[0]["CAST($1, STRING)"], "123456789"); +// }); +// +// it("should transform single-word negative BigInt as INT128 parameter", async function () { +// const preparedStatement = await conn.prepare("RETURN CAST($1, 'STRING')"); +// const queryResult = await conn.execute(preparedStatement, { +// 1: BigInt("-123456789"), +// }); +// const result = await queryResult.getAll(); +// assert.equal(result[0]["CAST($1, STRING)"], "-123456789"); +// }); +// +// it("should transform two-word positive BigInt as INT128 parameter", async function () { +// const preparedStatement = await conn.prepare("RETURN CAST($1, 'STRING')"); +// const queryResult = await conn.execute(preparedStatement, { +// 1: BigInt("18446744073709551610"), +// }); +// const result = await queryResult.getAll(); +// assert.equal(result[0]["CAST($1, STRING)"], "18446744073709551610"); +// }); +// +// it("should transform two-word negative BigInt as INT128 parameter", async function () { +// const preparedStatement = await conn.prepare("RETURN CAST($1, 'STRING')"); +// const queryResult = await conn.execute(preparedStatement, { +// 1: BigInt("-18446744073709551610"), +// }); +// const result = await queryResult.getAll(); +// assert.equal(result[0]["CAST($1, STRING)"], "-18446744073709551610"); +// }); +// +// it("should reject other type as INT128 parameter", async function () { +// const preparedStatement = await conn.prepare("RETURN CAST($1, 'STRING')"); +// try { +// await conn.execute(preparedStatement, { +// 1: "123456789", +// }); +// } catch (e) { +// assert.equal(e.message, "Expected a BigInt for parameter 1."); +// } +// }); +// }); + describe("DOUBLE", function () { it("should transform number as DOUBLE parameter", async function () { const preparedStatement = await conn.prepare( @@ -359,7 +523,7 @@ describe("TIMESTAMP", function () { describe("TIMESTAMP_TZ", function () { it("should transform date as TIMESTAMP_TZ parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_tz > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_tz > $1 RETURN COUNT(*)" ); const queryResult = await conn.execute(preparedStatement, { 1: new Date(0), @@ -370,7 +534,7 @@ describe("TIMESTAMP_TZ", function () { it("should reject other type as TIMESTAMP_TZ parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_tz > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_tz > $1 RETURN COUNT(*)" ); try { await conn.execute(preparedStatement, { @@ -401,7 +565,7 @@ describe("TIMESTAMP_TZ", function () { describe("TIMESTAMP_NS", function () { it("should transform date as TIMESTAMP_NS parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_ns > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_ns > $1 RETURN COUNT(*)" ); const queryResult = await conn.execute(preparedStatement, { 1: new Date(0), @@ -412,7 +576,7 @@ describe("TIMESTAMP_NS", function () { it("should reject other type as TIMESTAMP_NS parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_ns > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_ns > $1 RETURN COUNT(*)" ); try { await conn.execute(preparedStatement, { @@ -443,7 +607,7 @@ describe("TIMESTAMP_NS", function () { describe("TIMESTAMP_MS", function () { it("should transform date as TIMESTAMP_MS parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_ms > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_ms > $1 RETURN COUNT(*)" ); const queryResult = await conn.execute(preparedStatement, { 1: new Date(0), @@ -454,7 +618,7 @@ describe("TIMESTAMP_MS", function () { it("should reject other type as TIMESTAMP_MS parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_ms > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_ms > $1 RETURN COUNT(*)" ); try { await conn.execute(preparedStatement, { @@ -485,7 +649,7 @@ describe("TIMESTAMP_MS", function () { describe("TIMESTAMP_SEC", function () { it("should transform date as TIMESTAMP_SEC parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_sec > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_sec > $1 RETURN COUNT(*)" ); const queryResult = await conn.execute(preparedStatement, { 1: new Date(0), @@ -496,7 +660,7 @@ describe("TIMESTAMP_SEC", function () { it("should reject other type as TIMESTAMP_SEC parameter", async function () { const preparedStatement = await conn.prepare( - "MATCH (a:movies) WHERE a.description.release_sec > $1 RETURN COUNT(*)" + "MATCH (a:movies) WHERE a.description.release_sec > $1 RETURN COUNT(*)" ); try { await conn.execute(preparedStatement, { @@ -565,3 +729,16 @@ describe("INTERVAL", function () { } }); }); + +describe("UUID", function () { + it("should transform string as UUID parameter", async function () { + const preparedStatement = await conn.prepare( + "RETURN CAST($1, 'STRING') AS UUID" + ); + const queryResult = await conn.execute(preparedStatement, { + 1: "123e4567-e89b-12d3-a456-426614174000", + }); + const result = await queryResult.getAll(); + assert.equal(result[0]["UUID"], "123e4567-e89b-12d3-a456-426614174000"); + }); +}); diff --git a/tools/python_api/CMakeLists.txt b/tools/python_api/CMakeLists.txt index e1c3e1f4d97..aa0fb52fcc3 100644 --- a/tools/python_api/CMakeLists.txt +++ b/tools/python_api/CMakeLists.txt @@ -9,12 +9,16 @@ file(GLOB SOURCE_PY pybind11_add_module(_kuzu SHARED src_cpp/kuzu_binding.cpp + src_cpp/cached_import/py_cached_item.cpp + src_cpp/cached_import/py_cached_import.cpp src_cpp/py_connection.cpp src_cpp/py_database.cpp src_cpp/py_prepared_statement.cpp src_cpp/py_query_result.cpp src_cpp/py_query_result_converter.cpp src_cpp/py_conversion.cpp + src_cpp/pyarrow/pyarrow_bind.cpp + src_cpp/pyarrow/pyarrow_scan.cpp src_cpp/pandas/pandas_bind.cpp src_cpp/pandas/pandas_scan.cpp src_cpp/pandas/pandas_analyzer.cpp diff --git a/tools/python_api/Makefile b/tools/python_api/Makefile new file mode 100644 index 00000000000..fbf95585adf --- /dev/null +++ b/tools/python_api/Makefile @@ -0,0 +1,42 @@ +.DEFAULT_GOAL := help + +PYTHONPATH= +SHELL=/bin/bash +VENV=.venv + +ifeq ($(OS),Windows_NT) + VENV_BIN=$(VENV)/Scripts +else + VENV_BIN=$(VENV)/bin +endif + +.venv: ## Set up a Python virtual environment and install dev packages + python3 -m venv $(VENV) + $(MAKE) requirements + +.PHONY: requirements +requirements: .venv ## Install/update Python dev packages + @unset CONDA_PREFIX \ + && $(VENV_BIN)/python -m pip install -U uv \ + && $(VENV_BIN)/uv pip install --upgrade -r requirements_dev.txt \ + +.PHONY: lint +lint: ## Apply autoformatting and linting rules + $(VENV_BIN)/ruff check src_py test + $(VENV_BIN)/ruff format src_py test + -$(VENV_BIN)/mypy src_py test + +.PHONY: build +build: ## Compile kuzu (and install in 'build') for Python + $(MAKE) -C ../../ python + cp src_py/*.py build/kuzu/ + +.PHONY: test +test: ## Run the Python unit tests + cp src_py/*.py build/kuzu/ && cd build + $(VENV_BIN)/pytest test + +.PHONY: help +help: ## Display this help information + @echo -e "\033[1mAvailable commands:\033[0m" + @grep -E '^[a-z.A-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}' | sort diff --git a/tools/python_api/pyproject.toml b/tools/python_api/pyproject.toml new file mode 100644 index 00000000000..29f8a5ac578 --- /dev/null +++ b/tools/python_api/pyproject.toml @@ -0,0 +1,97 @@ +[project] +name = "kuzu" +description = "Highly scalable, extremely fast, easy-to-use embeddable graph database" +readme = "README.md" +license = { file = "LICENSE" } +keywords = ["graph", "database"] +version = "0.0.1" + +[project.urls] +Homepage = "https://kuzudb.com/" +Documentation = "https://docs.kuzudb.com/" +Repository = "https://github.com/kuzudb/kuzu" +Changelog = "https://github.com/kuzudb/kuzu/releases" + +[tool.mypy] +files = ["src_py", "test"] +strict = true +enable_error_code = [ + "redundant-expr", + "truthy-bool", + "ignore-without-code", +] +disable_error_code = [ + "import-not-found", + "no-any-return", +] + +[[tool.mypy.overrides]] +module = [ + "_kuzu.*", + "networkx.*", + "pandas.*", + "pyarrow.*", + "pytz.*", + "torch_geometric.*", +] +ignore_missing_imports = true + +[tool.ruff] +line-length = 119 +preview = true +fix = true + +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "W", # pycodestyle + "F", # Pyflakes + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "D", # flake8-docstrings + "D213", # Augment NumPy docstring convention: Multi-line docstring summary should start at the second line + "D417", # Augment NumPy docstring convention: Missing argument descriptions + "I", # isort + "SIM", # flake8-simplify + "TCH", # flake8-type-checking + "TID", # flake8-tidy-imports + "UP", # pyupgrade + "PT", # flake8-pytest-style + "RUF", # Ruff-specific rules + "PTH", # flake8-use-pathlib + "FA", # flake8-future-annotations + "PIE", # flake8-pie + "TD", # flake8-todos + "TRY", # tryceratops + "EM", # flake8-errmsg + "FBT001", # flake8-boolean-trap +] +ignore = [ + "D401", # First line should be in imperative mood + "D105", # Missing docstring in magic method + "D100", # Missing docstring in public module + "D104", # Missing docstring in public package + "D205", # 1 blank line required between summary line and description + "TD002", # Missing author in TODO + "TD003", # Missing issue link on the line following TODO +] + +[tool.ruff.lint.per-file-ignores] +"test/**/*.py" = ["D100", "D102", "D103", "E501", "F841", "TCH002"] +"src_py/torch_geo*.py" = ["E501", "FBT001"] + +[tool.ruff.lint.pycodestyle] +max-doc-length = 119 + +[tool.ruff.lint.pydocstyle] +convention = "numpy" + +[tool.ruff.lint.flake8-type-checking] +strict = true + +[tool.ruff.format] +docstring-code-format = true + +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/tools/python_api/requirements_dev.txt b/tools/python_api/requirements_dev.txt index ac095f8f454..7643f05bccf 100644 --- a/tools/python_api/requirements_dev.txt +++ b/tools/python_api/requirements_dev.txt @@ -1,7 +1,16 @@ +# required for tests +networkx~=3.0 +numpy +pandas +polars +pyarrow>=14 pybind11>=2.6.0 pytest -pandas -networkx~=3.0.0 -numpy -pyarrow==14.0.1 +torch torch-geometric~=2.3.0 +setuptools~=69.0 + +# required for lint/formatting +ruff==0.3.2 +mypy==1.9.0 +uv==0.1.17 diff --git a/tools/python_api/src_cpp/cached_import/py_cached_import.cpp b/tools/python_api/src_cpp/cached_import/py_cached_import.cpp new file mode 100644 index 00000000000..e0317ab9fda --- /dev/null +++ b/tools/python_api/src_cpp/cached_import/py_cached_import.cpp @@ -0,0 +1,18 @@ +#include "cached_import/py_cached_import.h" + +namespace kuzu { + +PythonCachedImport::~PythonCachedImport() { + py::gil_scoped_acquire acquire; + allObjects.clear(); +} + +py::handle PythonCachedImport::addToCache(py::object obj) { + auto ptr = obj.ptr(); + allObjects.push_back(obj); + return ptr; +} + +std::shared_ptr importCache; + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/cached_import/py_cached_item.cpp b/tools/python_api/src_cpp/cached_import/py_cached_item.cpp new file mode 100644 index 00000000000..ebbc1ecb392 --- /dev/null +++ b/tools/python_api/src_cpp/cached_import/py_cached_item.cpp @@ -0,0 +1,24 @@ +#include "cached_import/py_cached_item.h" + + +#include "cached_import/py_cached_import.h" +#include "common/exception/runtime.h" + +namespace kuzu { + +py::handle PythonCachedItem::operator()() { + assert((bool)PyGILState_Check()); + // load if unloaded, return cached object if already loaded + if (loaded) { + return object; + } + if (parent == nullptr) { + object = importCache->addToCache(std::move(py::module::import(name.c_str()))); + } else { + object = importCache->addToCache(std::move((*parent)().attr(name.c_str()))); + } + loaded = true; + return object; +} + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/include/cached_import/py_cached_import.h b/tools/python_api/src_cpp/include/cached_import/py_cached_import.h new file mode 100644 index 00000000000..cd093224e65 --- /dev/null +++ b/tools/python_api/src_cpp/include/cached_import/py_cached_import.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "py_cached_modules.h" + +namespace kuzu { + +class PythonCachedImport { +public: + // Note: Callers generally acquire the GIL prior to entering functions + // that require the import cache. + + PythonCachedImport() = default; + ~PythonCachedImport(); + + py::handle addToCache(py::object obj); + + DateTimeCachedItem datetime; + DecimalCachedItem decimal; + InspectCachedItem inspect; + NumpyMaCachedItem numpyma; + PandasCachedItem pandas; + PyarrowCachedItem pyarrow; + UUIDCachedItem uuid; + +private: + std::vector allObjects; +}; + +extern std::shared_ptr importCache; + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/include/cached_import/py_cached_item.h b/tools/python_api/src_cpp/include/cached_import/py_cached_item.h new file mode 100644 index 00000000000..159220e79bb --- /dev/null +++ b/tools/python_api/src_cpp/include/cached_import/py_cached_item.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "pybind_include.h" + +namespace kuzu { + +class PythonCachedItem { +public: + explicit PythonCachedItem(const std::string& name, PythonCachedItem* parent = nullptr) + : name(name), parent(parent), loaded(false) {} + virtual ~PythonCachedItem() = default; + + bool isLoaded() const {return loaded;} + py::handle operator()(); + +private: + std::string name; + PythonCachedItem* parent; + bool loaded; + py::handle object; +}; + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/include/cached_import/py_cached_modules.h b/tools/python_api/src_cpp/include/cached_import/py_cached_modules.h new file mode 100644 index 00000000000..28146a0cba6 --- /dev/null +++ b/tools/python_api/src_cpp/include/cached_import/py_cached_modules.h @@ -0,0 +1,130 @@ +#pragma once + +#include "py_cached_item.h" + +namespace kuzu { + +class DateTimeCachedItem : public PythonCachedItem { + +public: + DateTimeCachedItem() : PythonCachedItem("datetime"), date("date", this), + datetime("datetime", this), timedelta("timedelta", this) {} + + PythonCachedItem date; + PythonCachedItem datetime; + PythonCachedItem timedelta; +}; + +class DecimalCachedItem : public PythonCachedItem { + +public: + DecimalCachedItem() : PythonCachedItem("decimal"), Decimal("Decimal", this) {} + + PythonCachedItem Decimal; +}; + +class InspectCachedItem : public PythonCachedItem { + +public: + InspectCachedItem() : PythonCachedItem("inspect"), currentframe("currentframe", this) {} + + PythonCachedItem currentframe; +}; + +class NumpyMaCachedItem : public PythonCachedItem { + +public: + NumpyMaCachedItem() : PythonCachedItem("numpy.ma"), masked_array("masked_array", this) {} + + PythonCachedItem masked_array; +}; + +class PandasCachedItem : public PythonCachedItem { + + class SeriesCachedItem : public PythonCachedItem { + public: + explicit SeriesCachedItem(PythonCachedItem* parent): PythonCachedItem("series", parent), + Series("Series", this) {} + + PythonCachedItem Series; + }; + + class CoreCachedItem : public PythonCachedItem { + public: + explicit CoreCachedItem(PythonCachedItem* parent): PythonCachedItem("core", parent), + series(this) {} + + SeriesCachedItem series; + }; + + class DataFrameCachedItem : public PythonCachedItem { + public: + explicit DataFrameCachedItem(PythonCachedItem* parent): PythonCachedItem("DataFrame", parent), + from_dict("from_dict", this) {} + + PythonCachedItem from_dict; + }; + +public: + PandasCachedItem() : PythonCachedItem("pandas"), ArrowDtype("ArrowDtype", this), core(this), DataFrame(this), + NA("NA", this), NaT("NaT", this) {} + + PythonCachedItem ArrowDtype; + CoreCachedItem core; + DataFrameCachedItem DataFrame; + PythonCachedItem NA; + PythonCachedItem NaT; +}; + +class PyarrowCachedItem : public PythonCachedItem { + + class RecordBatchCachedItem : public PythonCachedItem { + public: + explicit RecordBatchCachedItem(PythonCachedItem* parent): PythonCachedItem("RecordBatch", parent), + _import_from_c("_import_from_c", this) {} + + PythonCachedItem _import_from_c; + }; + + class SchemaCachedItem : public PythonCachedItem { + public: + explicit SchemaCachedItem(PythonCachedItem* parent): PythonCachedItem("Schema", parent), + _import_from_c("_import_from_c", this) {} + + PythonCachedItem _import_from_c; + }; + + class TableCachedItem : public PythonCachedItem { + public: + explicit TableCachedItem(PythonCachedItem* parent): PythonCachedItem("Table", parent), + from_batches("from_batches", this), from_pandas("from_pandas", this) {} + + PythonCachedItem from_batches; + PythonCachedItem from_pandas; + }; + + class LibCachedItem : public PythonCachedItem { + public: + explicit LibCachedItem(PythonCachedItem* parent): PythonCachedItem("lib", parent), + RecordBatch(this), Schema(this), Table(this) {} + + RecordBatchCachedItem RecordBatch; + SchemaCachedItem Schema; + TableCachedItem Table; + }; + +public: + PyarrowCachedItem(): PythonCachedItem("pyarrow"), lib(this) {} + + LibCachedItem lib; +}; + +class UUIDCachedItem : public PythonCachedItem { + +public: + UUIDCachedItem() : PythonCachedItem("uuid"), UUID("UUID", this) {} + + PythonCachedItem UUID; +}; + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/include/pandas/pandas_scan.h b/tools/python_api/src_cpp/include/pandas/pandas_scan.h index 24546bfd8d6..7c36db5f1d9 100644 --- a/tools/python_api/src_cpp/include/pandas/pandas_scan.h +++ b/tools/python_api/src_cpp/include/pandas/pandas_scan.h @@ -17,32 +17,18 @@ struct PandasScanLocalState : public function::TableFuncLocalState { }; struct PandasScanSharedState : public function::BaseScanSharedState { - explicit PandasScanSharedState(uint64_t numRows) : BaseScanSharedState{numRows}, position{0} {} + explicit PandasScanSharedState(uint64_t numRows) + : BaseScanSharedState{numRows}, position{0}, numReadRows{0} {} std::mutex lock; uint64_t position; + uint64_t numReadRows; }; struct PandasScanFunction { + static constexpr const char* name = "READ_PANDAS"; + static function::function_set getFunctionSet(); - - static common::offset_t tableFunc(function::TableFuncInput& input, function::TableFuncOutput& output); - - static std::unique_ptr bindFunc(main::ClientContext* /*context*/, - function::TableFuncBindInput* input); - - static std::unique_ptr initSharedState( - function::TableFunctionInitInput& input); - - static std::unique_ptr initLocalState( - function::TableFunctionInitInput& input, function::TableFuncSharedState* state, - storage::MemoryManager* /*mm*/); - - static bool sharedStateNext(const function::TableFuncBindData* bindData, - PandasScanLocalState* localState, function::TableFuncSharedState* sharedState); - - static void pandasBackendScanSwitch(PandasColumnBindData* bindData, uint64_t count, - uint64_t offset, common::ValueVector* outputVector); }; struct PandasScanFunctionData : public function::TableFuncBindData { @@ -69,6 +55,6 @@ struct PandasScanFunctionData : public function::TableFuncBindData { } }; -std::unique_ptr replacePD(common::Value* value); +std::unique_ptr replacePD(const std::string& objectName); } // namespace kuzu diff --git a/tools/python_api/src_cpp/include/py_database.h b/tools/python_api/src_cpp/include/py_database.h index 2e65ec9e56c..0cc9265e9c5 100644 --- a/tools/python_api/src_cpp/include/py_database.h +++ b/tools/python_api/src_cpp/include/py_database.h @@ -2,6 +2,7 @@ #include "main/kuzu.h" #include "main/storage_driver.h" +#include "cached_import/py_cached_import.h" #include "pybind_include.h" // IWYU pragma: keep (used for py:: namespace) #define PYBIND11_DETAILED_ERROR_MESSAGES using namespace kuzu::main; @@ -23,7 +24,7 @@ class PyDatabase { explicit PyDatabase(const std::string& databasePath, uint64_t bufferPoolSize, uint64_t maxNumThreads, bool compression, bool readOnly, uint64_t maxDBSize); - ~PyDatabase() = default; + ~PyDatabase(); template void scanNodeTable(const std::string& tableName, const std::string& propName, diff --git a/tools/python_api/src_cpp/include/pyarrow/pyarrow_bind.h b/tools/python_api/src_cpp/include/pyarrow/pyarrow_bind.h new file mode 100644 index 00000000000..98f64e240a0 --- /dev/null +++ b/tools/python_api/src_cpp/include/pyarrow/pyarrow_bind.h @@ -0,0 +1,18 @@ +#pragma once + +#include "common/arrow/arrow_converter.h" +#include "py_object_container.h" +#include "pybind_include.h" + +namespace kuzu { + +namespace main { +class ClientContext; +} + +struct Pyarrow { + static std::shared_ptr bind(py::handle tableToBind, + std::vector& returnTypes, std::vector& names); +}; + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/include/pyarrow/pyarrow_scan.h b/tools/python_api/src_cpp/include/pyarrow/pyarrow_scan.h new file mode 100644 index 00000000000..4f477cfc91c --- /dev/null +++ b/tools/python_api/src_cpp/include/pyarrow/pyarrow_scan.h @@ -0,0 +1,60 @@ +#pragma once + +#include "common/arrow/arrow.h" +#include "function/scalar_function.h" +#include "function/table/bind_data.h" +#include "function/table/scan_functions.h" +#include "function/table_functions.h" +#include "pyarrow_bind.h" +#include "pybind_include.h" + +namespace kuzu { + +struct PyArrowTableScanLocalState final : public function::TableFuncLocalState { + ArrowArrayWrapper* arrowArray; + + explicit PyArrowTableScanLocalState(ArrowArrayWrapper* arrowArray) : arrowArray{arrowArray} {} +}; + +struct PyArrowTableScanSharedState final : public function::BaseScanSharedState { + std::vector> chunks; + uint64_t currentChunk; + std::mutex lock; + + PyArrowTableScanSharedState( + uint64_t numRows, std::vector> chunks) + : BaseScanSharedState{numRows}, chunks{std::move(chunks)}, currentChunk{0} {} + + ArrowArrayWrapper* getNextChunk(); +}; + +struct PyArrowTableScanFunctionData final : public function::TableFuncBindData { + std::shared_ptr schema; + std::vector> arrowArrayBatches; + uint64_t numRows; + + PyArrowTableScanFunctionData(std::vector columnTypes, + std::shared_ptr schema, std::vector columnNames, + std::vector> arrowArrayBatches, uint64_t numRows) + : TableFuncBindData{std::move(columnTypes), std::move(columnNames)}, + schema{std::move(schema)}, arrowArrayBatches{arrowArrayBatches}, numRows{numRows} {} + + ~PyArrowTableScanFunctionData() override {} + + std::unique_ptr copy() const override { + py::gil_scoped_acquire acquire; + // the schema is considered immutable so copying it by copying the shared_ptr is fine. + return std::make_unique( + columnTypes, schema, columnNames, arrowArrayBatches, numRows); + } +}; + +struct PyArrowTableScanFunction { + static constexpr const char* name = "READ_PYARROW"; + + static function::function_set getFunctionSet(); + + static function::TableFunction getFunction(); +}; + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/kuzu_binding.cpp b/tools/python_api/src_cpp/kuzu_binding.cpp index b3f8581e17d..69a51a4dfc4 100644 --- a/tools/python_api/src_cpp/kuzu_binding.cpp +++ b/tools/python_api/src_cpp/kuzu_binding.cpp @@ -1,3 +1,4 @@ +#include "include/cached_import/py_cached_import.h" #include "include/py_connection.h" #include "include/py_database.h" #include "include/py_prepared_statement.h" @@ -8,6 +9,10 @@ void bind(py::module& m) { PyConnection::initialize(m); PyPreparedStatement::initialize(m); PyQueryResult::initialize(m); + auto cleanImportCache = []() { + kuzu::importCache.reset(); + }; + m.add_object("_clean_import_cache", py::capsule(cleanImportCache)); } PYBIND11_MODULE(_kuzu, m) { diff --git a/tools/python_api/src_cpp/pandas/pandas_analyzer.cpp b/tools/python_api/src_cpp/pandas/pandas_analyzer.cpp index 5fd2af3d43f..0e8a35b3c66 100644 --- a/tools/python_api/src_cpp/pandas/pandas_analyzer.cpp +++ b/tools/python_api/src_cpp/pandas/pandas_analyzer.cpp @@ -1,6 +1,7 @@ #include "pandas/pandas_analyzer.h" #include "function/built_in_function_utils.h" +#include "cached_import/py_cached_import.h" #include "py_conversion.h" namespace kuzu { @@ -10,14 +11,14 @@ static bool upgradeType(common::LogicalType& left, const common::LogicalType& ri return true; } if (left.getLogicalTypeID() == common::LogicalTypeID::ANY || - ((left.getLogicalTypeID() == common::LogicalTypeID::VAR_LIST) && - (common::VarListType::getChildType(&left)->getLogicalTypeID() == + ((left.getLogicalTypeID() == common::LogicalTypeID::LIST) && + (common::ListType::getChildType(&left)->getLogicalTypeID() == common::LogicalTypeID::ANY))) { left = right; return true; } - if (((right.getLogicalTypeID() == common::LogicalTypeID::VAR_LIST) && - (common::VarListType::getChildType(&right)->getLogicalTypeID() == + if (((right.getLogicalTypeID() == common::LogicalTypeID::LIST) && + (common::ListType::getChildType(&right)->getLogicalTypeID() == common::LogicalTypeID::ANY))) { return true; } @@ -37,7 +38,7 @@ common::LogicalType PandasAnalyzer::getListType(py::object& ele, bool& canConver for (auto pyVal : ele) { auto object = py::reinterpret_borrow(pyVal); auto itemType = getItemType(object, canConvert); - if (i != 0) { + if (i == 0) { listType = itemType; } else { if (!upgradeType(listType, itemType)) { @@ -70,7 +71,7 @@ common::LogicalType PandasAnalyzer::getItemType(py::object ele, bool& canConvert case PythonObjectType::String: return *common::LogicalType::STRING(); case PythonObjectType::List: - return *common::LogicalType::VAR_LIST(getListType(ele, canConvert)); + return *common::LogicalType::LIST(getListType(ele, canConvert)); default: KU_UNREACHABLE; } @@ -88,8 +89,8 @@ static py::object findFirstNonNull(const py::handle& row, uint64_t numRows) { common::LogicalType PandasAnalyzer::innerAnalyze(py::object column, bool& canConvert) { auto numRows = py::len(column); - auto pandasModule = py::module::import("pandas"); - auto pandasSeries = pandasModule.attr("core").attr("series").attr("Series"); + auto pandasModule = importCache->pandas; + auto pandasSeries = pandasModule.core.series.Series(); if (py::isinstance(column, pandasSeries)) { column = column.attr("__array__")(); diff --git a/tools/python_api/src_cpp/pandas/pandas_scan.cpp b/tools/python_api/src_cpp/pandas/pandas_scan.cpp index a8027245bc5..d43b37678c8 100644 --- a/tools/python_api/src_cpp/pandas/pandas_scan.cpp +++ b/tools/python_api/src_cpp/pandas/pandas_scan.cpp @@ -1,9 +1,12 @@ #include "pandas/pandas_scan.h" +#include "pyarrow/pyarrow_scan.h" #include "function/table/bind_input.h" +#include "cached_import/py_cached_import.h" #include "numpy/numpy_scan.h" #include "py_connection.h" #include "pybind11/pytypes.h" +#include "binder/expression/function_expression.h" using namespace kuzu::function; using namespace kuzu::common; @@ -11,15 +14,7 @@ using namespace kuzu::catalog; namespace kuzu { -function_set PandasScanFunction::getFunctionSet() { - function_set functionSet; - functionSet.push_back( - std::make_unique(READ_PANDAS_FUNC_NAME, tableFunc, bindFunc, initSharedState, - initLocalState, std::vector{LogicalTypeID::POINTER})); - return functionSet; -} - -std::unique_ptr PandasScanFunction::bindFunc( +std::unique_ptr bindFunc( main::ClientContext* /*context*/, TableFuncBindInput* input) { py::gil_scoped_acquire acquire; py::handle df(reinterpret_cast(input->inputs[0].getValue())); @@ -38,9 +33,9 @@ std::unique_ptr PandasScanFunction::bindFunc( std::move(returnTypes), std::move(names), df, numRows, std::move(columnBindData)); } -bool PandasScanFunction::sharedStateNext(const TableFuncBindData* /*bindData*/, - PandasScanLocalState* localState, function::TableFuncSharedState* sharedState) { - auto pandasSharedState = reinterpret_cast(sharedState); +bool sharedStateNext(const TableFuncBindData* /*bindData*/, + PandasScanLocalState* localState, TableFuncSharedState* sharedState) { + auto pandasSharedState = ku_dynamic_cast(sharedState); std::lock_guard lck{pandasSharedState->lock}; if (pandasSharedState->position >= pandasSharedState->numRows) { return false; @@ -53,7 +48,7 @@ bool PandasScanFunction::sharedStateNext(const TableFuncBindData* /*bindData*/, return true; } -std::unique_ptr PandasScanFunction::initLocalState( +std::unique_ptr initLocalState( function::TableFunctionInitInput& input, function::TableFuncSharedState* sharedState, storage::MemoryManager* /*mm*/) { auto localState = std::make_unique(0 /* start */, 0 /* end */); @@ -61,18 +56,18 @@ std::unique_ptr PandasScanFunction::initLocalStat return localState; } -std::unique_ptr PandasScanFunction::initSharedState( +std::unique_ptr initSharedState( function::TableFunctionInitInput& input) { // LCOV_EXCL_START if (PyGILState_Check()) { - throw common::RuntimeException("PandasScan called but GIL was already held!"); + throw RuntimeException("PandasScan called but GIL was already held!"); } // LCOV_EXCL_STOP - auto scanBindData = reinterpret_cast(input.bindData); + auto scanBindData = ku_dynamic_cast(input.bindData); return std::make_unique(scanBindData->numRows); } -void PandasScanFunction::pandasBackendScanSwitch( +void pandasBackendScanSwitch( PandasColumnBindData* bindData, uint64_t count, uint64_t offset, ValueVector* outputVector) { auto backend = bindData->pandasCol->getBackEnd(); switch (backend) { @@ -84,10 +79,11 @@ void PandasScanFunction::pandasBackendScanSwitch( } } -common::offset_t PandasScanFunction::tableFunc( - function::TableFuncInput& input, function::TableFuncOutput& output) { - auto pandasScanData = reinterpret_cast(input.bindData); - auto pandasLocalState = reinterpret_cast(input.localState); +offset_t tableFunc( + TableFuncInput& input, TableFuncOutput& output) { + auto pandasScanData = ku_dynamic_cast(input.bindData); + auto pandasLocalState = ku_dynamic_cast(input.localState); + auto pandasSharedState = ku_dynamic_cast(input.sharedState); if (pandasLocalState->start >= pandasLocalState->end) { if (!sharedStateNext(input.bindData, pandasLocalState, input.sharedState)) { @@ -102,6 +98,7 @@ common::offset_t PandasScanFunction::tableFunc( } output.dataChunk.state->selVector->selectedSize = numValuesToOutput; pandasLocalState->start += numValuesToOutput; + pandasSharedState->numReadRows += numValuesToOutput; return numValuesToOutput; } @@ -114,23 +111,67 @@ std::vector> PandasScanFunctionData::copyC return result; } -std::unique_ptr tryReplacePD(py::dict& dict, py::str& tableName) { - if (!dict.contains(tableName)) { +static double progressFunc(TableFuncSharedState* sharedState) { + auto pandasSharedState = ku_dynamic_cast(sharedState); + if (pandasSharedState->numRows == 0) { + return 0.0; + } + return static_cast(pandasSharedState->numReadRows) / + pandasSharedState->numRows; +} + +static TableFunction getFunction() { + return TableFunction(PandasScanFunction::name, tableFunc, bindFunc, initSharedState, + initLocalState, progressFunc, std::vector{LogicalTypeID::POINTER}); +} + +function_set PandasScanFunction::getFunctionSet() { + function_set functionSet; + functionSet.push_back(getFunction().copy()); + return functionSet; +} + +static bool isPyArrowBacked(const py::handle &df) { + py::list dtypes = df.attr("dtypes"); + if (dtypes.empty()) { + return false; + } + + auto arrow_dtype = importCache->pandas.ArrowDtype(); + for (auto &dtype : dtypes) { + if (py::isinstance(dtype, arrow_dtype)) { + return true; + } + } + return false; +} + +static std::unique_ptr tryReplacePD(py::dict& dict, py::str& objectName) { + if (!dict.contains(objectName)) { return nullptr; } - auto entry = dict[tableName]; + auto entry = dict[objectName]; if (PyConnection::isPandasDataframe(entry)) { - return Value::createValue(reinterpret_cast(entry.ptr())).copy(); + auto scanReplacementData = std::make_unique(); + if (isPyArrowBacked(entry)) { + scanReplacementData->func = PyArrowTableScanFunction::getFunction(); + } else { + scanReplacementData->func = getFunction(); + } + auto bindInput = TableFuncBindInput(); + bindInput.inputs.push_back(Value::createValue(reinterpret_cast(entry.ptr()))); + scanReplacementData->bindInput = std::move(bindInput); + return scanReplacementData; } else { throw RuntimeException{"Only pandas dataframe is supported."}; } } -std::unique_ptr replacePD(common::Value* value) { +std::unique_ptr replacePD(const std::string& objectName) { py::gil_scoped_acquire acquire; - auto pyTableName = py::str(value->getValue()); + auto pyTableName = py::str(objectName); // Here we do an exhaustive search on the frame lineage. - auto currentFrame = py::module::import("inspect").attr("currentframe")(); + auto currentFrame = importCache->inspect.currentframe()(); while (hasattr(currentFrame, "f_locals")) { auto localDict = py::reinterpret_borrow(currentFrame.attr("f_locals")); if (localDict) { diff --git a/tools/python_api/src_cpp/py_connection.cpp b/tools/python_api/src_cpp/py_connection.cpp index 8ddef71b33f..b98c7bac3aa 100644 --- a/tools/python_api/src_cpp/py_connection.cpp +++ b/tools/python_api/src_cpp/py_connection.cpp @@ -2,14 +2,18 @@ #include +#include "common/constants.h" +#include "cached_import/py_cached_import.h" #include "common/string_format.h" +#include "common/types/uuid.h" #include "datetime.h" // from Python +#include "function/built_in_function_utils.h" #include "main/connection.h" #include "pandas/pandas_scan.h" #include "processor/result/factorized_table.h" -#include "common/types/uuid.h" using namespace kuzu::common; +using namespace kuzu; void PyConnection::initialize(py::handle& m) { py::class_(m, "Connection") @@ -31,8 +35,7 @@ void PyConnection::initialize(py::handle& m) { PyConnection::PyConnection(PyDatabase* pyDatabase, uint64_t numThreads) { storageDriver = std::make_unique(pyDatabase->database.get()); conn = std::make_unique(pyDatabase->database.get()); - // TODO(Xiyang): We should implement a generic replacement framework in binder. - conn->setReplaceFunc(kuzu::replacePD); + conn->getClientContext()->addScanReplace(function::ScanReplacement(kuzu::replacePD)); if (numThreads > 0) { conn->setMaxNumThreadForExec(numThreads); } @@ -151,21 +154,19 @@ void PyConnection::getAllEdgesForTorchGeometric(py::array_t& npArray, } bool PyConnection::isPandasDataframe(const py::object& object) { - // TODO(Ziyi): introduce PythonCachedImport to avoid unnecessary import. - py::module pandas = py::module::import("pandas"); - return py::isinstance(object, pandas.attr("DataFrame")); + return py::isinstance(object, importCache->pandas.DataFrame()); } static Value transformPythonValue(py::handle val); -std::unordered_map> transformPythonParameters( +static std::unordered_map> transformPythonParameters( const py::dict& params, Connection* conn) { std::unordered_map> result; for (auto& [key, value] : params) { if (!py::isinstance(key)) { // TODO(Chang): remove ROLLBACK once we can guarantee database is deleted after conn conn->query("ROLLBACK"); - throw std::runtime_error("Parameter name must be of type string but get " + + throw std::runtime_error("Parameter name must be of type string but got " + py::str(key.get_type()).cast()); } auto name = key.cast(); @@ -175,21 +176,136 @@ std::unordered_map> transformPythonParameter return result; } -Value transformPythonValue(py::handle val) { - auto datetime_mod = py::module::import("datetime"); - auto datetime_datetime = datetime_mod.attr("datetime"); - auto time_delta = datetime_mod.attr("timedelta"); - auto datetime_date = datetime_mod.attr("date"); - auto uuid = py::module::import("uuid").attr("UUID"); - if (py::isinstance(val)) { - return Value::createValue(val.cast()); +static bool canCastPyLogicalType(const LogicalType& from, const LogicalType& to) { + // the input of this function is restricted to the output of pyLogicalType + if (from.getLogicalTypeID() == LogicalTypeID::ANY || + from.getLogicalTypeID() == to.getLogicalTypeID()) { + return true; + } else if (to.getLogicalTypeID() == LogicalTypeID::ANY) { + return false; + } else if (from.getLogicalTypeID() == LogicalTypeID::MAP) { + if (to.getLogicalTypeID() != LogicalTypeID::MAP) { + return false; + } + auto fromKeyType = MapType::getKeyType(&from), fromValueType = MapType::getValueType(&to); + auto toKeyType = MapType::getKeyType(&to), toValueType = MapType::getValueType(&to); + return + (canCastPyLogicalType(*fromKeyType, *toKeyType) || + canCastPyLogicalType(*toKeyType, *fromKeyType)) && + (canCastPyLogicalType(*fromValueType, *toValueType) || + canCastPyLogicalType(*toValueType, *fromValueType)); + } else if (from.getLogicalTypeID() == LogicalTypeID::LIST) { + if (to.getLogicalTypeID() != LogicalTypeID::LIST) { + return false; + } + return canCastPyLogicalType( + *ListType::getChildType(&from), *ListType::getChildType(&to)); + } else { + auto castCost = function::BuiltInFunctionsUtils::getCastCost( + from.getLogicalTypeID(), to.getLogicalTypeID()); + return castCost != UNDEFINED_CAST_COST; + } + return false; +} + +static void tryConvertPyLogicalType(LogicalType& from, LogicalType& to); + +static std::unique_ptr castPyLogicalType(const LogicalType& from, const LogicalType& to) { + // assumes from can cast to to + if (from.getLogicalTypeID() == LogicalTypeID::MAP) { + auto fromKeyType = MapType::getKeyType(&from), fromValueType = MapType::getValueType(&from); + auto toKeyType = MapType::getKeyType(&to), toValueType = MapType::getValueType(&to); + auto outputKeyType = canCastPyLogicalType(*fromKeyType, *toKeyType) ? + castPyLogicalType(*fromKeyType, *toKeyType) : castPyLogicalType(*toKeyType, *fromKeyType); + auto outputValueType = canCastPyLogicalType(*fromValueType, *toValueType) ? + castPyLogicalType(*fromValueType, *toValueType) : castPyLogicalType(*toValueType, *fromValueType); + return LogicalType::MAP(std::move(outputKeyType), std::move(outputValueType)); + } + return std::make_unique(to); +} + +void tryConvertPyLogicalType(LogicalType& from, LogicalType& to) { + if (canCastPyLogicalType(from, to)) { + from = *castPyLogicalType(from, to); + } else if (canCastPyLogicalType(to, from)) { + to = *castPyLogicalType(to, from); + } else { + throw RuntimeException(stringFormat( + "Cannot convert Python object to Kuzu value : {} is incompatible with {}", + from.toString(), to.toString())); + } +} + +static std::unique_ptr pyLogicalType(py::handle val) { + auto datetime_datetime = importCache->datetime.datetime(); + auto time_delta = importCache->datetime.timedelta(); + auto datetime_date = importCache->datetime.date(); + auto uuid = importCache->uuid.UUID(); + if (val.is_none()) { + return LogicalType::ANY(); + } else if (py::isinstance(val)) { + return LogicalType::BOOL(); } else if (py::isinstance(val)) { - return Value::createValue(val.cast()); + return LogicalType::INT64(); } else if (py::isinstance(val)) { - return Value::createValue(val.cast()); + return LogicalType::DOUBLE(); } else if (py::isinstance(val)) { - return Value::createValue(val.cast()); + return LogicalType::STRING(); } else if (py::isinstance(val, datetime_datetime)) { + return LogicalType::TIMESTAMP(); + } else if (py::isinstance(val, datetime_date)) { + return LogicalType::DATE(); + } else if (py::isinstance(val, time_delta)) { + return LogicalType::INTERVAL(); + } else if (py::isinstance(val, uuid)) { + return LogicalType::UUID(); + } else if (py::isinstance(val)) { + py::list lst = py::reinterpret_borrow(val); + auto childType = LogicalType::ANY(); + for (auto child : lst) { + auto curChildType = pyLogicalType(child); + tryConvertPyLogicalType(*childType, *curChildType); + } + return LogicalType::LIST(std::move(childType)); + } else if (py::isinstance(val)) { + py::dict dict = py::reinterpret_borrow(val); + auto childKeyType = LogicalType::ANY(), childValueType = LogicalType::ANY(); + for (auto child : dict) { + auto curChildKeyType = pyLogicalType(child.first), + curChildValueType = pyLogicalType(child.second); + tryConvertPyLogicalType(*childKeyType, *curChildKeyType); + tryConvertPyLogicalType(*childValueType, *curChildValueType); + } + return LogicalType::MAP(std::move(childKeyType), std::move(childValueType)); + } else { + // LCOV_EXCL_START + throw common::RuntimeException( + "Unknown parameter type " + py::str(val.get_type()).cast()); + // LCOV_EXCL_STOP + } +} + +static Value transformPythonValueAs(py::handle val, const LogicalType* type) { + // ignore the type of the actual python object, just directly cast + if (val.is_none()) { + return Value::createNullValue(*type); + } + switch (type->getLogicalTypeID()) { + case LogicalTypeID::ANY: + return Value::createNullValue(); + case LogicalTypeID::BOOL: + return Value::createValue(val.cast()); + case LogicalTypeID::INT64: + return Value::createValue(val.cast()); + case LogicalTypeID::DOUBLE: + return Value::createValue(val.cast()); + case LogicalTypeID::STRING: + if (py::isinstance(val)) { + return Value::createValue(val.cast()); + } else { + return Value::createValue(py::str(val)); + } + case LogicalTypeID::TIMESTAMP: { auto ptr = val.ptr(); auto year = PyDateTime_GET_YEAR(ptr); auto month = PyDateTime_GET_MONTH(ptr); @@ -201,13 +317,15 @@ Value transformPythonValue(py::handle val) { auto date = Date::fromDate(year, month, day); auto time = Time::fromTime(hour, minute, second, micros); return Value::createValue(Timestamp::fromDateTime(date, time)); - } else if (py::isinstance(val, datetime_date)) { + } + case LogicalTypeID::DATE: { auto ptr = val.ptr(); auto year = PyDateTime_GET_YEAR(ptr); auto month = PyDateTime_GET_MONTH(ptr); auto day = PyDateTime_GET_DAY(ptr); return Value::createValue(Date::fromDate(year, month, day)); - } else if (py::isinstance(val, time_delta)) { + } + case LogicalTypeID::INTERVAL: { auto ptr = val.ptr(); auto days = PyDateTime_DELTA_GET_DAYS(ptr); auto seconds = PyDateTime_DELTA_GET_SECONDS(ptr); @@ -217,14 +335,53 @@ Value transformPythonValue(py::handle val) { Interval::addition(interval, seconds, "seconds"); Interval::addition(interval, microseconds, "microseconds"); return Value::createValue(interval); - } else if (py::isinstance(val, uuid)) { + } + case LogicalTypeID::UUID: { auto strVal = py::str(val).cast(); auto uuidVal = UUID::fromString(strVal); ku_uuid_t uuidToAppend; uuidToAppend.value = uuidVal; return Value{uuidToAppend}; - } else { - throw std::runtime_error( - "Unknown parameter type " + py::str(val.get_type()).cast()); } + case LogicalTypeID::LIST: { + py::list lst = py::reinterpret_borrow(val); + std::vector> children; + for (auto child : lst) { + children.push_back(std::make_unique( + transformPythonValueAs(child, ListType::getChildType(type)))); + } + return Value(std::make_unique(*type), std::move(children)); + } + case LogicalTypeID::MAP: { + py::dict dict = py::reinterpret_borrow(val); + std::vector> children; + auto childKeyType = MapType::getKeyType(type), + childValueType = MapType::getValueType(type); + for (auto child : dict) { + // type construction is inefficient, we have to create duplicates because it asks for + // a unique ptr + std::vector fields; + fields.emplace_back( + InternalKeyword::MAP_KEY, std::make_unique(*childKeyType)); + fields.emplace_back( + InternalKeyword::MAP_VALUE, std::make_unique(*childValueType)); + std::vector> structValues; + structValues.push_back(std::make_unique(transformPythonValueAs(child.first, childKeyType))); + structValues.push_back(std::make_unique(transformPythonValueAs(child.second, childValueType))); + children.push_back(std::make_unique( + LogicalType::STRUCT(std::move(fields)), + std::move(structValues))); + } + return Value(std::make_unique(*type), std::move(children)); + } + // LCOV_EXCL_START + default: + KU_UNREACHABLE; + // LCOV_EXCL_STOP + } +} + +Value transformPythonValue(py::handle val) { + auto type = pyLogicalType(val); + return transformPythonValueAs(val, type.get()); } diff --git a/tools/python_api/src_cpp/py_conversion.cpp b/tools/python_api/src_cpp/py_conversion.cpp index d194a4b86cf..bad439c29d0 100644 --- a/tools/python_api/src_cpp/py_conversion.cpp +++ b/tools/python_api/src_cpp/py_conversion.cpp @@ -1,18 +1,18 @@ #include "py_conversion.h" #include "common/type_utils.h" +#include "cached_import/py_cached_import.h" namespace kuzu { using namespace kuzu::common; +using kuzu::importCache; PythonObjectType getPythonObjectType(py::handle& ele) { - py::object pandas = py::module::import("pandas"); - auto pandasNa = pandas.attr("NA"); - auto pandasNat = pandas.attr("NaT"); - py::object datetime = py::module::import("datetime"); - auto pyDateTime = datetime.attr("datetime"); - auto pyDate = datetime.attr("date"); + auto pandasNa = importCache->pandas.NA(); + auto pyDateTime = importCache->datetime.datetime(); + auto pandasNat = importCache->pandas.NaT(); + auto pyDate = importCache->datetime.date(); if (ele.is_none() || ele.is(pandasNa) || ele.is(pandasNat)) { return PythonObjectType::None; } else if (py::isinstance(ele)) { diff --git a/tools/python_api/src_cpp/py_database.cpp b/tools/python_api/src_cpp/py_database.cpp index 0ed4c234fd3..b99a5968b71 100644 --- a/tools/python_api/src_cpp/py_database.cpp +++ b/tools/python_api/src_cpp/py_database.cpp @@ -1,5 +1,9 @@ #include "include/py_database.h" +#include "include/cached_import/py_cached_import.h" +#include "pandas/pandas_scan.h" +#include "pyarrow/pyarrow_scan.h" + #include #include "main/version.h" @@ -46,10 +50,16 @@ PyDatabase::PyDatabase(const std::string& databasePath, uint64_t bufferPoolSize, auto systemConfig = SystemConfig(bufferPoolSize, maxNumThreads, compression, readOnly, maxDBSize); database = std::make_unique(databasePath, systemConfig); - database->addBuiltInFunction(READ_PANDAS_FUNC_NAME, kuzu::PandasScanFunction::getFunctionSet()); + database->addBuiltInFunction(kuzu::PandasScanFunction::name, kuzu::PandasScanFunction::getFunctionSet()); storageDriver = std::make_unique(database.get()); + py::gil_scoped_acquire acquire; + if (kuzu::importCache.get() == nullptr) { + kuzu::importCache = std::make_shared(); + } } +PyDatabase::~PyDatabase() {} + template void PyDatabase::scanNodeTable(const std::string& tableName, const std::string& propName, const py::array_t& indices, py::array_t& result, int numThreads) { diff --git a/tools/python_api/src_cpp/py_query_result.cpp b/tools/python_api/src_cpp/py_query_result.cpp index a0c1edf388a..6a8446e4bfa 100644 --- a/tools/python_api/src_cpp/py_query_result.cpp +++ b/tools/python_api/src_cpp/py_query_result.cpp @@ -9,9 +9,11 @@ #include "common/types/value/node.h" #include "common/types/value/rel.h" #include "datetime.h" // python lib +#include "cached_import/py_cached_import.h" #include "include/py_query_result_converter.h" using namespace kuzu::common; +using kuzu::importCache; #define PyDateTimeTZ_FromDateAndTime(year, month, day, hour, min, sec, usec, timezone) \ PyDateTimeAPI->DateTime_FromDateAndTime( \ @@ -125,8 +127,7 @@ py::object convertRdfVariantToPyObject(const Value& value) { case LogicalTypeID::INTERVAL: { auto intervalVal = RdfVariant::getValue(&value); auto days = Interval::DAYS_PER_MONTH * intervalVal.months + intervalVal.days; - return py::cast(py::module::import("datetime") - .attr("timedelta")(py::arg("days") = days, + return py::cast(importCache->datetime.timedelta()(py::arg("days") = days, py::arg("microseconds") = intervalVal.micros)); } default: { @@ -172,7 +173,8 @@ py::object PyQueryResult::convertValueToPyObject(const Value& value) { case LogicalTypeID::INT128: { kuzu::common::int128_t result = value.getValue(); std::string int128_string = kuzu::common::Int128_t::ToString(result); - py::object Decimal = py::module_::import("decimal").attr("Decimal"); + + auto Decimal = importCache->decimal.Decimal(); py::object largeInt = Decimal(int128_string); return largeInt; } @@ -193,7 +195,7 @@ py::object PyQueryResult::convertValueToPyObject(const Value& value) { case LogicalTypeID::UUID: { kuzu::common::int128_t result = value.getValue(); std::string uuidString = kuzu::common::UUID::toString(result); - py::object UUID = py::module_::import("uuid").attr("UUID"); + auto UUID = importCache->uuid.UUID(); return UUID(uuidString); } case LogicalTypeID::DATE: { @@ -236,12 +238,12 @@ py::object PyQueryResult::convertValueToPyObject(const Value& value) { case LogicalTypeID::INTERVAL: { auto intervalVal = value.getValue(); auto days = Interval::DAYS_PER_MONTH * intervalVal.months + intervalVal.days; - return py::cast(py::module::import("datetime") - .attr("timedelta")(py::arg("days") = days, + + return py::cast(importCache->datetime.timedelta()(py::arg("days") = days, py::arg("microseconds") = intervalVal.micros)); } - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: { + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: { py::list list; for (auto i = 0u; i < NestedVal::getChildrenSize(&value); ++i) { list.append(convertValueToPyObject(*NestedVal::getChildVal(&value, i))); @@ -331,9 +333,9 @@ bool PyQueryResult::getNextArrowChunk(const std::vectorpyarrow.lib.RecordBatch._import_from_c(); + auto schema = ArrowConverter::toArrowSchema(typesInfo); batches.append(batchImportFunc((std::uint64_t)&data, (std::uint64_t)schema.get())); return true; @@ -341,22 +343,19 @@ bool PyQueryResult::getNextArrowChunk(const std::vector>& typesInfo, std::int64_t chunkSize) { - auto pyarrowLibModule = py::module::import("pyarrow").attr("lib"); py::list batches; while (getNextArrowChunk(typesInfo, batches, chunkSize)) {} return batches; } kuzu::pyarrow::Table PyQueryResult::getAsArrow(std::int64_t chunkSize) { - py::gil_scoped_acquire acquire; - - auto pyarrowLibModule = py::module::import("pyarrow").attr("lib"); - auto fromBatchesFunc = pyarrowLibModule.attr("Table").attr("from_batches"); - auto schemaImportFunc = pyarrowLibModule.attr("Schema").attr("_import_from_c"); auto typesInfo = queryResult->getColumnTypesInfo(); py::list batches = getArrowChunks(typesInfo, chunkSize); auto schema = ArrowConverter::toArrowSchema(typesInfo); + + auto fromBatchesFunc = importCache->pyarrow.lib.Table.from_batches(); + auto schemaImportFunc = importCache->pyarrow.lib.Schema._import_from_c(); auto schemaObj = schemaImportFunc((std::uint64_t)schema.get()); return py::cast(fromBatchesFunc(batches, schemaObj)); } diff --git a/tools/python_api/src_cpp/py_query_result_converter.cpp b/tools/python_api/src_cpp/py_query_result_converter.cpp index 7b2a4e5bca1..9c75c157d8b 100644 --- a/tools/python_api/src_cpp/py_query_result_converter.cpp +++ b/tools/python_api/src_cpp/py_query_result_converter.cpp @@ -1,9 +1,11 @@ #include "include/py_query_result_converter.h" +#include "cached_import/py_cached_import.h" #include "common/types/value/value.h" #include "include/py_query_result.h" using namespace kuzu::common; +using namespace kuzu; NPArrayWrapper::NPArrayWrapper(const LogicalType& type, uint64_t numFlatTuple) : type{type}, numElements{0} { @@ -77,10 +79,8 @@ void NPArrayWrapper::appendElement(Value* value) { } break; case LogicalTypeID::STRING: { auto val = value->getValue(); - auto result = PyUnicode_New(val.length(), 127); - auto target_data = PyUnicode_DATA(result); - memcpy(target_data, val.c_str(), val.length()); - ((PyObject**)dataBuffer)[numElements] = result; + py::str result(val); + ((py::str*)dataBuffer)[numElements] = result; } break; case LogicalTypeID::BLOB: { ((py::bytes*)dataBuffer)[numElements] = PyQueryResult::convertValueToPyObject(*value); @@ -93,8 +93,8 @@ void NPArrayWrapper::appendElement(Value* value) { case LogicalTypeID::REL: { ((py::object*)dataBuffer)[numElements] = PyQueryResult::convertValueToPyObject(*value); } break; - case LogicalTypeID::FIXED_LIST: - case LogicalTypeID::VAR_LIST: { + case LogicalTypeID::ARRAY: + case LogicalTypeID::LIST: { ((py::list*)dataBuffer)[numElements] = PyQueryResult::convertValueToPyObject(*value); } break; case LogicalTypeID::RECURSIVE_REL: { @@ -173,8 +173,8 @@ py::dtype NPArrayWrapper::convertToArrayType(const LogicalType& type) { case LogicalTypeID::STRUCT: case LogicalTypeID::NODE: case LogicalTypeID::REL: - case LogicalTypeID::VAR_LIST: - case LogicalTypeID::FIXED_LIST: + case LogicalTypeID::LIST: + case LogicalTypeID::ARRAY: case LogicalTypeID::STRING: case LogicalTypeID::MAP: case LogicalTypeID::RECURSIVE_REL: @@ -205,9 +205,11 @@ py::object QueryResultConverter::toDF() { py::dict result; auto colNames = queryResult->getColumnNames(); + auto maskedArray = importCache->numpyma.masked_array(); + auto fromDict = importCache->pandas.DataFrame.from_dict(); + for (auto i = 0u; i < colNames.size(); i++) { - result[colNames[i].c_str()] = - py::module::import("numpy.ma").attr("masked_array")(columns[i]->data, columns[i]->mask); + result[colNames[i].c_str()] = maskedArray(columns[i]->data, columns[i]->mask); } - return py::module::import("pandas").attr("DataFrame").attr("from_dict")(result); + return fromDict(result); } diff --git a/tools/python_api/src_cpp/pyarrow/pyarrow_bind.cpp b/tools/python_api/src_cpp/pyarrow/pyarrow_bind.cpp new file mode 100644 index 00000000000..9bcaf40e06d --- /dev/null +++ b/tools/python_api/src_cpp/pyarrow/pyarrow_bind.cpp @@ -0,0 +1,26 @@ +#include "pyarrow/pyarrow_bind.h" + +#include "cached_import/py_cached_import.h" +#include "common/arrow/arrow.h" +#include "common/arrow/arrow_converter.h" + +namespace kuzu { + +std::shared_ptr Pyarrow::bind(py::handle tableToBind, + std::vector& returnTypes, std::vector& names) { + + std::shared_ptr schema = std::make_shared(); + auto pyschema = tableToBind.attr("schema"); + auto exportSchemaToC = pyschema.attr("_export_to_c"); + exportSchemaToC(reinterpret_cast(schema.get())); + + for (int64_t i = 0; i < schema->n_children; i++) { + ArrowSchema* child = schema->children[i]; + names.emplace_back(child->name); + returnTypes.push_back(common::ArrowConverter::fromArrowSchema(child)); + } + + return schema; +} + +} // namespace kuzu diff --git a/tools/python_api/src_cpp/pyarrow/pyarrow_scan.cpp b/tools/python_api/src_cpp/pyarrow/pyarrow_scan.cpp new file mode 100644 index 00000000000..0598c269cda --- /dev/null +++ b/tools/python_api/src_cpp/pyarrow/pyarrow_scan.cpp @@ -0,0 +1,112 @@ +#include "pyarrow/pyarrow_scan.h" + +#include "cached_import/py_cached_import.h" +#include "common/arrow/arrow_converter.h" +#include "function/table/bind_input.h" +#include "py_connection.h" +#include "pybind11/pytypes.h" + +using namespace kuzu::function; +using namespace kuzu::common; +using namespace kuzu::catalog; + +namespace kuzu { + +static std::unique_ptr bindFunc( + main::ClientContext* /*context*/, TableFuncBindInput* input) { + + py::gil_scoped_acquire acquire; + py::object table(py::reinterpret_borrow( + reinterpret_cast(input->inputs[0].getValue()))); + if (py::isinstance(table, importCache->pandas.DataFrame())) { + table = importCache->pyarrow.lib.Table.from_pandas()(table); + } + std::vector returnTypes; + std::vector names; + if (py::isinstance(table)) { + KU_UNREACHABLE; + } + auto numRows = py::len(table); + auto schema = Pyarrow::bind(table, returnTypes, names); + + py::list batches = table.attr("to_batches")(DEFAULT_VECTOR_CAPACITY); + std::vector> arrowArrayBatches; + for (auto& i: batches) { + arrowArrayBatches.push_back(std::make_shared()); + i.attr("_export_to_c")(reinterpret_cast(arrowArrayBatches.back().get())); + } + + return std::make_unique( + std::move(returnTypes), std::move(schema), std::move(names), arrowArrayBatches, numRows); +} + +ArrowArrayWrapper* PyArrowTableScanSharedState::getNextChunk() { + std::lock_guard lck{lock}; + if (currentChunk == chunks.size()) { + return nullptr; + } + return chunks[currentChunk++].get(); +} + +static std::unique_ptr initSharedState( + function::TableFunctionInitInput& input) { + + py::gil_scoped_acquire acquire; + PyArrowTableScanFunctionData* bindData = + dynamic_cast(input.bindData); + + return std::make_unique( + bindData->numRows, bindData->arrowArrayBatches); +} + +static std::unique_ptr initLocalState( + function::TableFunctionInitInput& /*input*/, function::TableFuncSharedState* sharedState, + storage::MemoryManager* /*mm*/) { + + PyArrowTableScanSharedState* pyArrowShared = + dynamic_cast(sharedState); + return std::make_unique(pyArrowShared->getNextChunk()); +} + +static common::offset_t tableFunc( + function::TableFuncInput& input, function::TableFuncOutput& output) { + + auto arrowScanData = dynamic_cast(input.bindData); + auto arrowLocalState = dynamic_cast(input.localState); + auto arrowSharedState = dynamic_cast(input.sharedState); + if (arrowLocalState->arrowArray == nullptr) { + return 0; + } + for (auto i = 0u; i < arrowScanData->columnTypes.size(); i++) { + common::ArrowConverter::fromArrowArray(arrowScanData->schema->children[i], + arrowLocalState->arrowArray->children[i], *output.dataChunk.getValueVector(i)); + } + auto len = arrowLocalState->arrowArray->length; + arrowLocalState->arrowArray = arrowSharedState->getNextChunk(); + return len; +} + +double progressFunc(function::TableFuncSharedState* sharedState) { + PyArrowTableScanSharedState* state = + ku_dynamic_cast(sharedState); + if (state->chunks.size() == 0) { + return 0.0; + } + return static_cast(state->currentChunk) / state->chunks.size(); +} + +function::function_set PyArrowTableScanFunction::getFunctionSet() { + + function_set functionSet; + functionSet.push_back( + std::make_unique(name, tableFunc, bindFunc, + initSharedState, initLocalState, progressFunc, std::vector{LogicalTypeID::POINTER})); + return functionSet; +} + +TableFunction PyArrowTableScanFunction::getFunction() { + return TableFunction(name, tableFunc, bindFunc, initSharedState, + initLocalState, progressFunc, std::vector{LogicalTypeID::POINTER}); +} + +} // namespace kuzu diff --git a/tools/python_api/src_py/__init__.py b/tools/python_api/src_py/__init__.py index 899bc394bce..2baf11825f5 100644 --- a/tools/python_api/src_py/__init__.py +++ b/tools/python_api/src_py/__init__.py @@ -1,5 +1,5 @@ """ -# Kùzu Python API bindings +# Kùzu Python API bindings. This package provides a Python API for Kùzu graph database management system. @@ -12,7 +12,7 @@ ```python import kuzu -db = kuzu.Database('./test') +db = kuzu.Database("./test") conn = kuzu.Connection(db) # Define the schema @@ -28,7 +28,7 @@ conn.execute('COPY LivesIn FROM "lives-in.csv"') # Query the data -results = conn.execute('MATCH (u:User) RETURN u.name, u.age;') +results = conn.execute("MATCH (u:User) RETURN u.name, u.age;") while results.has_next(): print(results.get_next()) ``` @@ -37,8 +37,10 @@ """ -import sys +from __future__ import annotations + import os +import sys # Set RTLD_GLOBAL and RTLD_LAZY flags on Linux to fix the issue with loading # extensions @@ -46,20 +48,34 @@ original_dlopen_flags = sys.getdlopenflags() sys.setdlopenflags(os.RTLD_GLOBAL | os.RTLD_LAZY) -from .database import * -from .connection import * -from .query_result import * -from .types import * +from .connection import Connection +from .database import Database +from .prepared_statement import PreparedStatement +from .query_result import QueryResult +from .types import Type -def __getattr__(name): - if name == "version": + +def __getattr__(name: str) -> str | int: + if name in ("version", "__version__"): return Database.get_version() elif name == "storage_version": return Database.get_storage_version() else: - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") - + msg = f"module {__name__!r} has no attribute {name!r}" + raise AttributeError(msg) + # Restore the original dlopen flags if sys.platform == "linux": sys.setdlopenflags(original_dlopen_flags) + +__all__ = [ + "Connection", + "Database", + "PreparedStatement", + "QueryResult", + "Type", + "__version__", + "storage_version", + "version", +] diff --git a/tools/python_api/src_py/connection.py b/tools/python_api/src_py/connection.py index 102073d86dd..50f8f8cff18 100644 --- a/tools/python_api/src_py/connection.py +++ b/tools/python_api/src_py/connection.py @@ -1,15 +1,22 @@ -from .query_result import QueryResult -from .prepared_statement import PreparedStatement +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + from . import _kuzu +from .prepared_statement import PreparedStatement +from .query_result import QueryResult + +if TYPE_CHECKING: + from .database import Database class Connection: - """ - Connection to a database. - """ + """Connection to a database.""" - def __init__(self, database, num_threads=0): + def __init__(self, database: Database, num_threads: int = 0): """ + Initialise kuzu database connection. + Parameters ---------- database : Database @@ -19,27 +26,22 @@ def __init__(self, database, num_threads=0): Maximum number of threads to use for executing queries. """ - + self._connection: Any = None # (type: _kuzu.Connection from pybind11) self.database = database self.num_threads = num_threads - self._connection = None self.init_connection() - def __getstate__(self): - state = { - "database": self.database, - "num_threads": self.num_threads, - "_connection": None - } + def __getstate__(self) -> dict[str, Any]: + state = {"database": self.database, "num_threads": self.num_threads, "_connection": None} return state - def init_connection(self): + def init_connection(self) -> None: + """Establish a connection to the database, if not already initalised.""" self.database.init_database() if self._connection is None: - self._connection = _kuzu.Connection( - self.database._database, self.num_threads) + self._connection = _kuzu.Connection(self.database._database, self.num_threads) # type: ignore[union-attr] - def set_max_threads_for_exec(self, num_threads): + def set_max_threads_for_exec(self, num_threads: int) -> None: """ Set the maximum number of threads for executing queries. @@ -52,7 +54,11 @@ def set_max_threads_for_exec(self, num_threads): self.init_connection() self._connection.set_max_threads_for_exec(num_threads) - def execute(self, query, parameters={}): + def execute( + self, + query: str | PreparedStatement, + parameters: dict[str, Any] | None = None, + ) -> QueryResult: """ Execute a query. @@ -72,21 +78,23 @@ def execute(self, query, parameters={}): Query result. """ + if parameters is None: + parameters = {} + self.init_connection() - if type(parameters) != dict: + if not isinstance(parameters, dict): # TODO(Chang): remove ROLLBACK once we can guarantee database is deleted after conn self._connection.execute(self.prepare("ROLLBACK")._prepared_statement, {}) - raise RuntimeError("Parameters must be a dict") - prepared_statement = self.prepare( - query) if type(query) == str else query - _query_result = self._connection.execute( - prepared_statement._prepared_statement, - parameters) + msg = f"Parameters must be a dict; found {type(parameters)}." + raise RuntimeError(msg) # noqa: TRY004 + + prepared_statement = self.prepare(query) if isinstance(query, str) else query + _query_result = self._connection.execute(prepared_statement._prepared_statement, parameters) if not _query_result.isSuccess(): raise RuntimeError(_query_result.getErrorMessage()) return QueryResult(self, _query_result) - def prepare(self, query): + def prepare(self, query: str) -> PreparedStatement: """ Create a prepared statement for a query. @@ -101,22 +109,19 @@ def prepare(self, query): Prepared statement. """ - return PreparedStatement(self, query) - def _get_node_property_names(self, table_name): - PRIMARY_KEY_SYMBOL = "(PRIMARY KEY)" + def _get_node_property_names(self, table_name: str) -> dict[str, Any]: LIST_START_SYMBOL = "[" LIST_END_SYMBOL = "]" self.init_connection() - query_result = self.execute( - "CALL table_info('%s') RETURN *;" % table_name) + query_result = self.execute(f"CALL table_info('{table_name}') RETURN *;") results = {} while query_result.has_next(): row = query_result.get_next() prop_name = row[1] prop_type = row[2] - is_primary_key = row[3] == True + is_primary_key = row[3] is True dimension = prop_type.count(LIST_START_SYMBOL) splitted = prop_type.split(LIST_START_SYMBOL) shape = [] @@ -127,16 +132,12 @@ def _get_node_property_names(self, table_name): if s != "": shape.append(int(s)) prop_type = splitted[0] - results[prop_name] = { - "type": prop_type, - "dimension": dimension, - "is_primary_key": is_primary_key - } + results[prop_name] = {"type": prop_type, "dimension": dimension, "is_primary_key": is_primary_key} if len(shape) > 0: results[prop_name]["shape"] = tuple(shape) return results - def _get_node_table_names(self): + def _get_node_table_names(self) -> list[Any]: results = [] self.init_connection() query_result = self.execute("CALL show_tables() RETURN *;") @@ -146,7 +147,7 @@ def _get_node_table_names(self): results.append(row[0]) return results - def _get_rel_table_names(self): + def _get_rel_table_names(self) -> list[dict[str, Any]]: results = [] self.init_connection() tables_result = self.execute("CALL show_tables() RETURN *;") @@ -154,18 +155,14 @@ def _get_rel_table_names(self): row = tables_result.get_next() if row[1] == "REL": name = row[0] - connections_result = self.execute("CALL show_connection('%s') RETURN *;" % name) + connections_result = self.execute(f"CALL show_connection({name!r}) RETURN *;") src_dst_row = connections_result.get_next() src_node = src_dst_row[0] dst_node = src_dst_row[1] - results.append({ - "name": name, - "src": src_node, - "dst": dst_node - }) + results.append({"name": name, "src": src_node, "dst": dst_node}) return results - def set_query_timeout(self, timeout_in_ms): + def set_query_timeout(self, timeout_in_ms: int) -> None: """ Set the query timeout value in ms for executing queries. @@ -173,7 +170,7 @@ def set_query_timeout(self, timeout_in_ms): ---------- timeout_in_ms : int query timeout value in ms for executing queries. - + """ self.init_connection() self._connection.set_query_timeout(timeout_in_ms) diff --git a/tools/python_api/src_py/database.py b/tools/python_api/src_py/database.py index 2b0b4470f22..64fc3911619 100644 --- a/tools/python_api/src_py/database.py +++ b/tools/python_api/src_py/database.py @@ -1,23 +1,47 @@ +from __future__ import annotations + +from pathlib import Path +from typing import TYPE_CHECKING, Any + from . import _kuzu from .types import Type +if TYPE_CHECKING: + from numpy.typing import NDArray + from torch_geometric.data.feature_store import IndexType -class Database: - """ - Kùzu database instance. - """ + from .torch_geometric_feature_store import KuzuFeatureStore + from .torch_geometric_graph_store import KuzuGraphStore - def __init__(self, database_path, buffer_pool_size=0, max_num_threads=0, compression=True, lazy_init=False, - read_only=False, max_db_size= 1 << 43): + +class Database: + """Kùzu database instance.""" + + def __init__( + self, + database_path: str | Path, + *, + buffer_pool_size: int = 0, + max_num_threads: int = 0, + compression: bool = True, + lazy_init: bool = False, + read_only: bool = False, + max_db_size: int = (1 << 43), + ): """ Parameters ---------- - database_path : str + database_path : str, Path The path to database files buffer_pool_size : int - The maximum size of buffer pool in bytes (Optional). Default to 80% - of system memory. + The maximum size of buffer pool in bytes. Defaults to ~80% of system memory. + + max_num_threads : int + The maximum number of threads to use for executing queries. + + compression : bool + Enable database compression. lazy_init : bool If True, the database will not be initialized until the first query. @@ -41,17 +65,22 @@ def __init__(self, database_path, buffer_pool_size=0, max_num_threads=0, compres environment and 1GB under 32-bit one. """ + if isinstance(database_path, Path): + database_path = str(database_path) + self.database_path = database_path self.buffer_pool_size = buffer_pool_size self.max_num_threads = max_num_threads self.compression = compression self.read_only = read_only self.max_db_size = max_db_size - self._database = None + + self._database: Any = None # (type: _kuzu.Database from pybind11) if not lazy_init: self.init_database() - - def get_version(): + + @staticmethod + def get_version() -> str: """ Get the version of the database. @@ -60,9 +89,10 @@ def get_version(): str The version of the database. """ - return _kuzu.Database.get_version() - - def get_storage_version(): + return _kuzu.Database.get_version() # type: ignore[union-attr] + + @staticmethod + def get_storage_version() -> int: """ Get the storage version of the database. @@ -71,28 +101,31 @@ def get_storage_version(): int The storage version of the database. """ - return _kuzu.Database.get_storage_version() + return _kuzu.Database.get_storage_version() # type: ignore[union-attr] - def __getstate__(self): + def __getstate__(self) -> dict[str, Any]: state = { "database_path": self.database_path, "buffer_pool_size": self.buffer_pool_size, "compression": self.compression, "read_only": self.read_only, - "_database": None + "_database": None, } return state - def init_database(self): - """ - Initialize the database. - """ + def init_database(self) -> None: + """Initialize the database.""" if self._database is None: - self._database = _kuzu.Database(self.database_path, - self.buffer_pool_size, self.max_num_threads, self.compression, - self.read_only, self.max_db_size) + self._database = _kuzu.Database( # type: ignore[union-attr] + self.database_path, + self.buffer_pool_size, + self.max_num_threads, + self.compression, + self.read_only, + self.max_db_size, + ) - def set_logging_level(self, level): + def set_logging_level(self, level: str) -> None: """ Set the logging level. @@ -100,24 +133,25 @@ def set_logging_level(self, level): ---------- level : str Logging level. One of "debug", "info", "err". - - """ + """ self._database.set_logging_level(level) - def get_torch_geometric_remote_backend(self, num_threads=None): + def get_torch_geometric_remote_backend( + self, num_threads: int | None = None + ) -> tuple[KuzuFeatureStore, KuzuGraphStore]: """ - Use the database as the remote backend for torch_geometric. + Use the database as the remote backend for torch_geometric. - For the interface of the remote backend, please refer to + For the interface of the remote backend, please refer to https://pytorch-geometric.readthedocs.io/en/latest/advanced/remote.html. The current implementation is read-only and does not support edge features. The IDs of the nodes are based on the internal IDs (i.e., node offsets). For the remote node IDs to be consistent with the positions in the output tensors, please ensure that no deletion has been performed - on the node tables. + on the node tables. - The remote backend can also be plugged into the data loader of + The remote backend can also be plugged into the data loader of torch_geometric, which is useful for mini-batch training. For example: ```python @@ -130,7 +164,7 @@ def get_torch_geometric_remote_backend(self, num_threads=None): filter_per_worker=False, ) ``` - + Please note that the database instance is not fork-safe, so if more than one worker is used, `filter_per_worker` must be set to False. @@ -149,38 +183,49 @@ def get_torch_geometric_remote_backend(self, num_threads=None): """ from .torch_geometric_feature_store import KuzuFeatureStore from .torch_geometric_graph_store import KuzuGraphStore - return KuzuFeatureStore(self, num_threads), KuzuGraphStore(self, num_threads) - def _scan_node_table(self, table_name, prop_name, prop_type, dim, indices, num_threads): + return ( + KuzuFeatureStore(self, num_threads), + KuzuGraphStore(self, num_threads), + ) + + def _scan_node_table( + self, + table_name: str, + prop_name: str, + prop_type: str, + dim: int, + indices: IndexType, + num_threads: int, + ) -> NDArray[Any]: import numpy as np + """ Scan a node table from storage directly, bypassing query engine. Used internally by torch_geometric remote backend only. """ self.init_database() indices_cast = np.array(indices, dtype=np.uint64) - result = None + if prop_type == Type.INT64.value: result = np.empty(len(indices) * dim, dtype=np.int64) - self._database.scan_node_table_as_int64( - table_name, prop_name, indices_cast, result, num_threads) - if prop_type == Type.INT32.value: + self._database.scan_node_table_as_int64(table_name, prop_name, indices_cast, result, num_threads) + elif prop_type == Type.INT32.value: result = np.empty(len(indices) * dim, dtype=np.int32) - self._database.scan_node_table_as_int32( - table_name, prop_name, indices_cast, result, num_threads) - if prop_type == Type.INT16.value: + self._database.scan_node_table_as_int32(table_name, prop_name, indices_cast, result, num_threads) + elif prop_type == Type.INT16.value: result = np.empty(len(indices) * dim, dtype=np.int16) - self._database.scan_node_table_as_int16( - table_name, prop_name, indices_cast, result, num_threads) - if prop_type == Type.DOUBLE.value: + self._database.scan_node_table_as_int16(table_name, prop_name, indices_cast, result, num_threads) + elif prop_type == Type.DOUBLE.value: result = np.empty(len(indices) * dim, dtype=np.float64) - self._database.scan_node_table_as_double( - table_name, prop_name, indices_cast, result, num_threads) - if prop_type == Type.FLOAT.value: + self._database.scan_node_table_as_double(table_name, prop_name, indices_cast, result, num_threads) + elif prop_type == Type.FLOAT.value: result = np.empty(len(indices) * dim, dtype=np.float32) - self._database.scan_node_table_as_float( - table_name, prop_name, indices_cast, result, num_threads) + self._database.scan_node_table_as_float(table_name, prop_name, indices_cast, result, num_threads) + if result is not None: return result - raise ValueError("Unsupported property type: {}".format(prop_type)) + + msg = f"Unsupported property type: {prop_type}" + raise ValueError(msg) diff --git a/tools/python_api/src_py/prepared_statement.py b/tools/python_api/src_py/prepared_statement.py index f0e67dd2adb..a528a37e782 100644 --- a/tools/python_api/src_py/prepared_statement.py +++ b/tools/python_api/src_py/prepared_statement.py @@ -1,10 +1,18 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .connection import Connection + + class PreparedStatement: """ - A prepared statement is a parameterized query which can avoid planning the + A prepared statement is a parameterized query which can avoid planning the same query for repeated execution. """ - def __init__(self, connection, query): + def __init__(self, connection: Connection, query: str): """ Parameters ---------- @@ -13,10 +21,9 @@ def __init__(self, connection, query): query : str Query to prepare. """ - self._prepared_statement = connection._connection.prepare(query) - def is_success(self): + def is_success(self) -> bool: """ Check if the prepared statement is successfully prepared. @@ -25,10 +32,9 @@ def is_success(self): bool True if the prepared statement is successfully prepared. """ - return self._prepared_statement.is_success() - def get_error_message(self): + def get_error_message(self) -> str: """ Get the error message if the query is not prepared successfully. @@ -37,5 +43,4 @@ def get_error_message(self): str Error message. """ - return self._prepared_statement.get_error_message() diff --git a/src/planner/plan/append_comment_on.cpp b/tools/python_api/src_py/py.typed similarity index 100% rename from src/planner/plan/append_comment_on.cpp rename to tools/python_api/src_py/py.typed diff --git a/tools/python_api/src_py/query_result.py b/tools/python_api/src_py/query_result.py index c7201230fab..7200153132f 100644 --- a/tools/python_api/src_py/query_result.py +++ b/tools/python_api/src_py/query_result.py @@ -1,13 +1,32 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + from .torch_geometric_result_converter import TorchGeometricResultConverter from .types import Type +if TYPE_CHECKING: + import sys + from types import TracebackType + + import networkx as nx + import pandas as pd + import polars as pl + import pyarrow as pa + import torch_geometric.data as geo + + from . import _kuzu + + if sys.version_info >= (3, 11): + from typing import Self + else: + from typing_extensions import Self + class QueryResult: - """ - QueryResult stores the result of a query execution. - """ + """QueryResult stores the result of a query execution.""" - def __init__(self, connection, query_result): + def __init__(self, connection: _kuzu.Connection, query_result: _kuzu.QueryResult): # type: ignore[name-defined] """ Parameters ---------- @@ -18,15 +37,25 @@ def __init__(self, connection, query_result): The underlying C++ query result object from pybind11. """ - self.connection = connection self._query_result = query_result self.is_closed = False - def __del__(self): + def __enter__(self) -> Self: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + exc_traceback: TracebackType | None, + ) -> None: self.close() - def check_for_query_result_close(self): + def __del__(self) -> None: + self.close() + + def check_for_query_result_close(self) -> None: """ Check if the query result is closed and raise an exception if it is. @@ -36,11 +65,11 @@ def check_for_query_result_close(self): If the query result is closed. """ - if self.is_closed: - raise Exception("Query result is closed") + msg = "Query result is closed" + raise RuntimeError(msg) - def has_next(self): + def has_next(self) -> bool: """ Check if there are more rows in the query result. @@ -50,11 +79,10 @@ def has_next(self): True if there are more rows in the query result, False otherwise. """ - self.check_for_query_result_close() return self._query_result.hasNext() - def get_next(self): + def get_next(self) -> list[Any]: """ Get the next row in the query result. @@ -64,61 +92,99 @@ def get_next(self): Next row in the query result. """ - self.check_for_query_result_close() return self._query_result.getNext() - def close(self): - """ - Close the query result. - """ + def close(self) -> None: + """Close the query result.""" + if not self.is_closed: + # Allows the connection to be garbage collected if the query result + # is closed manually by the user. + self._query_result.close() + self.connection = None + self.is_closed = True - if self.is_closed: - return - self._query_result.close() - # Allows the connection to be garbage collected if the query result - # is closed manually by the user. - self.connection = None - self.is_closed = True - - def get_as_df(self): + def get_as_df(self) -> pd.DataFrame: """ Get the query result as a Pandas DataFrame. + See Also + -------- + get_as_pl : Get the query result as a Polars DataFrame. + get_as_arrow : Get the query result as a PyArrow Table. + Returns ------- pandas.DataFrame Query result as a Pandas DataFrame. """ - self.check_for_query_result_close() - import numpy - import pandas return self._query_result.getAsDF() - def get_as_arrow(self, chunk_size): + def get_as_pl(self) -> pl.DataFrame: + """ + Get the query result as a Polars DataFrame. + + See Also + -------- + get_as_df : Get the query result as a Pandas DataFrame. + get_as_arrow : Get the query result as a PyArrow Table. + + Returns + ------- + polars.DataFrame + Query result as a Polars DataFrame. + """ + import polars as pl + + self.check_for_query_result_close() + + # note: polars should always export just a single chunk, + # (eg: "-1") otherwise it will just need to rechunk anyway + return pl.from_arrow( # type: ignore[return-value] + data=self.get_as_arrow(chunk_size=-1), + ) + + def get_as_arrow(self, chunk_size: int | None = None) -> pa.Table: """ Get the query result as a PyArrow Table. Parameters ---------- - chunk_size : int - Number of rows to include in each chunk. + chunk_size : Number of rows to include in each chunk. + None + The chunk size is adaptive and depends on the number of columns in the query result. + -1 or 0 + The entire result is returned as a single chunk. + > 0 + The chunk size is the number of rows specified. + + See Also + -------- + get_as_pl : Get the query result as a Polars DataFrame. + get_as_df : Get the query result as a Pandas DataFrame. Returns ------- pyarrow.Table Query result as a PyArrow Table. """ - self.check_for_query_result_close() - import pyarrow + + if chunk_size is None: + # Adaptive; target 10m total elements in each chunk. + # (eg: if we had 10 cols, this would result in a 1m row chunk_size). + target_n_elems = 10_000_000 + chunk_size = max(target_n_elems // len(self.get_column_names()), 10) + elif chunk_size <= 0: + # No chunking: return the entire result as a single chunk + chunk_size = self.get_num_tuples() return self._query_result.getAsArrow(chunk_size) - def get_column_data_types(self): + def get_column_data_types(self) -> list[str]: """ Get the data types of the columns in the query result. @@ -128,11 +194,10 @@ def get_column_data_types(self): Data types of the columns in the query result. """ - self.check_for_query_result_close() return self._query_result.getColumnDataTypes() - def get_column_names(self): + def get_column_names(self) -> list[str]: """ Get the names of the columns in the query result. @@ -142,19 +207,33 @@ def get_column_names(self): Names of the columns in the query result. """ - self.check_for_query_result_close() return self._query_result.getColumnNames() - def reset_iterator(self): - """ - Reset the iterator of the query result. + def get_schema(self) -> dict[str, str]: """ + Get the column schema of the query result. + Returns + ------- + dict + Schema of the query result. + + """ + self.check_for_query_result_close() + return dict( + zip( + self._query_result.getColumnNames(), + self._query_result.getColumnDataTypes(), + ) + ) + + def reset_iterator(self) -> None: + """Reset the iterator of the query result.""" self.check_for_query_result_close() self._query_result.resetIterator() - def get_as_networkx(self, directed=True): + def get_as_networkx(self, directed: bool = True) -> nx.Graph | nx.DiGraph: # noqa: FBT001 """ Convert the nodes and rels in query result into a NetworkX directed or undirected graph with the following rules: @@ -172,14 +251,10 @@ def get_as_networkx(self, directed=True): Query result as a NetworkX graph. """ - self.check_for_query_result_close() import networkx as nx - if directed: - nx_graph = nx.DiGraph() - else: - nx_graph = nx.Graph() + nx_graph = nx.DiGraph() if directed else nx.Graph() properties_to_extract = self._get_properties_to_extract() self.reset_iterator() @@ -189,8 +264,9 @@ def get_as_networkx(self, directed=True): table_to_label_dict = {} table_primary_key_dict = {} - def encode_node_id(node, table_primary_key_dict): - return node['_label'] + "_" + str(node[table_primary_key_dict[node['_label']]]) + def encode_node_id(node: dict[str, Any], table_primary_key_dict: dict[str, Any]) -> str: + node_label = node["_label"] + return f"{node_label}_{node[table_primary_key_dict[node_label]]!s}" # De-duplicate nodes and rels while self.has_next(): @@ -205,36 +281,33 @@ def encode_node_id(node, table_primary_key_dict): elif column_type == Type.REL.value: _src = row[i]["_src"] _dst = row[i]["_dst"] - rels[(_src["table"], _src["offset"], _dst["table"], - _dst["offset"])] = row[i] + rels[(_src["table"], _src["offset"], _dst["table"], _dst["offset"])] = row[i] elif column_type == Type.RECURSIVE_REL.value: - for node in row[i]['_nodes']: + for node in row[i]["_nodes"]: _id = node["_id"] nodes[(_id["table"], _id["offset"])] = node table_to_label_dict[_id["table"]] = node["_label"] - for rel in row[i]['_rels']: + for rel in row[i]["_rels"]: for key in rel: if rel[key] is None: del rel[key] _src = rel["_src"] _dst = rel["_dst"] - rels[(_src["table"], _src["offset"], _dst["table"], - _dst["offset"])] = rel + rels[(_src["table"], _src["offset"], _dst["table"], _dst["offset"])] = rel # Add nodes for node in nodes.values(): _id = node["_id"] - node_id = node['_label'] + "_" + str(_id["offset"]) - if node['_label'] not in table_primary_key_dict: - props = self.connection._get_node_property_names( - node['_label']) + node_id = node["_label"] + "_" + str(_id["offset"]) + if node["_label"] not in table_primary_key_dict: + props = self.connection._get_node_property_names(node["_label"]) for prop_name in props: - if props[prop_name]['is_primary_key']: - table_primary_key_dict[node['_label']] = prop_name + if props[prop_name]["is_primary_key"]: + table_primary_key_dict[node["_label"]] = prop_name break node_id = encode_node_id(node, table_primary_key_dict) - node[node['_label']] = True + node[node["_label"]] = True nx_graph.add_node(node_id, **node) # Add rels @@ -248,7 +321,7 @@ def encode_node_id(node, table_primary_key_dict): nx_graph.add_edge(src_id, dst_id, **rel) return nx_graph - def _get_properties_to_extract(self): + def _get_properties_to_extract(self) -> dict[int, tuple[str, str]]: column_names = self.get_column_names() column_types = self.get_column_data_types() properties_to_extract = {} @@ -257,17 +330,21 @@ def _get_properties_to_extract(self): for i in range(len(column_names)): column_name = column_names[i] column_type = column_types[i] - if column_type in [Type.NODE.value, Type.REL.value, Type.RECURSIVE_REL.value]: + if column_type in [ + Type.NODE.value, + Type.REL.value, + Type.RECURSIVE_REL.value, + ]: properties_to_extract[i] = (column_type, column_name) return properties_to_extract - def get_as_torch_geometric(self): + def get_as_torch_geometric(self) -> tuple[geo.Data | geo.HeteroData, dict, dict, dict]: # type: ignore[type-arg] """ Converts the nodes and rels in query result into a PyTorch Geometric graph representation torch_geometric.data.Data or torch_geometric.data.HeteroData. For node conversion, numerical and boolean properties are directly converted into tensor and - stored in Data/HeteroData. For properties cannot be converted into tensor automatically + stored in Data/HeteroData. For properties cannot be converted into tensor automatically (please refer to the notes below for more detail), they are returned as unconverted_properties. For rel conversion, rel is converted into edge_index tensor director. Edge properties are returned @@ -277,9 +354,9 @@ def get_as_torch_geometric(self): - If the type of a node property is not one of INT64, DOUBLE, or BOOL, it cannot be converted automatically. - If a node property contains a null value, it cannot be converted automatically. - - If a node property contains a nested list of variable length (e.g. [[1,2],[3]]), it cannot be + - If a node property contains a nested list of variable length (e.g. [[1,2],[3]]), it cannot be converted automatically. - - If a node property is a list or nested list, but the shape is inconsistent (e.g. the list length + - If a node property is a list or nested list, but the shape is inconsistent (e.g. the list length is 6 for one node but 5 for another node), it cannot be converted automatically. Additional conversion rules: @@ -304,19 +381,15 @@ def get_as_torch_geometric(self): A dictionary contains edge properties. The order of values for each property is aligned with edge_index in Data/HeteroData. """ - self.check_for_query_result_close() # Despite we are not using torch_geometric in this file, we need to # import it here to throw an error early if the user does not have # torch_geometric or torch installed. - import torch - import torch_geometric - converter = TorchGeometricResultConverter(self) return converter.get_as_torch_geometric() - def get_execution_time(self): + def get_execution_time(self) -> int: """ Get the time in ms which was required for executing the query. @@ -329,7 +402,7 @@ def get_execution_time(self): self.check_for_query_result_close() return self._query_result.getExecutionTime() - def get_compiling_time(self): + def get_compiling_time(self) -> int: """ Get the time in ms which was required for compiling the query. @@ -342,7 +415,7 @@ def get_compiling_time(self): self.check_for_query_result_close() return self._query_result.getCompilingTime() - def get_num_tuples(self): + def get_num_tuples(self) -> int: """ Get the number of tuples which the query returned. @@ -350,7 +423,7 @@ def get_num_tuples(self): ------- int Number of tuples. - + """ self.check_for_query_result_close() return self._query_result.getNumTuples() diff --git a/tools/python_api/src_py/torch_geometric_feature_store.py b/tools/python_api/src_py/torch_geometric_feature_store.py index 3ac812dabb1..149e49702c7 100644 --- a/tools/python_api/src_py/torch_geometric_feature_store.py +++ b/tools/python_api/src_py/torch_geometric_feature_store.py @@ -1,46 +1,61 @@ -from .connection import Connection -from typing import List, Optional, Tuple -from .types import Type -import numpy as np +from __future__ import annotations -import torch import multiprocessing -from torch import Tensor +from typing import TYPE_CHECKING, Any +import numpy as np +import torch +from torch import Tensor from torch_geometric.data.feature_store import FeatureStore, TensorAttr -from torch_geometric.typing import FeatureTensorType +from .connection import Connection +from .types import Type + +if TYPE_CHECKING: + from torch_geometric.typing import FeatureTensorType + + from .database import Database + + +class KuzuFeatureStore(FeatureStore): # type: ignore[misc] + """Feature store compatible with `torch_geometric`.""" -class KuzuFeatureStore(FeatureStore): - def __init__(self, db, num_threads): + def __init__(self, db: Database, num_threads: int | None = None): super().__init__() self.db = db - self.connection = None - self.node_properties_cache = {} + self.connection: Connection = None # type: ignore[assignment] + self.node_properties_cache: dict[str, dict[str, Any]] = {} if num_threads is None: num_threads = multiprocessing.cpu_count() self.num_threads = num_threads - def __get_connection(self): - if not self.connection: + def __get_connection(self) -> Connection: + if self.connection is None: self.connection = Connection(self.db, self.num_threads) return self.connection def _put_tensor(self, tensor: FeatureTensorType, attr: TensorAttr) -> bool: raise NotImplementedError - def _get_tensor(self, attr: TensorAttr) -> Optional[FeatureTensorType]: + def _get_tensor(self, attr: TensorAttr) -> FeatureTensorType | None: table_name = attr.group_name attr_name = attr.attr_name attr_info = self.__get_node_property(table_name, attr_name) - if (not attr_info["type"] in [ - Type.INT64.value, Type.INT32.value, Type.INT16.value, - Type.DOUBLE.value, Type.FLOAT.value, Type.BOOL.value - ]) or (attr_info["dimension"] > 0 and "shape" not in attr_info): + if ( + attr_info["type"] + not in [ + Type.INT64.value, + Type.INT32.value, + Type.INT16.value, + Type.DOUBLE.value, + Type.FLOAT.value, + Type.BOOL.value, + ] + ) or (attr_info["dimension"] > 0 and "shape" not in attr_info): return self.__get_tensor_by_query(attr) return self.__get_tensor_by_scan(attr) - def __get_tensor_by_scan(self, attr: TensorAttr) -> Optional[FeatureTensorType]: + def __get_tensor_by_scan(self, attr: TensorAttr) -> FeatureTensorType | None: table_name = attr.group_name attr_name = attr.attr_name indices = attr.index @@ -51,17 +66,14 @@ def __get_tensor_by_scan(self, attr: TensorAttr) -> Optional[FeatureTensorType]: indices = np.arange(shape[0], dtype=np.uint64) elif isinstance(indices, slice): if indices.step is None or indices.step == 1: - indices = np.arange( - indices.start, indices.stop, dtype=np.uint64) + indices = np.arange(indices.start, indices.stop, dtype=np.uint64) else: - indices = np.arange(indices.start, indices.stop, - indices.step, dtype=np.uint64) + indices = np.arange(indices.start, indices.stop, indices.step, dtype=np.uint64) elif isinstance(indices, int): indices = np.array([indices]) if table_name not in self.node_properties_cache: - self.node_properties_cache[table_name] = self.connection._get_node_property_names( - table_name) + self.node_properties_cache[table_name] = self.connection._get_node_property_names(table_name) attr_info = self.node_properties_cache[table_name][attr_name] flat_dim = 1 @@ -69,45 +81,48 @@ def __get_tensor_by_scan(self, attr: TensorAttr) -> Optional[FeatureTensorType]: for i in range(attr_info["dimension"]): flat_dim *= attr_info["shape"][i] scan_result = self.connection.database._scan_node_table( - table_name, attr_name, attr_info["type"], flat_dim, indices, self.num_threads) + table_name, attr_name, attr_info["type"], flat_dim, indices, self.num_threads + ) - if attr_info['dimension'] > 0 and "shape" in attr_info: + if attr_info["dimension"] > 0 and "shape" in attr_info: result_shape = (len(indices),) + attr_info["shape"] scan_result = scan_result.reshape(result_shape) result = torch.from_numpy(scan_result) return result - def __get_tensor_by_query(self, attr: TensorAttr) -> Optional[FeatureTensorType]: + def __get_tensor_by_query(self, attr: TensorAttr) -> FeatureTensorType | None: table_name = attr.group_name attr_name = attr.attr_name indices = attr.index self.__get_connection() - match_clause = "MATCH (item:%s)" % table_name - return_clause = "RETURN item.%s" % attr_name + match_clause = f"MATCH (item:{table_name})" + return_clause = f"RETURN item.{attr_name}" if indices is None: where_clause = "" elif isinstance(indices, int): - where_clause = "WHERE offset(id(item)) = %d" % indices + where_clause = f"WHERE offset(id(item)) = {indices}" elif isinstance(indices, slice): if indices.step is None or indices.step == 1: - where_clause = "WHERE offset(id(item)) >= %d AND offset(id(item)) < %d" % ( - indices.start, indices.stop) + where_clause = f"WHERE offset(id(item)) >= {indices.start} AND offset(id(item)) < {indices.stop}" else: - where_clause = "WHERE offset(id(item)) >= %d AND offset(id(item)) < %d AND (offset(id(item)) - %d) %% %d = 0" % ( - indices.start, indices.stop, indices.start, indices.step) - elif isinstance(indices, Tensor) or isinstance(indices, list) or isinstance(indices, np.ndarray) or isinstance(indices, tuple): + where_clause = ( + f"WHERE offset(id(item)) >= {indices.start} AND offset(id(item)) < {indices.stop} " + f"AND (offset(id(item)) - {indices.start}) % {indices.step} = 0" + ) + elif isinstance(indices, (Tensor, list, np.ndarray, tuple)): where_clause = "WHERE" for i in indices: - where_clause += " offset(id(item)) = %d OR" % int(i) + where_clause += f" offset(id(item)) = {int(i)} OR" where_clause = where_clause[:-3] else: - raise ValueError("Invalid attr.index type: %s" % type(indices)) + msg = f"Invalid attr.index type: {type(indices)!s}" + raise ValueError(msg) - query = "%s %s %s" % (match_clause, where_clause, return_clause) + query = f"{match_clause} {where_clause} {return_clause}" res = self.connection.execute(query) result_list = [] @@ -117,17 +132,16 @@ def __get_tensor_by_query(self, attr: TensorAttr) -> Optional[FeatureTensorType] value_array = value_array[0] result_list.append(value_array) try: - tensor_result = torch.tensor(result_list) - return tensor_result - except: + return torch.tensor(result_list) + except Exception: return result_list def _remove_tensor(self, attr: TensorAttr) -> bool: raise NotImplementedError - def _get_tensor_size(self, attr: TensorAttr) -> Tuple: + def _get_tensor_size(self, attr: TensorAttr) -> tuple[Any, ...]: self.__get_connection() - length_query = "MATCH (item:%s) RETURN count(item)" % attr.group_name + length_query = f"MATCH (item:{attr.group_name}) RETURN count(item)" res = self.connection.execute(length_query) length = res.get_next()[0] attr_info = self.__get_node_property(attr.group_name, attr.attr_name) @@ -136,30 +150,33 @@ def _get_tensor_size(self, attr: TensorAttr) -> Tuple: else: return (length,) + attr_info["shape"] - def __get_node_property(self, table_name: str, attr_name: str) -> str: + def __get_node_property(self, table_name: str, attr_name: str) -> dict[str, Any]: if table_name in self.node_properties_cache and attr_name in self.node_properties_cache[table_name]: return self.node_properties_cache[table_name][attr_name] self.__get_connection() if table_name not in self.node_properties_cache: - self.node_properties_cache[table_name] = self.connection._get_node_property_names( - table_name) + self.node_properties_cache[table_name] = self.connection._get_node_property_names(table_name) if attr_name not in self.node_properties_cache[table_name]: - raise ValueError("Attribute %s not found in group %s" % - (attr_name, table_name)) + msg = f"Attribute {attr_name} not found in group {table_name}" + raise ValueError(msg) attr_info = self.node_properties_cache[table_name][attr_name] return attr_info - def get_all_tensor_attrs(self) -> List[TensorAttr]: + def get_all_tensor_attrs(self) -> list[TensorAttr]: + """Return all TensorAttr from the table nodes.""" result_list = [] self.__get_connection() for table_name in self.connection._get_node_table_names(): if table_name not in self.node_properties_cache: - self.node_properties_cache[table_name] = self.connection._get_node_property_names( - table_name) + self.node_properties_cache[table_name] = self.connection._get_node_property_names(table_name) for attr_name in self.node_properties_cache[table_name]: if self.node_properties_cache[table_name][attr_name]["type"] in [ - Type.INT64.value, Type.INT32.value, Type.INT16.value, - Type.DOUBLE.value, Type.FLOAT.value, Type.BOOL.value + Type.INT64.value, + Type.INT32.value, + Type.INT16.value, + Type.DOUBLE.value, + Type.FLOAT.value, + Type.BOOL.value, ] and ( self.node_properties_cache[table_name][attr_name]["dimension"] == 0 or "shape" in self.node_properties_cache[table_name][attr_name] diff --git a/tools/python_api/src_py/torch_geometric_graph_store.py b/tools/python_api/src_py/torch_geometric_graph_store.py index 5686cbf292b..7d615a50622 100644 --- a/tools/python_api/src_py/torch_geometric_graph_store.py +++ b/tools/python_api/src_py/torch_geometric_graph_store.py @@ -1,111 +1,131 @@ -from typing import Dict, List, Optional, Tuple +from __future__ import annotations -import torch import multiprocessing -from torch_geometric.data.graph_store import EdgeAttr, GraphStore, EdgeLayout -from torch_geometric.typing import EdgeTensorType -from .connection import Connection +from dataclasses import dataclass +from typing import TYPE_CHECKING, Any + import numpy as np +import torch +from torch_geometric.data.graph_store import EdgeAttr, EdgeLayout, GraphStore + +from .connection import Connection + +if TYPE_CHECKING: + import sys + + from torch_geometric.typing import EdgeTensorType + + from .database import Database + + if sys.version_info >= (3, 10): + from typing import TypeAlias + else: + from typing_extensions import TypeAlias + +StoreKeyType: TypeAlias = tuple[tuple[str], Any, bool] REL_BATCH_SIZE = 1000000 -class Rel: - def __init__(self, edge_type, layout, is_sorted, size, materialized=False, edge_index=None): - self.edge_type = edge_type - self.layout = layout - self.is_sorted = is_sorted - self.size = size - self.materialized = materialized - self.edge_index = edge_index +@dataclass +class Rel: # noqa: D101 + edge_type: tuple[str, ...] + layout: str + is_sorted: bool + size: tuple[int, ...] + materialized: bool = False + edge_index: EdgeTensorType | None = None + +class KuzuGraphStore(GraphStore): # type: ignore[misc] + """Graph store compatible with `torch_geometric`.""" -class KuzuGraphStore(GraphStore): - def __init__(self, db, num_threads): + def __init__(self, db: Database, num_threads: int | None = None): super().__init__() self.db = db - self.connection = None - self.store = {} + self.connection: Connection | None = None + self.store: dict[StoreKeyType, Rel] = {} if num_threads is None: num_threads = multiprocessing.cpu_count() self.num_threads = num_threads self.__populate_edge_attrs() @staticmethod - def key(attr: EdgeAttr) -> Tuple: - return (attr.edge_type, attr.layout.value, attr.is_sorted) + def key(attr: EdgeAttr) -> tuple[tuple[str], Any, bool]: # noqa: D102 + return attr.edge_type, attr.layout.value, attr.is_sorted - def _put_edge_index(self, edge_index: EdgeTensorType, - edge_attr: EdgeAttr) -> bool: + def _put_edge_index(self, edge_index: EdgeTensorType, edge_attr: EdgeAttr) -> None: key = self.key(edge_attr) if key in self.store: self.store[key].edge_index = edge_index self.store[key].materialized = True self.store[key].size = edge_attr.size else: - self.store[key] = Rel(key[0], key[1], key[2], edge_attr.size, True, - edge_index) + self.store[key] = Rel(key[0], key[1], key[2], edge_attr.size, True, edge_index) - def _get_edge_index(self, edge_attr: EdgeAttr) -> Optional[EdgeTensorType]: - if edge_attr.layout.value == EdgeLayout.COO.value: + def _get_edge_index(self, edge_attr: EdgeAttr) -> EdgeTensorType | None: + if edge_attr.layout.value == EdgeLayout.COO.value: # noqa: SIM102 # We always return a sorted COO edge index, if the request is # for an unsorted COO edge index, we change the is_sorted flag # to True and return the sorted COO edge index. - if edge_attr.is_sorted == False: + if edge_attr.is_sorted is False: edge_attr.is_sorted = True + key = self.key(edge_attr) if key in self.store: rel = self.store[self.key(edge_attr)] - if not rel.materialized: - if rel.layout != EdgeLayout.COO.value: - raise ValueError("Only COO layout is supported") + if not rel.materialized and rel.layout != EdgeLayout.COO.value: + msg = "Only COO layout is supported" + raise ValueError(msg) + if rel.layout == EdgeLayout.COO.value: self.__get_edge_coo_from_database(self.key(edge_attr)) return rel.edge_index else: return None - def _remove_edge_index(self, edge_attr: EdgeAttr) -> bool: + def _remove_edge_index(self, edge_attr: EdgeAttr) -> None: key = self.key(edge_attr) if key in self.store: del self.store[key] - def get_all_edge_attrs(self) -> List[EdgeAttr]: + def get_all_edge_attrs(self) -> list[EdgeAttr]: + """Return all EdgeAttr from the store values.""" return [EdgeAttr(rel.edge_type, rel.layout, rel.is_sorted, rel.size) for rel in self.store.values()] - def __get_edge_coo_from_database(self, key): + def __get_edge_coo_from_database(self, key: StoreKeyType) -> None: if not self.connection: self.connection = Connection(self.db, self.num_threads) rel = self.store[key] if rel.layout != EdgeLayout.COO.value: - raise ValueError("Only COO layout is supported") + msg = "Only COO layout is supported" + raise ValueError(msg) if rel.materialized: return + edge_type = rel.edge_type num_edges = self.connection._connection.get_num_rels(edge_type[1]) result = np.empty(2 * num_edges, dtype=np.int64) self.connection._connection.get_all_edges_for_torch_geometric( - result, edge_type[0], edge_type[1], edge_type[2], REL_BATCH_SIZE) + result, edge_type[0], edge_type[1], edge_type[2], REL_BATCH_SIZE + ) edge_list = torch.from_numpy(result) edge_list = edge_list.reshape((2, edge_list.shape[0] // 2)) rel.edge_index = edge_list rel.materialized = True - def __populate_edge_attrs(self): + def __populate_edge_attrs(self) -> None: if not self.connection: self.connection = Connection(self.db, self.num_threads) rel_tables = self.connection._get_rel_table_names() for rel_table in rel_tables: - edge_type = (rel_table['src'], rel_table['name'], rel_table['dst']) + edge_type = (rel_table["src"], rel_table["name"], rel_table["dst"]) size = self.__get_size(edge_type) - rel = Rel(edge_type, EdgeLayout.COO.value, - True, size, False, None) - self.store[self.key( - EdgeAttr(edge_type, EdgeLayout.COO, True))] = rel - - def __get_size(self, edge_type): - src_count = self.connection._connection.get_num_nodes(edge_type[0]) - dst_count = self.connection._connection.get_num_nodes(edge_type[-1]) - size = (src_count, dst_count) - return size + rel = Rel(edge_type, EdgeLayout.COO.value, True, size, False, None) + self.store[self.key(EdgeAttr(edge_type, EdgeLayout.COO, True))] = rel + + def __get_size(self, edge_type: tuple[str, ...]) -> tuple[int, int]: + num_nodes = self.connection._connection.get_num_nodes # type: ignore[union-attr] + src_count, dst_count = num_nodes(edge_type[0]), num_nodes(edge_type[-1]) + return (src_count, dst_count) diff --git a/tools/python_api/src_py/torch_geometric_result_converter.py b/tools/python_api/src_py/torch_geometric_result_converter.py index ee6e09ab652..991e1e17660 100644 --- a/tools/python_api/src_py/torch_geometric_result_converter.py +++ b/tools/python_api/src_py/torch_geometric_result_converter.py @@ -1,31 +1,41 @@ -from .types import Type +from __future__ import annotations + import warnings +from typing import TYPE_CHECKING, Any + +from .types import Type + +if TYPE_CHECKING: + import torch_geometric.data as geo + + from .query_result import QueryResult class TorchGeometricResultConverter: - def __init__(self, query_result): + """Convert graph results to `torch_geometric`.""" + + def __init__(self, query_result: QueryResult): self.query_result = query_result - self.nodes_dict = {} - self.edges_dict = {} - self.edges_properties = {} - self.rels = {} - self.nodes_property_names_dict = {} - self.table_to_label_dict = {} - self.internal_id_to_pos_dict = {} - self.pos_to_primary_key_dict = {} - self.warning_messages = set() - self.unconverted_properties = {} + self.nodes_dict: dict[str, Any] = {} + self.edges_dict: dict[str, Any] = {} + self.edges_properties: dict[str | tuple[str, str], dict[str, Any]] = {} + self.rels: dict[tuple[Any, ...], dict[str, Any]] = {} + self.nodes_property_names_dict: dict[str, Any] = {} + self.table_to_label_dict: dict[int, str] = {} + self.internal_id_to_pos_dict: dict[tuple[int, int], int | None] = {} + self.pos_to_primary_key_dict: dict[str, Any] = {} + self.warning_messages: set[str] = set() + self.unconverted_properties: dict[str, Any] = {} self.properties_to_extract = self.query_result._get_properties_to_extract() - def __get_node_property_names(self, table_name): + def __get_node_property_names(self, table_name: str) -> dict[str, Any]: if table_name in self.nodes_property_names_dict: return self.nodes_property_names_dict[table_name] - results = self.query_result.connection._get_node_property_names( - table_name) + results = self.query_result.connection._get_node_property_names(table_name) self.nodes_property_names_dict[table_name] = results return results - def __populate_nodes_dict_and_deduplicte_edges(self): + def __populate_nodes_dict_and_deduplicte_edges(self) -> None: self.query_result.reset_iterator() while self.query_result.has_next(): row = self.query_result.get_next() @@ -40,14 +50,11 @@ def __populate_nodes_dict_and_deduplicte_edges(self): if (_id["table"], _id["offset"]) in self.internal_id_to_pos_dict: continue - node_property_names = self.__get_node_property_names( - label) + node_property_names = self.__get_node_property_names(label) - pos, primary_key = self.__extract_properties_from_node( - node, label, node_property_names) + pos, primary_key = self.__extract_properties_from_node(node, label, node_property_names) - self.internal_id_to_pos_dict[( - _id["table"], _id["offset"])] = pos + self.internal_id_to_pos_dict[(_id["table"], _id["offset"])] = pos if label not in self.pos_to_primary_key_dict: self.pos_to_primary_key_dict[label] = {} self.pos_to_primary_key_dict[label][pos] = primary_key @@ -55,12 +62,17 @@ def __populate_nodes_dict_and_deduplicte_edges(self): elif column_type == Type.REL.value: _src = row[i]["_src"] _dst = row[i]["_dst"] - self.rels[(_src["table"], _src["offset"], - _dst["table"], _dst["offset"])] = row[i] + self.rels[(_src["table"], _src["offset"], _dst["table"], _dst["offset"])] = row[i] - def __extract_properties_from_node(self, node, label, node_property_names): + def __extract_properties_from_node( + self, + node: dict[str, Any], + label: str, + node_property_names: dict[str, Any], + ) -> tuple[int | None, Any]: pos = None import torch + for prop_name in node_property_names: # Read primary key if node_property_names[prop_name]["is_primary_key"]: @@ -74,47 +86,48 @@ def __extract_properties_from_node(self, node, label, node_property_names): # Mark properties that are not supported by torch_geometric as unconverted if node_property_names[prop_name]["type"] not in [Type.INT64.value, Type.DOUBLE.value, Type.BOOL.value]: self.warning_messages.add( - "Property {}.{} of type {} is not supported by torch_geometric. The property is marked as unconverted." - .format(label, prop_name, node_property_names[prop_name]["type"])) + "Property {}.{} of type {} is not supported by torch_geometric. The property is marked as unconverted.".format( + label, prop_name, node_property_names[prop_name]["type"] + ) + ) self.__mark_property_unconverted(label, prop_name) pos = self.__add_unconverted_property(node, label, prop_name) continue if node[prop_name] is None: self.warning_messages.add( - "Property {}.{} has a null value. torch_geometric does not support null values. The property is marked as unconverted." - .format(label, prop_name)) + f"Property {label}.{prop_name} has a null value. torch_geometric does not support null values. The property is marked as unconverted." + ) self.__mark_property_unconverted(label, prop_name) pos = self.__add_unconverted_property(node, label, prop_name) continue - if node_property_names[prop_name]['dimension'] == 0: + if node_property_names[prop_name]["dimension"] == 0: curr_value = node[prop_name] else: try: - if node_property_names[prop_name]['type'] == Type.INT64.value: + if node_property_names[prop_name]["type"] == Type.INT64.value: curr_value = torch.LongTensor(node[prop_name]) - elif node_property_names[prop_name]['type'] == Type.DOUBLE.value: + elif node_property_names[prop_name]["type"] == Type.DOUBLE.value: curr_value = torch.FloatTensor(node[prop_name]) - elif node_property_names[prop_name]['type'] == Type.BOOL.value: + elif node_property_names[prop_name]["type"] == Type.BOOL.value: curr_value = torch.BoolTensor(node[prop_name]) except ValueError: self.warning_messages.add( - "Property {}.{} cannot be converted to Tensor (likely due to nested list of variable length). The property is marked as unconverted." - .format(label, prop_name)) + f"Property {label}.{prop_name} cannot be converted to Tensor (likely due to nested list of variable length). The property is marked as unconverted." + ) self.__mark_property_unconverted(label, prop_name) - pos = self.__add_unconverted_property( - node, label, prop_name) + pos = self.__add_unconverted_property(node, label, prop_name) continue + # Check if the shape of the property is consistent - if label in self.nodes_dict and prop_name in self.nodes_dict[label]: + if label in self.nodes_dict and prop_name in self.nodes_dict[label]: # noqa: SIM102 # If the shape is inconsistent, then mark the property as unconverted if curr_value.shape != self.nodes_dict[label][prop_name][0].shape: self.warning_messages.add( - "Property {}.{} has an inconsistent shape. The property is marked as unconverted." - .format(label, prop_name)) + f"Property {label}.{prop_name} has an inconsistent shape. The property is marked as unconverted." + ) self.__mark_property_unconverted(label, prop_name) - pos = self.__add_unconverted_property( - node, label, prop_name) + pos = self.__add_unconverted_property(node, label, prop_name) continue # Create the dictionary for the label if it does not exist @@ -131,13 +144,13 @@ def __extract_properties_from_node(self, node, label, node_property_names): pos = len(self.nodes_dict[label][prop_name]) - 1 return pos, primary_key - def __add_unconverted_property(self, node, label, prop_name): - self.unconverted_properties[label][prop_name].append( - node[prop_name]) + def __add_unconverted_property(self, node: dict[str, Any], label: str, prop_name: str) -> int: + self.unconverted_properties[label][prop_name].append(node[prop_name]) return len(self.unconverted_properties[label][prop_name]) - 1 - def __mark_property_unconverted(self, label, prop_name): + def __mark_property_unconverted(self, label: str, prop_name: str) -> None: import torch + if label not in self.unconverted_properties: self.unconverted_properties[label] = {} if prop_name not in self.unconverted_properties[label]: @@ -148,13 +161,14 @@ def __mark_property_unconverted(self, label, prop_name): del self.nodes_dict[label] for i in range(len(self.unconverted_properties[label][prop_name])): # If the property is a tensor, convert it back to list (consistent with the original type) - if torch.is_tensor(self.unconverted_properties[label][prop_name][i]): - self.unconverted_properties[label][prop_name][i] = self.unconverted_properties[label][prop_name][i].tolist( - ) + if torch.is_tensor(self.unconverted_properties[label][prop_name][i]): # type: ignore[no-untyped-call] + self.unconverted_properties[label][prop_name][i] = self.unconverted_properties[label][ + prop_name + ][i].tolist() else: self.unconverted_properties[label][prop_name] = [] - def __populate_edges_dict(self): + def __populate_edges_dict(self) -> None: # Post-process edges, map internal ids to positions for r in self.rels: src_pos = self.internal_id_to_pos_dict[(r[0], r[1])] @@ -170,24 +184,29 @@ def __populate_edges_dict(self): if (src_label, dst_label) not in self.edges_properties: self.edges_properties[src_label, dst_label] = {} for prop_name in curr_edge_properties: - if prop_name in ['_src', '_dst', '_id']: + if prop_name in ["_src", "_dst", "_id"]: continue if prop_name not in self.edges_properties[src_label, dst_label]: - self.edges_properties[src_label, dst_label][prop_name] = [ - ] - self.edges_properties[src_label, dst_label][prop_name].append( - curr_edge_properties[prop_name]) + self.edges_properties[src_label, dst_label][prop_name] = [] + self.edges_properties[src_label, dst_label][prop_name].append(curr_edge_properties[prop_name]) - def __print_warnings(self): + def __print_warnings(self) -> None: for message in self.warning_messages: - warnings.warn(message) + warnings.warn(message, stacklevel=2) - def __convert_to_torch_geometric(self): + def __convert_to_torch_geometric( + self, + ) -> tuple[ + geo.Data | geo.HeteroData, + dict[str, Any], + dict[str, Any], + dict[str | tuple[str, str], dict[str, Any]], + ]: import torch import torch_geometric + if len(self.nodes_dict) == 0: - self.warning_messages.add( - "No nodes found or all node properties are not converted.") + self.warning_messages.add("No nodes found or all node properties are not converted.") # If there is only one node type, then convert to torch_geometric.data.Data # Otherwise, convert to torch_geometric.data.HeteroData @@ -199,23 +218,20 @@ def __convert_to_torch_geometric(self): is_hetero = True # Convert nodes to tensors + converted: torch.Tensor for label in self.nodes_dict: for prop_name in self.nodes_dict[label]: prop_type = self.nodes_property_names_dict[label][prop_name]["type"] prop_dimension = self.nodes_property_names_dict[label][prop_name]["dimension"] if prop_dimension == 0: if prop_type == Type.INT64.value: - converted = torch.LongTensor( - self.nodes_dict[label][prop_name]) + converted = torch.LongTensor(self.nodes_dict[label][prop_name]) elif prop_type == Type.BOOL.value: - converted = torch.BoolTensor( - self.nodes_dict[label][prop_name]) + converted = torch.BoolTensor(self.nodes_dict[label][prop_name]) elif prop_type == Type.DOUBLE.value: - converted = torch.FloatTensor( - self.nodes_dict[label][prop_name]) + converted = torch.FloatTensor(self.nodes_dict[label][prop_name]) else: - converted = torch.stack( - self.nodes_dict[label][prop_name], dim=0) + converted = torch.stack(self.nodes_dict[label][prop_name], dim=0) if is_hetero: data[label][prop_name] = converted else: @@ -224,14 +240,15 @@ def __convert_to_torch_geometric(self): # Convert edges to tensors for src_label in self.edges_dict: for dst_label in self.edges_dict[src_label]: - edge_idx = torch.tensor( - self.edges_dict[src_label][dst_label], dtype=torch.long).t().contiguous() + edge_idx = torch.tensor(self.edges_dict[src_label][dst_label], dtype=torch.long).t().contiguous() if is_hetero: data[src_label, dst_label].edge_index = edge_idx else: data.edge_index = edge_idx - pos_to_primary_key_dict = self.pos_to_primary_key_dict[ - label] if not is_hetero else self.pos_to_primary_key_dict + + pos_to_primary_key_dict: dict[str, Any] = ( + self.pos_to_primary_key_dict[label] if not is_hetero else self.pos_to_primary_key_dict + ) if is_hetero: unconverted_properties = self.unconverted_properties @@ -240,16 +257,22 @@ def __convert_to_torch_geometric(self): if len(self.unconverted_properties) == 0: unconverted_properties = {} else: - unconverted_properties = self.unconverted_properties[next( - iter(self.unconverted_properties))] + unconverted_properties = self.unconverted_properties[next(iter(self.unconverted_properties))] if len(self.edges_properties) == 0: edge_properties = {} else: - edge_properties = self.edges_properties[next( - iter(self.edges_properties))] + edge_properties = self.edges_properties[next(iter(self.edges_properties))] # type: ignore[assignment] return data, pos_to_primary_key_dict, unconverted_properties, edge_properties - def get_as_torch_geometric(self): + def get_as_torch_geometric( + self, + ) -> tuple[ + geo.Data | geo.HeteroData, + dict[str, Any], + dict[str, Any], + dict[str | tuple[str, str], dict[str, Any]], + ]: + """Convert graph data to `torch_geometric`.""" self.__populate_nodes_dict_and_deduplicte_edges() self.__populate_edges_dict() result = self.__convert_to_torch_geometric() diff --git a/tools/python_api/src_py/types.py b/tools/python_api/src_py/types.py index 10ab55308d7..4566e24af54 100644 --- a/tools/python_api/src_py/types.py +++ b/tools/python_api/src_py/types.py @@ -3,6 +3,7 @@ class Type(Enum): """The type of a value in the database.""" + ANY = "ANY" NODE = "NODE" REL = "REL" @@ -27,12 +28,12 @@ class Type(Enum): TIMESTAMP_MS = "TIMESTAMP_MS" TIMESTAMP_SEC = "TIMESTAMP_SEC" INTERVAL = "INTERVAL" - FIXED_LIST = "FIXED_LIST" INTERNAL_ID = "INTERNAL_ID" STRING = "STRING" BLOB = "BLOB" UUID = "UUID" - VAR_LIST = "VAR_LIST" + LIST = "LIST" + ARRAY = "ARRAY" STRUCT = "STRUCT" MAP = "MAP" UNION = "UNION" diff --git a/tools/python_api/test/conftest.py b/tools/python_api/test/conftest.py index df741c13f24..86fadae001a 100644 --- a/tools/python_api/test/conftest.py +++ b/tools/python_api/test/conftest.py @@ -1,63 +1,107 @@ -import os -import pytest +from __future__ import annotations + import shutil +import sys +from pathlib import Path +from typing import TYPE_CHECKING + +import pytest from test_helper import KUZU_ROOT -import kuzu +python_build_dir = Path(__file__).parent.parent / "build" +try: + import kuzu +except ModuleNotFoundError: + sys.path.append(str(python_build_dir)) + import kuzu + +if TYPE_CHECKING: + from type_aliases import ConnDB -def init_npy(conn): +def init_npy(conn: kuzu.Connection) -> None: conn.execute( - 'create node table npyoned (i64 INT64,i32 INT32,i16 INT16,f64 DOUBLE,f32 FLOAT, PRIMARY KEY(i64));' + """ + CREATE NODE TABLE npyoned ( + i64 INT64, + i32 INT32, + i16 INT16, + f64 DOUBLE, + f32 FLOAT, + PRIMARY KEY(i64) + ); + """ ) conn.execute( - f'copy npyoned from ("{KUZU_ROOT}/dataset/npy-1d/one_dim_int64.npy", "{KUZU_ROOT}/dataset/npy-1d/one_dim_int32.npy", ' - f' "{KUZU_ROOT}/dataset/npy-1d/one_dim_int16.npy", "{KUZU_ROOT}/dataset/npy-1d/one_dim_double.npy", ' - f'"{KUZU_ROOT}/dataset/npy-1d/one_dim_float.npy") by column;' + f""" + COPY npyoned from ( + "{KUZU_ROOT}/dataset/npy-1d/one_dim_int64.npy", + "{KUZU_ROOT}/dataset/npy-1d/one_dim_int32.npy", + "{KUZU_ROOT}/dataset/npy-1d/one_dim_int16.npy", + "{KUZU_ROOT}/dataset/npy-1d/one_dim_double.npy", + "{KUZU_ROOT}/dataset/npy-1d/one_dim_float.npy") BY COLUMN; + """ ) conn.execute( - 'create node table npytwod (id INT64, i64 INT64[3], i32 INT32[3], i16 INT16[3], f64 DOUBLE[3], f32 FLOAT[3],' - 'PRIMARY KEY(id));' + """ + CREATE NODE TABLE npytwod ( + id INT64, + i64 INT64[3], + i32 INT32[3], + i16 INT16[3], + f64 DOUBLE[3], + f32 FLOAT[3], + PRIMARY KEY(id) + ); + """ ) conn.execute( - f'copy npytwod from ("{KUZU_ROOT}/dataset/npy-2d/id_int64.npy", "{KUZU_ROOT}/dataset/npy-2d/two_dim_int64.npy", ' - f'"{KUZU_ROOT}/dataset/npy-2d/two_dim_int32.npy", "{KUZU_ROOT}/dataset/npy-2d/two_dim_int16.npy", ' - f' "{KUZU_ROOT}/dataset/npy-2d/two_dim_double.npy", "{KUZU_ROOT}/dataset/npy-2d/two_dim_float.npy") by column;' + f""" + COPY npytwod FROM ( + "{KUZU_ROOT}/dataset/npy-2d/id_int64.npy", + "{KUZU_ROOT}/dataset/npy-2d/two_dim_int64.npy", + "{KUZU_ROOT}/dataset/npy-2d/two_dim_int32.npy", + "{KUZU_ROOT}/dataset/npy-2d/two_dim_int16.npy", + "{KUZU_ROOT}/dataset/npy-2d/two_dim_double.npy", + "{KUZU_ROOT}/dataset/npy-2d/two_dim_float.npy") BY COLUMN; + """ ) -def init_tensor(conn): - conn.execute('create node table tensor (ID INT64, boolTensor BOOLEAN[], doubleTensor DOUBLE[][], ' - 'intTensor INT64[][][], oneDimInt INT64, PRIMARY KEY (ID));') +def init_tensor(conn: kuzu.Connection) -> None: conn.execute( - f'COPY tensor FROM "{KUZU_ROOT}/dataset/tensor-list/vTensor.csv" (HEADER=true)') + """ + CREATE NODE TABLE tensor ( + ID INT64, + boolTensor BOOLEAN[], + doubleTensor DOUBLE[][], + intTensor INT64[][][], + oneDimInt INT64, + PRIMARY KEY (ID) + ); + """ + ) + conn.execute(f'COPY tensor FROM "{KUZU_ROOT}/dataset/tensor-list/vTensor.csv" (HEADER=true)') -def init_long_str(conn): - conn.execute( - f"CREATE NODE TABLE personLongString (name STRING, spouse STRING, PRIMARY KEY(name))") - conn.execute( - f'COPY personLongString FROM "{KUZU_ROOT}/dataset/long-string-pk-tests/vPerson.csv"') - conn.execute( - f"CREATE REL TABLE knowsLongString (FROM personLongString TO personLongString, MANY_MANY)") - conn.execute( - f'COPY knowsLongString FROM "{KUZU_ROOT}/dataset/long-string-pk-tests/eKnows.csv"') +def init_long_str(conn: kuzu.Connection) -> None: + conn.execute("CREATE NODE TABLE personLongString (name STRING, spouse STRING, PRIMARY KEY(name))") + conn.execute(f'COPY personLongString FROM "{KUZU_ROOT}/dataset/long-string-pk-tests/vPerson.csv"') + conn.execute("CREATE REL TABLE knowsLongString (FROM personLongString TO personLongString, MANY_MANY)") + conn.execute(f'COPY knowsLongString FROM "{KUZU_ROOT}/dataset/long-string-pk-tests/eKnows.csv"') -def init_tinysnb(conn): - tiny_snb_path = os.path.abspath( - os.path.join( - os.path.dirname(os.path.abspath(__file__)), - f"{KUZU_ROOT}/dataset/tinysnb") - ) - schema_path = os.path.join(tiny_snb_path, "schema.cypher") - with open(schema_path, "r") as f: +def init_tinysnb(conn: kuzu.Connection) -> None: + tiny_snb_path = (Path(__file__).parent / f"{KUZU_ROOT}/dataset/tinysnb").resolve() + schema_path = tiny_snb_path / "schema.cypher" + with schema_path.open(mode="r") as f: for line in f.readlines(): line = line.strip() if line: conn.execute(line) - copy_path = os.path.join(tiny_snb_path, "copy.cypher") - with open(copy_path, "r") as f: + + copy_path = tiny_snb_path / "copy.cypher" + with copy_path.open(mode="r") as f: for line in f.readlines(): line = line.strip() line = line.replace("dataset/tinysnb", f"{KUZU_ROOT}/dataset/tinysnb") @@ -65,36 +109,35 @@ def init_tinysnb(conn): conn.execute(line) -def init_movie_serial(conn): - conn.execute( - "create node table moviesSerial (ID SERIAL, name STRING, length INT32, note STRING, PRIMARY KEY (ID));" - ) +def init_movie_serial(conn: kuzu.Connection) -> None: conn.execute( - f'copy moviesSerial from "{KUZU_ROOT}/dataset/tinysnb-serial/vMovies.csv"' + """ + CREATE NODE TABLE moviesSerial ( + ID SERIAL, + name STRING, + length INT32, + note STRING, + PRIMARY KEY (ID) + );""" ) + conn.execute(f'COPY moviesSerial from "{KUZU_ROOT}/dataset/tinysnb-serial/vMovies.csv"') -def init_rdf(conn): - rdf_path = os.path.abspath( - os.path.join( - os.path.dirname(os.path.abspath(__file__)), - f"{KUZU_ROOT}/dataset/rdf/rdf_variant") - ) - scripts = [os.path.join(rdf_path, "schema.cypher"), os.path.join(rdf_path, "copy.cypher")] + +def init_rdf(conn: kuzu.Connection) -> None: + rdf_path = (Path(__file__).parent / f"{KUZU_ROOT}/dataset/rdf/rdf_variant").resolve() + scripts = [Path(rdf_path) / "schema.cypher", Path(rdf_path) / "copy.cypher"] for script in scripts: - with open(script, "r") as f: + with script.open(mode="r") as f: for line in f.readlines(): - line = line.strip() - if line: + if line := line.strip(): conn.execute(line) +def init_db(path: Path) -> Path: + if Path(path).exists(): + shutil.rmtree(path) -@pytest.fixture -def init_db(tmp_path): - if os.path.exists(tmp_path): - shutil.rmtree(tmp_path) - output_path = str(tmp_path) - db = kuzu.Database(output_path) + db = kuzu.Database(path) conn = kuzu.Connection(db) init_tinysnb(conn) init_npy(conn) @@ -102,16 +145,39 @@ def init_db(tmp_path): init_long_str(conn) init_movie_serial(conn) init_rdf(conn) - return output_path + return path + +_READONLY_CONN_DB_: ConnDB | None = None +_POOL_SIZE_: int = 256 * 1024 * 1024 -@pytest.fixture -def establish_connection(init_db): - db = kuzu.Database(init_db, buffer_pool_size=256 * 1024 * 1024) + +def _create_conn_db(path: Path, *, read_only: bool) -> ConnDB: + """Return a new connection and database.""" + db = kuzu.Database(init_db(path), buffer_pool_size=_POOL_SIZE_, read_only=read_only) conn = kuzu.Connection(db, num_threads=4) return conn, db -@pytest.fixture -def get_tmp_path(tmp_path): - return str(tmp_path) +@pytest.fixture() +def conn_db_readonly(tmp_path: Path) -> ConnDB: + """Return a cached read-only connection and database.""" + global _READONLY_CONN_DB_ + if _READONLY_CONN_DB_ is None: + # On Windows, the read-only mode is not implemented yet. + # Therefore, we create a writable database on Windows. + # However, the caller should ensure that the database is not modified. + # TODO: Remove this workaround when the read-only mode is implemented on Windows. + _READONLY_CONN_DB_ = _create_conn_db(tmp_path, read_only=sys.platform != "win32") + return _READONLY_CONN_DB_ + + +@pytest.fixture() +def conn_db_readwrite(tmp_path: Path) -> ConnDB: + """Return a new writable connection and database.""" + return _create_conn_db(tmp_path, read_only=False) + + +@pytest.fixture() +def build_dir() -> Path: + return python_build_dir diff --git a/tools/python_api/test/example.py b/tools/python_api/test/example.py index d6b2601a39e..428c2076855 100644 --- a/tools/python_api/test/example.py +++ b/tools/python_api/test/example.py @@ -1,8 +1,9 @@ import sys -sys.path.append('/home/lc/Developer/guodong/kuzu/tools/python_api/build') + +sys.path.append("/home/lc/Developer/guodong/kuzu/tools/python_api/build") import kuzu -DB_PATH = '/home/lc/Developer/kuzu_ogb_mag' -db = kuzu.Database(DB_PATH, (10*1024**3)) +DB_PATH = "/home/lc/Developer/kuzu_ogb_mag" +db = kuzu.Database(DB_PATH, (10 * 1024**3)) conn = kuzu.Connection(db) t = conn.get_all_edges_for_torch_geometric(10792672, "paper", "cites", "paper", 1000000) diff --git a/tools/python_api/test/ground_truth.py b/tools/python_api/test/ground_truth.py index 0bb5a6517a1..a587b288c86 100644 --- a/tools/python_api/test/ground_truth.py +++ b/tools/python_api/test/ground_truth.py @@ -1,157 +1,182 @@ -import datetime +from datetime import date, datetime, timedelta -TINY_SNB_PERSONS_GROUND_TRUTH = {0: {'ID': 0, - 'fName': 'Alice', - 'gender': 1, - 'isStudent': True, - 'isWorker': False, - 'age': 35, - 'eyeSight': 5.0, - 'birthdate': datetime.date(1900, 1, 1), - 'registerTime': datetime.datetime(2011, 8, 20, 11, 25, 30), - 'lastJobDuration': datetime.timedelta(days=1082, seconds=46920), - 'workedHours': [10, 5], - 'usedNames': ['Aida'], - 'courseScoresPerTerm': [[10, 8], [6, 7, 8]], - '_label': 'person', - '_id': {'offset': 0, 'table': 0}}, - 2: {'ID': 2, - 'fName': 'Bob', - 'gender': 2, - 'isStudent': True, - 'isWorker': False, - 'age': 30, - 'eyeSight': 5.1, - 'birthdate': datetime.date(1900, 1, 1), - 'registerTime': datetime.datetime(2008, 11, 3, 15, 25, 30, 526), - 'lastJobDuration': datetime.timedelta(days=3750, seconds=46800, microseconds=24), - 'workedHours': [12, 8], - 'usedNames': ['Bobby'], - 'courseScoresPerTerm': [[8, 9], [9, 10]], - '_label': 'person', - '_id': {'offset': 1, 'table': 0}}, - 3: {'ID': 3, - 'fName': 'Carol', - 'gender': 1, - 'isStudent': False, - 'isWorker': True, - 'age': 45, - 'eyeSight': 5.0, - 'birthdate': datetime.date(1940, 6, 22), - 'registerTime': datetime.datetime(1911, 8, 20, 2, 32, 21), - 'lastJobDuration': datetime.timedelta(days=2, seconds=1451), - 'workedHours': [4, 5], - 'usedNames': ['Carmen', 'Fred'], - 'courseScoresPerTerm': [[8, 10]], - '_label': 'person', - '_id': {'offset': 2, 'table': 0}}, - 5: {'ID': 5, - 'fName': 'Dan', - 'gender': 2, - 'isStudent': False, - 'isWorker': True, - 'age': 20, - 'eyeSight': 4.8, - 'birthdate': datetime.date(1950, 7, 23), - 'registerTime': datetime.datetime(2031, 11, 30, 12, 25, 30), - 'lastJobDuration': datetime.timedelta(days=3750, seconds=46800, microseconds=24), - 'workedHours': [1, 9], - 'usedNames': ['Wolfeschlegelstein', 'Daniel'], - 'courseScoresPerTerm': [[7, 4], [8, 8], [9]], - '_label': 'person', - '_id': {'offset': 3, 'table': 0}}, - 7: {'ID': 7, - 'fName': 'Elizabeth', - 'gender': 1, - 'isStudent': False, - 'isWorker': True, - 'age': 20, - 'eyeSight': 4.7, - 'birthdate': datetime.date(1980, 10, 26), - 'registerTime': datetime.datetime(1976, 12, 23, 11, 21, 42), - 'lastJobDuration': datetime.timedelta(days=2, seconds=1451), - 'workedHours': [2], - 'usedNames': ['Ein'], - 'courseScoresPerTerm': [[6], [7], [8]], - '_label': 'person', - '_id': {'offset': 4, 'table': 0}}, - 8: {'ID': 8, - 'fName': 'Farooq', - 'gender': 2, - 'isStudent': True, - 'isWorker': False, - 'age': 25, - 'eyeSight': 4.5, - 'birthdate': datetime.date(1980, 10, 26), - 'registerTime': datetime.datetime(1972, 7, 31, 13, 22, 30, 678559), - 'lastJobDuration': datetime.timedelta(seconds=1080, microseconds=24000), - 'workedHours': [3, 4, 5, 6, 7], - 'usedNames': ['Fesdwe'], - 'courseScoresPerTerm': [[8]], - '_label': 'person', - '_id': {'offset': 5, 'table': 0}}, - 9: {'ID': 9, - 'fName': 'Greg', - 'gender': 2, - 'isStudent': False, - 'isWorker': False, - 'age': 40, - 'eyeSight': 4.9, - 'birthdate': datetime.date(1980, 10, 26), - 'registerTime': datetime.datetime(1976, 12, 23, 4, 41, 42), - 'lastJobDuration': datetime.timedelta(days=3750, seconds=46800, microseconds=24), - 'workedHours': [1], - 'usedNames': ['Grad'], - 'courseScoresPerTerm': [[10]], - '_label': 'person', - '_id': {'offset': 6, 'table': 0}}, - 10: {'ID': 10, - 'fName': 'Hubert Blaine Wolfeschlegelsteinhausenbergerdorff', - 'gender': 2, - 'isStudent': False, - 'isWorker': True, - 'age': 83, - 'eyeSight': 4.9, - 'birthdate': datetime.date(1990, 11, 27), - 'registerTime': datetime.datetime(2023, 2, 21, 13, 25, 30), - 'lastJobDuration': datetime.timedelta(days=1082, seconds=46920), - 'workedHours': [10, 11, 12, 3, 4, 5, 6, 7], - 'usedNames': ['Ad', 'De', 'Hi', 'Kye', 'Orlan'], - 'courseScoresPerTerm': [[7], [10], [6, 7]], - '_label': 'person', - '_id': {'offset': 7, 'table': 0}}} +TINY_SNB_PERSONS_GROUND_TRUTH = { + 0: { + "ID": 0, + "fName": "Alice", + "gender": 1, + "isStudent": True, + "isWorker": False, + "age": 35, + "eyeSight": 5.0, + "birthdate": date(1900, 1, 1), + "registerTime": datetime(2011, 8, 20, 11, 25, 30), + "lastJobDuration": timedelta(days=1082, seconds=46920), + "workedHours": [10, 5], + "usedNames": ["Aida"], + "courseScoresPerTerm": [[10, 8], [6, 7, 8]], + "_label": "person", + "_id": {"offset": 0, "table": 0}, + }, + 2: { + "ID": 2, + "fName": "Bob", + "gender": 2, + "isStudent": True, + "isWorker": False, + "age": 30, + "eyeSight": 5.1, + "birthdate": date(1900, 1, 1), + "registerTime": datetime(2008, 11, 3, 15, 25, 30, 526), + "lastJobDuration": timedelta(days=3750, seconds=46800, microseconds=24), + "workedHours": [12, 8], + "usedNames": ["Bobby"], + "courseScoresPerTerm": [[8, 9], [9, 10]], + "_label": "person", + "_id": {"offset": 1, "table": 0}, + }, + 3: { + "ID": 3, + "fName": "Carol", + "gender": 1, + "isStudent": False, + "isWorker": True, + "age": 45, + "eyeSight": 5.0, + "birthdate": date(1940, 6, 22), + "registerTime": datetime(1911, 8, 20, 2, 32, 21), + "lastJobDuration": timedelta(days=2, seconds=1451), + "workedHours": [4, 5], + "usedNames": ["Carmen", "Fred"], + "courseScoresPerTerm": [[8, 10]], + "_label": "person", + "_id": {"offset": 2, "table": 0}, + }, + 5: { + "ID": 5, + "fName": "Dan", + "gender": 2, + "isStudent": False, + "isWorker": True, + "age": 20, + "eyeSight": 4.8, + "birthdate": date(1950, 7, 23), + "registerTime": datetime(2031, 11, 30, 12, 25, 30), + "lastJobDuration": timedelta(days=3750, seconds=46800, microseconds=24), + "workedHours": [1, 9], + "usedNames": ["Wolfeschlegelstein", "Daniel"], + "courseScoresPerTerm": [[7, 4], [8, 8], [9]], + "_label": "person", + "_id": {"offset": 3, "table": 0}, + }, + 7: { + "ID": 7, + "fName": "Elizabeth", + "gender": 1, + "isStudent": False, + "isWorker": True, + "age": 20, + "eyeSight": 4.7, + "birthdate": date(1980, 10, 26), + "registerTime": datetime(1976, 12, 23, 11, 21, 42), + "lastJobDuration": timedelta(days=2, seconds=1451), + "workedHours": [2], + "usedNames": ["Ein"], + "courseScoresPerTerm": [[6], [7], [8]], + "_label": "person", + "_id": {"offset": 4, "table": 0}, + }, + 8: { + "ID": 8, + "fName": "Farooq", + "gender": 2, + "isStudent": True, + "isWorker": False, + "age": 25, + "eyeSight": 4.5, + "birthdate": date(1980, 10, 26), + "registerTime": datetime(1972, 7, 31, 13, 22, 30, 678559), + "lastJobDuration": timedelta(seconds=1080, microseconds=24000), + "workedHours": [3, 4, 5, 6, 7], + "usedNames": ["Fesdwe"], + "courseScoresPerTerm": [[8]], + "_label": "person", + "_id": {"offset": 5, "table": 0}, + }, + 9: { + "ID": 9, + "fName": "Greg", + "gender": 2, + "isStudent": False, + "isWorker": False, + "age": 40, + "eyeSight": 4.9, + "birthdate": date(1980, 10, 26), + "registerTime": datetime(1976, 12, 23, 4, 41, 42), + "lastJobDuration": timedelta(days=3750, seconds=46800, microseconds=24), + "workedHours": [1], + "usedNames": ["Grad"], + "courseScoresPerTerm": [[10]], + "_label": "person", + "_id": {"offset": 6, "table": 0}, + }, + 10: { + "ID": 10, + "fName": "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + "gender": 2, + "isStudent": False, + "isWorker": True, + "age": 83, + "eyeSight": 4.9, + "birthdate": date(1990, 11, 27), + "registerTime": datetime(2023, 2, 21, 13, 25, 30), + "lastJobDuration": timedelta(days=1082, seconds=46920), + "workedHours": [10, 11, 12, 3, 4, 5, 6, 7], + "usedNames": ["Ad", "De", "Hi", "Kye", "Orlan"], + "courseScoresPerTerm": [[7], [10], [6, 7]], + "_label": "person", + "_id": {"offset": 7, "table": 0}, + }, +} -TINY_SNB_ORGANISATIONS_GROUND_TRUTH = {1: {'ID': 1, - 'name': 'ABFsUni', - 'orgCode': 325, - 'mark': 3.7, - 'score': -2, - 'history': '10 years 5 months 13 hours 24 us', - 'licenseValidInterval': datetime.timedelta(days=1085), - 'rating': 1.0, - '_label': 'organisation', - '_id': {'offset': 0, 'table': 2}}, - 4: {'ID': 4, - 'name': 'CsWork', - 'orgCode': 934, - 'mark': 4.1, - 'score': -100, - 'history': '2 years 4 days 10 hours', - 'licenseValidInterval': datetime.timedelta(days=9414), - 'rating': 0.78, - '_label': 'organisation', - '_id': {'offset': 1, 'table': 2}}, - 6: {'ID': 6, - 'name': 'DEsWork', - 'orgCode': 824, - 'mark': 4.1, - 'score': 7, - 'history': '2 years 4 hours 22 us 34 minutes', - 'licenseValidInterval': datetime.timedelta(days=3, seconds=36000, - microseconds=100000), - 'rating': 0.52, - '_label': 'organisation', - '_id': {'offset': 2, 'table': 2}}} +TINY_SNB_ORGANISATIONS_GROUND_TRUTH = { + 1: { + "ID": 1, + "name": "ABFsUni", + "orgCode": 325, + "mark": 3.7, + "score": -2, + "history": "10 years 5 months 13 hours 24 us", + "licenseValidInterval": timedelta(days=1085), + "rating": 1.0, + "_label": "organisation", + "_id": {"offset": 0, "table": 2}, + }, + 4: { + "ID": 4, + "name": "CsWork", + "orgCode": 934, + "mark": 4.1, + "score": -100, + "history": "2 years 4 days 10 hours", + "licenseValidInterval": timedelta(days=9414), + "rating": 0.78, + "_label": "organisation", + "_id": {"offset": 1, "table": 2}, + }, + 6: { + "ID": 6, + "name": "DEsWork", + "orgCode": 824, + "mark": 4.1, + "score": 7, + "history": "2 years 4 hours 22 us 34 minutes", + "licenseValidInterval": timedelta(days=3, seconds=36000, microseconds=100000), + "rating": 0.52, + "_label": "organisation", + "_id": {"offset": 2, "table": 2}, + }, +} TINY_SNB_KNOWS_GROUND_TRUTH = { 0: [2, 3, 5], @@ -162,118 +187,150 @@ } TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH = { - (0, 2): {'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(1986, 10, 21, 21, 8, 31, 521000), - 'validInterval': datetime.timedelta(days=3750, seconds=46800, microseconds=24), - 'comments': ['rnme', 'm8sihsdnf2990nfiwf'], - 'summary': {'locations': ["'toronto'", "'waterloo'"], - 'transfer': {'day': datetime.date(2021, 1, 2), 'amount': [100, 200]}}, - 'notes': 1, - 'someMap': {'a': 'b'}}, - (0, 3): {'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(1946, 8, 25, 19, 7, 22), - 'validInterval': datetime.timedelta(days=7232), - 'comments': ['njnojppo9u0jkmf', 'fjiojioh9h9h89hph'], - 'summary': {'locations': None, 'transfer': None}, - 'notes': datetime.date(2020, 10, 10), - 'someMap': {'c': 'd', 'e': 'f', '1': '2'}}, - (0, 5): {'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(2012, 12, 11, 20, 7, 22), - 'validInterval': datetime.timedelta(days=10), - 'comments': ['ioji232', 'jifhe8w99u43434'], - 'summary': {'locations': ["'shanghai'"], 'transfer': {'day': datetime.date(1990, 9, 10), 'amount': [10]}}, - 'notes': 'nice weather', - 'someMap': None}, - (2, 0): {'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(1946, 8, 25, 19, 7, 22), - 'validInterval': datetime.timedelta(days=3750, seconds=46800, microseconds=24), - 'comments': ['2huh9y89fsfw23', '23nsihufhw723'], - 'summary': {'locations': ["'paris'"], - 'transfer': {'day': datetime.date(2000, 1, 1), 'amount': [20, 5000]}}, - 'notes': 4, - 'someMap': None}, - (2, 3): {'date': datetime.date(1950, 5, 14), - 'meetTime': datetime.datetime(1946, 8, 25, 19, 7, 22), - 'validInterval': datetime.timedelta(seconds=1380), - 'comments': ['fwehu9h9832wewew', '23u9h989sdfsss'], - 'summary': {'locations': ["'paris'"], - 'transfer': {'day': datetime.date(2011, 5, 1), 'amount': [2000, 5340]}}, - 'notes': 'cool stuff found', - 'someMap': None}, - (2, 5): {'date': datetime.date(1950, 5, 14), - 'meetTime': datetime.datetime(2012, 12, 11, 20, 7, 22), - 'validInterval': datetime.timedelta(days=7232), - 'comments': ['fwh9y81232uisuiehuf', 'ewnuihxy8dyf232'], - 'summary': {'locations': ["'vancouver'"], - 'transfer': {'day': datetime.date(2020, 1, 1), 'amount': [120, 50]}}, - 'notes': 'matthew perry', - 'someMap': None}, - (3, 0): {'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(2002, 7, 31, 11, 42, 53, 123420), - 'validInterval': datetime.timedelta(days=41, seconds=21600), - 'comments': ['fnioh8323aeweae34d', 'osd89e2ejshuih12'], - 'summary': {'locations': ["'london'", "'toronto'"], - 'transfer': {'day': datetime.date(2012, 11, 21), 'amount': [223, 5230]}}, - 'notes': 10, - 'someMap': None}, - (3, 2): {'date': datetime.date(1950, 5, 14), - 'meetTime': datetime.datetime(2007, 2, 12, 12, 11, 42, 123000), - 'validInterval': datetime.timedelta(seconds=1680, microseconds=30000), - 'comments': ['fwh983-sdjisdfji', 'ioh89y32r2huir'], - 'summary': {'locations': ["'paris'", "'beijing'"], - 'transfer': {'day': datetime.date(2011, 3, 11), 'amount': [2323, 50]}}, - 'notes': 1, - 'someMap': None}, - (3, 5): {'date': datetime.date(2000, 1, 1), - 'meetTime': datetime.datetime(1998, 10, 2, 13, 9, 22, 423000), - 'validInterval': datetime.timedelta(microseconds=300000), - 'comments': ['psh989823oaaioe', 'nuiuah1nosndfisf'], - 'summary': {'locations': [], 'transfer': {'day': datetime.date(1980, 11, 21), 'amount': [20, 5]}}, - 'notes': 2, - 'someMap': None}, - (5, 0): {'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(1936, 11, 2, 11, 2, 1), - 'validInterval': datetime.timedelta(microseconds=480), - 'comments': ['fwewe'], - 'summary': {'locations': ["'shanghai'", "'nanjing'"], - 'transfer': {'day': datetime.date(1998, 11, 12), 'amount': [22, 53240]}}, - 'notes': 15, - 'someMap': None}, - (5, 2): {'date': datetime.date(1950, 5, 14), - 'meetTime': datetime.datetime(1982, 11, 11, 13, 12, 5, 123000), - 'validInterval': datetime.timedelta(seconds=1380), - 'comments': ['fewh9182912e3', - 'h9y8y89soidfsf', - 'nuhudf78w78efw', - 'hioshe0f9023sdsd'], - 'summary': {'locations': ["'paris'"], - 'transfer': {'day': datetime.date(2000, 1, 1), 'amount': [20, 5000]}}, - 'notes': 'happy new year', - 'someMap': None}, - (5, 3): {'date': datetime.date(2000, 1, 1), - 'meetTime': datetime.datetime(1999, 4, 21, 15, 12, 11, 420000), - 'validInterval': datetime.timedelta(days=2, microseconds=52000), - 'comments': ['23h9sdslnfowhu2932', 'shuhf98922323sf'], - 'summary': {'locations': ["'paris'"], - 'transfer': {'day': datetime.date(2000, 1, 1), 'amount': [20, 5000]}}, - 'notes': 4, - 'someMap': None}, - (7, 8): {'date': datetime.date(1905, 12, 12), - 'meetTime': datetime.datetime(2025, 1, 1, 11, 22, 33, 520000), - 'validInterval': datetime.timedelta(seconds=2878), - 'comments': ['ahu2333333333333', '12weeeeeeeeeeeeeeeeee'], - 'summary': {'locations': ["'toronto'", "'thisisalongcityname'"], - 'transfer': {'day': datetime.date(1930, 11, 22), 'amount': [18, 323]}}, - 'notes': 8, - 'someMap': None}, - (7, 9): {'date': datetime.date(1905, 12, 12), - 'meetTime': datetime.datetime(2020, 3, 1, 12, 11, 41, 655200), - 'validInterval': datetime.timedelta(seconds=2878), - 'comments': ['peweeeeeeeeeeeeeeeee', 'kowje9w0eweeeeeeeee'], - 'summary': {'locations': ["'waterloo'"], - 'transfer': {'day': datetime.date(2000, 1, 1), 'amount': [1000, 5000]}}, - 'notes': 10, - 'someMap': None} + (0, 2): { + "date": date(2021, 6, 30), + "meetTime": datetime(1986, 10, 21, 21, 8, 31, 521000), + "validInterval": timedelta(days=3750, seconds=46800, microseconds=24), + "comments": ["rnme", "m8sihsdnf2990nfiwf"], + "summary": { + "locations": ["'toronto'", "'waterloo'"], + "transfer": {"day": date(2021, 1, 2), "amount": [100, 200]}, + }, + "notes": 1, + "someMap": {"a": "b"}, + }, + (0, 3): { + "date": date(2021, 6, 30), + "meetTime": datetime(1946, 8, 25, 19, 7, 22), + "validInterval": timedelta(days=7232), + "comments": ["njnojppo9u0jkmf", "fjiojioh9h9h89hph"], + "summary": {"locations": None, "transfer": None}, + "notes": date(2020, 10, 10), + "someMap": {"c": "d", "e": "f", "1": "2"}, + }, + (0, 5): { + "date": date(2021, 6, 30), + "meetTime": datetime(2012, 12, 11, 20, 7, 22), + "validInterval": timedelta(days=10), + "comments": ["ioji232", "jifhe8w99u43434"], + "summary": {"locations": ["'shanghai'"], "transfer": {"day": date(1990, 9, 10), "amount": [10]}}, + "notes": "nice weather", + "someMap": None, + }, + (2, 0): { + "date": date(2021, 6, 30), + "meetTime": datetime(1946, 8, 25, 19, 7, 22), + "validInterval": timedelta(days=3750, seconds=46800, microseconds=24), + "comments": ["2huh9y89fsfw23", "23nsihufhw723"], + "summary": {"locations": ["'paris'"], "transfer": {"day": date(2000, 1, 1), "amount": [20, 5000]}}, + "notes": 4, + "someMap": None, + }, + (2, 3): { + "date": date(1950, 5, 14), + "meetTime": datetime(1946, 8, 25, 19, 7, 22), + "validInterval": timedelta(seconds=1380), + "comments": ["fwehu9h9832wewew", "23u9h989sdfsss"], + "summary": {"locations": ["'paris'"], "transfer": {"day": date(2011, 5, 1), "amount": [2000, 5340]}}, + "notes": "cool stuff found", + "someMap": None, + }, + (2, 5): { + "date": date(1950, 5, 14), + "meetTime": datetime(2012, 12, 11, 20, 7, 22), + "validInterval": timedelta(days=7232), + "comments": ["fwh9y81232uisuiehuf", "ewnuihxy8dyf232"], + "summary": {"locations": ["'vancouver'"], "transfer": {"day": date(2020, 1, 1), "amount": [120, 50]}}, + "notes": "matthew perry", + "someMap": None, + }, + (3, 0): { + "date": date(2021, 6, 30), + "meetTime": datetime(2002, 7, 31, 11, 42, 53, 123420), + "validInterval": timedelta(days=41, seconds=21600), + "comments": ["fnioh8323aeweae34d", "osd89e2ejshuih12"], + "summary": { + "locations": ["'london'", "'toronto'"], + "transfer": {"day": date(2012, 11, 21), "amount": [223, 5230]}, + }, + "notes": 10, + "someMap": None, + }, + (3, 2): { + "date": date(1950, 5, 14), + "meetTime": datetime(2007, 2, 12, 12, 11, 42, 123000), + "validInterval": timedelta(seconds=1680, microseconds=30000), + "comments": ["fwh983-sdjisdfji", "ioh89y32r2huir"], + "summary": { + "locations": ["'paris'", "'beijing'"], + "transfer": {"day": date(2011, 3, 11), "amount": [2323, 50]}, + }, + "notes": 1, + "someMap": None, + }, + (3, 5): { + "date": date(2000, 1, 1), + "meetTime": datetime(1998, 10, 2, 13, 9, 22, 423000), + "validInterval": timedelta(microseconds=300000), + "comments": ["psh989823oaaioe", "nuiuah1nosndfisf"], + "summary": {"locations": [], "transfer": {"day": date(1980, 11, 21), "amount": [20, 5]}}, + "notes": 2, + "someMap": None, + }, + (5, 0): { + "date": date(2021, 6, 30), + "meetTime": datetime(1936, 11, 2, 11, 2, 1), + "validInterval": timedelta(microseconds=480), + "comments": ["fwewe"], + "summary": { + "locations": ["'shanghai'", "'nanjing'"], + "transfer": {"day": date(1998, 11, 12), "amount": [22, 53240]}, + }, + "notes": 15, + "someMap": None, + }, + (5, 2): { + "date": date(1950, 5, 14), + "meetTime": datetime(1982, 11, 11, 13, 12, 5, 123000), + "validInterval": timedelta(seconds=1380), + "comments": ["fewh9182912e3", "h9y8y89soidfsf", "nuhudf78w78efw", "hioshe0f9023sdsd"], + "summary": {"locations": ["'paris'"], "transfer": {"day": date(2000, 1, 1), "amount": [20, 5000]}}, + "notes": "happy new year", + "someMap": None, + }, + (5, 3): { + "date": date(2000, 1, 1), + "meetTime": datetime(1999, 4, 21, 15, 12, 11, 420000), + "validInterval": timedelta(days=2, microseconds=52000), + "comments": ["23h9sdslnfowhu2932", "shuhf98922323sf"], + "summary": {"locations": ["'paris'"], "transfer": {"day": date(2000, 1, 1), "amount": [20, 5000]}}, + "notes": 4, + "someMap": None, + }, + (7, 8): { + "date": date(1905, 12, 12), + "meetTime": datetime(2025, 1, 1, 11, 22, 33, 520000), + "validInterval": timedelta(seconds=2878), + "comments": ["ahu2333333333333", "12weeeeeeeeeeeeeeeeee"], + "summary": { + "locations": ["'toronto'", "'thisisalongcityname'"], + "transfer": {"day": date(1930, 11, 22), "amount": [18, 323]}, + }, + "notes": 8, + "someMap": None, + }, + (7, 9): { + "date": date(1905, 12, 12), + "meetTime": datetime(2020, 3, 1, 12, 11, 41, 655200), + "validInterval": timedelta(seconds=2878), + "comments": ["peweeeeeeeeeeeeeeeee", "kowje9w0eweeeeeeeee"], + "summary": { + "locations": ["'waterloo'"], + "transfer": {"day": date(2000, 1, 1), "amount": [1000, 5000]}, + }, + "notes": 10, + "someMap": None, + }, } TINY_SNB_WORKS_AT_GROUND_TRUTH = { @@ -282,56 +339,52 @@ 7: [6], } -TINY_SNB_WORKS_AT_PROPERTIES_GROUND_TRUTH = { - (3, 4): {'year': 2015}, - (5, 6): {'year': 2010}, - (7, 6): {'year': 2015} -} +TINY_SNB_WORKS_AT_PROPERTIES_GROUND_TRUTH = {(3, 4): {"year": 2015}, (5, 6): {"year": 2010}, (7, 6): {"year": 2015}} TENSOR_LIST_GROUND_TRUTH = { 0: { - 'boolTensor': [True, False], - 'doubleTensor': [[0.1, 0.2], [0.3, 0.4]], - 'intTensor': [[[1, 2], [3, 4]], [[5, 6], [7, 8]]] + "boolTensor": [True, False], + "doubleTensor": [[0.1, 0.2], [0.3, 0.4]], + "intTensor": [[[1, 2], [3, 4]], [[5, 6], [7, 8]]], }, 3: { - 'boolTensor': [True, False], - 'doubleTensor': [[0.1, 0.2], [0.3, 0.4]], - 'intTensor': [[[3, 4], [5, 6]], [[7, 8], [9, 10]]] + "boolTensor": [True, False], + "doubleTensor": [[0.1, 0.2], [0.3, 0.4]], + "intTensor": [[[3, 4], [5, 6]], [[7, 8], [9, 10]]], }, 4: { - 'boolTensor': [False, True], - 'doubleTensor': [[0.4, 0.8], [0.7, 0.6]], - 'intTensor': [[[5, 6], [7, 8]], [[9, 10], [11, 12]]] + "boolTensor": [False, True], + "doubleTensor": [[0.4, 0.8], [0.7, 0.6]], + "intTensor": [[[5, 6], [7, 8]], [[9, 10], [11, 12]]], }, 5: { - 'boolTensor': [True, True], - 'doubleTensor': [[0.4, 0.9], [0.5, 0.2]], - 'intTensor': [[[7, 8], [9, 10]], [[11, 12], [13, 14]]] + "boolTensor": [True, True], + "doubleTensor": [[0.4, 0.9], [0.5, 0.2]], + "intTensor": [[[7, 8], [9, 10]], [[11, 12], [13, 14]]], }, 6: { - 'boolTensor': [False, True], - 'doubleTensor': [[0.2, 0.4], [0.5, 0.1]], - 'intTensor': [[[9, 10], [11, 12]], [[13, 14], [15, 16]]] + "boolTensor": [False, True], + "doubleTensor": [[0.2, 0.4], [0.5, 0.1]], + "intTensor": [[[9, 10], [11, 12]], [[13, 14], [15, 16]]], }, 8: { - 'boolTensor': [False, True], - 'doubleTensor': [[0.6, 0.4], [0.6, 0.1]], - 'intTensor': [[[11, 12], [13, 14]], [[15, 16], [17, 18]]] - } + "boolTensor": [False, True], + "doubleTensor": [[0.6, 0.4], [0.6, 0.1]], + "intTensor": [[[11, 12], [13, 14]], [[15, 16], [17, 18]]], + }, } PERSONLONGSTRING_GROUND_TRUTH = { - 'AAAAAAAAAAAAAAAAAAAA': { - 'name': 'AAAAAAAAAAAAAAAAAAAA', - 'spouse': 'Bob', + "AAAAAAAAAAAAAAAAAAAA": { + "name": "AAAAAAAAAAAAAAAAAAAA", + "spouse": "Bob", }, - 'Bob': { - 'name': 'Bob', - 'spouse': 'AAAAAAAAAAAAAAAAAAAA', + "Bob": { + "name": "Bob", + "spouse": "AAAAAAAAAAAAAAAAAAAA", }, } PERSONLONGSTRING_KNOWS_GROUND_TRUTH = { - 'AAAAAAAAAAAAAAAAAAAA': ['Bob'], + "AAAAAAAAAAAAAAAAAAAA": ["Bob"], } diff --git a/tools/python_api/test/test_arrow.py b/tools/python_api/test/test_arrow.py index d071f6c082d..e579c034f40 100644 --- a/tools/python_api/test/test_arrow.py +++ b/tools/python_api/test/test_arrow.py @@ -1,307 +1,560 @@ -import time +from __future__ import annotations +from datetime import date, datetime, timedelta +from decimal import Decimal +from typing import Any + +import ground_truth import kuzu +import polars as pl import pyarrow as pa -import datetime -import ground_truth -from decimal import Decimal -from pandas import Timestamp import pytz - - -def test_to_arrow(establish_connection): - conn, db = establish_connection - - def _test_person_table(_conn): +from pandas import Timestamp +from type_aliases import ConnDB + +# enable polars' decimal support +pl.Config.activate_decimals(True) + + +_expected_dtypes = { + # ------------------------------------------------ + # person + # ------------------------------------------------ + "a.ID": {"arrow": pa.int64(), "pl": pl.Int64}, + "a.fName": {"arrow": pa.string(), "pl": pl.String}, + "a.gender": {"arrow": pa.int64(), "pl": pl.Int64}, + "a.isStudent": {"arrow": pa.bool_(), "pl": pl.Boolean}, + "a.isWorker": {"arrow": pa.bool_(), "pl": pl.Boolean}, + "a.age": {"arrow": pa.int64(), "pl": pl.Int64}, + "a.eyeSight": {"arrow": pa.float64(), "pl": pl.Float64}, + "a.birthdate": {"arrow": pa.date32(), "pl": pl.Date}, + "a.registerTime": {"arrow": pa.timestamp("us"), "pl": pl.Datetime("us")}, + "a.lastJobDuration": {"arrow": pa.duration("ms"), "pl": pl.Duration("ms")}, + "a.workedHours": {"arrow": pa.list_(pa.int64()), "pl": pl.List(pl.Int64)}, + "a.usedNames": {"arrow": pa.list_(pa.string()), "pl": pl.List(pl.String)}, + "a.courseScoresPerTerm": {"arrow": pa.list_(pa.list_(pa.int64())), "pl": pl.List(pl.List(pl.Int64))}, + "a.grades": {"arrow": pa.list_(pa.int64(), 4), "pl": pl.Array(pl.Int64, width=4)}, + "a.height": {"arrow": pa.float32(), "pl": pl.Float32}, + "a.u": {"arrow": pa.string(), "pl": pl.String}, + # ------------------------------------------------ + # movies + # ------------------------------------------------ + "a.length": {"arrow": pa.int32(), "pl": pl.Int32}, + "m.name": {"arrow": pa.string(), "pl": pl.String}, + "a.description": { + "arrow": pa.struct([ + ("rating", pa.float64()), + ("stars", pa.int8()), + ("views", pa.int64()), + ("release", pa.timestamp("us")), + ("release_ns", pa.timestamp("ns")), + ("release_ms", pa.timestamp("ms")), + ("release_sec", pa.timestamp("s")), + ("release_tz", pa.timestamp("us", tz="UTC")), + ("film", pa.date32()), + ("u8", pa.uint8()), + ("u16", pa.uint16()), + ("u32", pa.uint32()), + ("u64", pa.uint64()), + ("hugedata", pa.decimal128(38, 0)), + ]), + "pl": pl.Struct({ + "rating": pl.Float64, + "stars": pl.Int8, + "views": pl.Int64, + "release": pl.Datetime(time_unit="us"), + "release_ns": pl.Datetime(time_unit="ns"), + "release_ms": pl.Datetime(time_unit="ms"), + "release_sec": pl.Datetime(time_unit="ms"), + "release_tz": pl.Datetime(time_unit="us", time_zone="UTC"), + "film": pl.Date, + "u8": pl.UInt8, + "u16": pl.UInt16, + "u32": pl.UInt32, + "u64": pl.UInt64, + "hugedata": pl.Decimal(precision=38, scale=0), + }), + }, + # ------------------------------------------------ + # miscellaneous + # ------------------------------------------------ + "a.lbl": {"arrow": pa.string(), "pl": pl.String}, + "a.orgCode": {"arrow": pa.int64(), "pl": pl.Int64}, +} + + +def get_result(query_result: kuzu.QueryResult, result_type: str, chunk_size: int | None) -> Any: + sz = [] if (chunk_size is None or result_type == "pl") else [chunk_size] + res = getattr(query_result, f"get_as_{result_type}")(*sz) + if result_type == "arrow" and chunk_size: + assert res[0].num_chunks == max((len(res) // chunk_size), 1) + return res + + +def assert_column_equals(data: Any, col_name: str, return_type: str, expected_values: list[Any]) -> None: + col = data[col_name] + col_dtype = col.dtype if hasattr(col, "dtype") else col.type + values = col.to_pylist() if return_type == "arrow" else col.to_list() + + assert len(col) == len(expected_values) + assert values == expected_values, f"Unexpected values for {col_name} ({return_type!r})" + assert col_dtype == _expected_dtypes[col_name][return_type], f"Unexpected dtype for {col_name} ({return_type!r})" + + +def assert_col_names(data: Any, expected_col_names: list[str]) -> None: + col_names = [(c._name if hasattr(c, "_name") else c.name) for c in data] + assert col_names == expected_col_names, f"Unexpected column names: {col_names!r}" + + +def test_to_arrow(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + + def _test_person_table(_conn: kuzu.Connection, return_type: str, chunk_size: int | None = None) -> None: query = "MATCH (a:person) RETURN a.* ORDER BY a.ID" - arrow_tbl = _conn.execute(query).get_as_arrow(9) - assert arrow_tbl.num_columns == 16 - - id_col = arrow_tbl.column(0) - assert id_col.type == pa.int64() - assert id_col.length() == 8 - assert id_col.to_pylist() == [0, 2, 3, 5, 7, 8, 9, 10] - - f_name_col = arrow_tbl.column(1) - assert f_name_col.type == pa.string() - assert f_name_col.length() == 8 - assert f_name_col.to_pylist() == ["Alice", "Bob", "Carol", "Dan", "Elizabeth", "Farooq", "Greg", - "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"] - - f_gender_col = arrow_tbl.column(2) - assert f_gender_col.type == pa.int64() - assert f_gender_col.length() == 8 - assert f_gender_col.to_pylist() == [1, 2, 1, 2, 1, 2, 2, 2] - - is_student_col = arrow_tbl.column(3) - assert is_student_col.type == pa.bool_() - assert is_student_col.length() == 8 - assert is_student_col.to_pylist() == [True, True, False, False, False, True, False, False] - - is_worker_col = arrow_tbl.column(4) - assert is_worker_col.type == pa.bool_() - assert is_worker_col.length() == 8 - assert is_worker_col.to_pylist() == [False, False, True, True, True, False, False, True] - - age_col = arrow_tbl.column(5) - assert age_col.type == pa.int64() - assert age_col.length() == 8 - assert age_col.to_pylist() == [35, 30, 45, 20, 20, 25, 40, 83] - - eye_sight_col = arrow_tbl.column(6) - assert eye_sight_col.type == pa.float64() - assert eye_sight_col.length() == 8 - assert eye_sight_col.to_pylist() == [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9] - - birthdate_col = arrow_tbl.column(7) - assert birthdate_col.type == pa.date32() - assert birthdate_col.length() == 8 - assert birthdate_col.to_pylist() == [datetime.date(1900, 1, 1), datetime.date(1900, 1, 1), - datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), - datetime.date(1980, 10, 26), datetime.date(1980, 10, 26), - datetime.date(1980, 10, 26), datetime.date(1990, 11, 27)] - - register_time_col = arrow_tbl.column(8) - assert register_time_col.type == pa.timestamp('us') - assert register_time_col.length() == 8 - assert register_time_col.to_pylist() == [ - datetime.datetime(2011, 8, 20, 11, 25, 30), datetime.datetime(2008, 11, 3, 15, 25, 30, 526), - datetime.datetime(1911, 8, 20, 2, 32, 21), datetime.datetime(2031, 11, 30, 12, 25, 30), - datetime.datetime(1976, 12, 23, 11, 21, 42), datetime.datetime(1972, 7, 31, 13, 22, 30, 678559), - datetime.datetime(1976, 12, 23, 4, 41, 42), datetime.datetime(2023, 2, 21, 13, 25, 30)] - - last_job_duration_col = arrow_tbl.column(9) - assert last_job_duration_col.type == pa.duration('ms') - assert last_job_duration_col.length() == 8 - assert last_job_duration_col.to_pylist() == [datetime.timedelta(days=99, seconds=36334, microseconds=628000), - datetime.timedelta(days=543, seconds=4800), - datetime.timedelta(microseconds=125000), - datetime.timedelta(days=541, seconds=57600, microseconds=24000), - datetime.timedelta(0), - datetime.timedelta(days=2016, seconds=68600), - datetime.timedelta(microseconds=125000), - datetime.timedelta(days=541, seconds=57600, microseconds=24000)] - - worked_hours_col = arrow_tbl.column(10) - assert worked_hours_col.type == pa.list_(pa.int64()) - assert worked_hours_col.length() == 8 - assert worked_hours_col.to_pylist() == [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], - [10, 11, 12, 3, 4, 5, 6, 7]] - - used_names_col = arrow_tbl.column(11) - assert used_names_col.type == pa.list_(pa.string()) - assert used_names_col.length() == 8 - assert used_names_col.to_pylist() == [["Aida"], ["Bobby"], ["Carmen", "Fred"], ["Wolfeschlegelstein", "Daniel"], - ["Ein"], ["Fesdwe"], ["Grad"], ["Ad", "De", "Hi", "Kye", "Orlan"]] - - used_names_col = arrow_tbl.column(12) - assert used_names_col.type == pa.list_(pa.list_(pa.int64())) - assert used_names_col.length() == 8 - assert used_names_col.to_pylist() == [[[10, 8], [6, 7, 8]], [[8, 9], [9, 10]], [[8, 10]], [[7, 4], [8, 8], [9]], - [[6], [7], [8]], [[8]], [[10]], [[7], [10], [6, 7]]] - - grades_col = arrow_tbl.column(13) - assert grades_col.type == pa.list_(pa.int64(), 4) - assert grades_col.length() == 8 - assert grades_col.to_pylist() == [[96, 54, 86, 92], [98, 42, 93, 88], [91, 75, 21, 95], [76, 88, 99, 89], - [96, 59, 65, 88], [80, 78, 34, 83], [43, 83, 67, 43], [77, 64, 100, 54]] - - uuid_col = arrow_tbl.column(15) - assert uuid_col.type ==pa.string() - assert uuid_col.length() == 8 - assert uuid_col.to_pylist() == ['a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13','a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14', - 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18'] - - def _test_movies_table(_conn): + data = get_result(_conn.execute(query), return_type, chunk_size) + assert len(data.columns) == 16 + + assert_column_equals( + data=data, + col_name="a.ID", + return_type=return_type, + expected_values=[0, 2, 3, 5, 7, 8, 9, 10], + ) + + assert_column_equals( + data=data, + col_name="a.fName", + return_type=return_type, + expected_values=[ + "Alice", + "Bob", + "Carol", + "Dan", + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ], + ) + + assert_column_equals( + data=data, + col_name="a.gender", + return_type=return_type, + expected_values=[1, 2, 1, 2, 1, 2, 2, 2], + ) + + assert_column_equals( + data=data, + col_name="a.isStudent", + return_type=return_type, + expected_values=[True, True, False, False, False, True, False, False], + ) + + assert_column_equals( + data=data, + col_name="a.isWorker", + return_type=return_type, + expected_values=[False, False, True, True, True, False, False, True], + ) + + assert_column_equals( + data=data, + col_name="a.age", + return_type=return_type, + expected_values=[35, 30, 45, 20, 20, 25, 40, 83], + ) + + assert_column_equals( + data=data, + col_name="a.eyeSight", + return_type=return_type, + expected_values=[5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], + ) + + assert_column_equals( + data=data, + col_name="a.birthdate", + return_type=return_type, + expected_values=[ + date(1900, 1, 1), + date(1900, 1, 1), + date(1940, 6, 22), + date(1950, 7, 23), + date(1980, 10, 26), + date(1980, 10, 26), + date(1980, 10, 26), + date(1990, 11, 27), + ], + ) + + assert_column_equals( + data=data, + col_name="a.registerTime", + return_type=return_type, + expected_values=[ + datetime(2011, 8, 20, 11, 25, 30), + datetime(2008, 11, 3, 15, 25, 30, 526), + datetime(1911, 8, 20, 2, 32, 21), + datetime(2031, 11, 30, 12, 25, 30), + datetime(1976, 12, 23, 11, 21, 42), + datetime(1972, 7, 31, 13, 22, 30, 678559), + datetime(1976, 12, 23, 4, 41, 42), + datetime(2023, 2, 21, 13, 25, 30), + ], + ) + + assert_column_equals( + data=data, + col_name="a.lastJobDuration", + return_type=return_type, + expected_values=[ + timedelta(days=99, seconds=36334, microseconds=628000), + timedelta(days=543, seconds=4800), + timedelta(microseconds=125000), + timedelta(days=541, seconds=57600, microseconds=24000), + timedelta(0), + timedelta(days=2016, seconds=68600), + timedelta(microseconds=125000), + timedelta(days=541, seconds=57600, microseconds=24000), + ], + ) + + assert_column_equals( + data=data, + col_name="a.workedHours", + return_type=return_type, + expected_values=[[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], [10, 11, 12, 3, 4, 5, 6, 7]], + ) + + assert_column_equals( + data=data, + col_name="a.usedNames", + return_type=return_type, + expected_values=[ + ["Aida"], + ["Bobby"], + ["Carmen", "Fred"], + ["Wolfeschlegelstein", "Daniel"], + ["Ein"], + ["Fesdwe"], + ["Grad"], + ["Ad", "De", "Hi", "Kye", "Orlan"], + ], + ) + + assert_column_equals( + data=data, + col_name="a.courseScoresPerTerm", + return_type=return_type, + expected_values=[ + [[10, 8], [6, 7, 8]], + [[8, 9], [9, 10]], + [[8, 10]], + [[7, 4], [8, 8], [9]], + [[6], [7], [8]], + [[8]], + [[10]], + [[7], [10], [6, 7]], + ], + ) + + assert_column_equals( + data=data, + col_name="a.grades", + return_type=return_type, + expected_values=[ + [96, 54, 86, 92], + [98, 42, 93, 88], + [91, 75, 21, 95], + [76, 88, 99, 89], + [96, 59, 65, 88], + [80, 78, 34, 83], + [43, 83, 67, 43], + [77, 64, 100, 54], + ], + ) + + assert_column_equals( + data=data, + col_name="a.u", + return_type=return_type, + expected_values=[ + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", + "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18", + ], + ) + + def _test_movies_table(_conn: kuzu.Connection, return_type: str, chunk_size: int | None = None) -> None: query = "MATCH (a:movies) RETURN a.length, a.description ORDER BY a.length" - arrow_tbl = _conn.execute(query).get_as_arrow(8) - assert arrow_tbl.num_columns == 2 - - length_col = arrow_tbl.column(0) - assert length_col.type == pa.int32() - assert length_col.length() == 3 - assert length_col.to_pylist() == [126, 298, 2544] - - description_col = arrow_tbl.column(1) - assert description_col.type == pa.struct( - [('rating', pa.float64()), ('stars', pa.int8()), ('views', pa.int64()), ('release', pa.timestamp('us')), - ('release_ns', pa.timestamp('ns')), ('release_ms', pa.timestamp('ms')), - ('release_sec', pa.timestamp('s')), ('release_tz', pa.timestamp('us', tz='UTC')), - ('film', pa.date32()), ('u8', pa.uint8()), ('u16', pa.uint16()), ('u32', pa.uint32()), - ('u64', pa.uint64()), ('hugedata', pa.decimal128(38, 0))]) - assert description_col.length() == 3 - assert description_col.to_pylist() == [{ - 'rating': 5.3, - 'stars': 2, - 'views': 152, - 'release': datetime.datetime(2011, 8, 20, 11, 25, 30), - 'release_ns': Timestamp('2011-08-20 11:25:30.123456'), - 'release_ms': datetime.datetime(2011, 8, 20, 11, 25, 30, 123000), - 'release_sec': datetime.datetime(2011, 8, 20, 11, 25, 30), - 'release_tz': datetime.datetime(2011, 8, 20, 11, 25, 30, 123456, pytz.UTC), - 'film': datetime.date(2012, 5, 11), - 'u8': 220, - 'u16': 20, - 'u32': 1, - 'u64': 180, - 'hugedata': Decimal(1844674407370955161811111111) - }, { - 'rating': 1223.0, - 'stars': 100, - 'views': 10003, - 'release': datetime.datetime(2011, 2, 11, 16, 44, 22), - 'release_ns': Timestamp('2011-02-11 16:44:22.123456'), - 'release_ms': datetime.datetime(2011, 2, 11, 16, 44, 22, 123000), - 'release_sec': datetime.datetime(2011, 2, 11, 16, 44, 22), - 'release_tz': datetime.datetime(2011, 2, 11, 16, 44, 22, 123456, pytz.UTC), - 'film': datetime.date(2013, 2, 22), - 'u8': 1, - 'u16': 15, - 'u32': 200, - 'u64': 4, - 'hugedata': Decimal(-15) - }, { - 'rating': 7.0, - 'stars': 10, - 'views': 982, - 'release': datetime.datetime(2018, 11, 13, 13, 33, 11), - 'release_ns': Timestamp('2018-11-13 13:33:11.123456'), - 'release_ms': datetime.datetime(2018, 11, 13, 13, 33, 11, 123000), - 'release_sec': datetime.datetime(2018, 11, 13, 13, 33, 11), - 'release_tz': datetime.datetime(2018, 11, 13, 13, 33, 11, 123456, pytz.UTC), - 'film': datetime.date(2014, 9, 12), - 'u8': 12, - 'u16': 120, - 'u32': 55, - 'u64': 1, - 'hugedata': Decimal(-1844674407370955161511) - }] - - def _test_utf8_string(_conn): + data = get_result(_conn.execute(query), return_type, chunk_size) + + assert_col_names(data, ["a.length", "a.description"]) + assert_column_equals( + data=data, + col_name="a.length", + return_type=return_type, + expected_values=[126, 298, 2544], + ) + + assert_column_equals( + data=data, + col_name="a.description", + return_type=return_type, + expected_values=[ + { + "rating": 5.3, + "stars": 2, + "views": 152, + "release": datetime(2011, 8, 20, 11, 25, 30), + "release_ns": datetime(2011, 8, 20, 11, 25, 30, 123456) + if return_type == "pl" + else Timestamp("2011-08-20 11:25:30.123456"), + "release_ms": datetime(2011, 8, 20, 11, 25, 30, 123000), + "release_sec": datetime(2011, 8, 20, 11, 25, 30), + "release_tz": datetime(2011, 8, 20, 11, 25, 30, 123456, pytz.UTC), + "film": date(2012, 5, 11), + "u8": 220, + "u16": 20, + "u32": 1, + "u64": 180, + "hugedata": Decimal(1844674407370955161811111111), + }, + { + "rating": 1223.0, + "stars": 100, + "views": 10003, + "release": datetime(2011, 2, 11, 16, 44, 22), + "release_ns": datetime(2011, 2, 11, 16, 44, 22, 123456) + if return_type == "pl" + else Timestamp("2011-02-11 16:44:22.123456"), + "release_ms": datetime(2011, 2, 11, 16, 44, 22, 123000), + "release_sec": datetime(2011, 2, 11, 16, 44, 22), + "release_tz": datetime(2011, 2, 11, 16, 44, 22, 123456, pytz.UTC), + "film": date(2013, 2, 22), + "u8": 1, + "u16": 15, + "u32": 200, + "u64": 4, + "hugedata": Decimal(-15), + }, + { + "rating": 7.0, + "stars": 10, + "views": 982, + "release": datetime(2018, 11, 13, 13, 33, 11), + "release_ns": datetime(2018, 11, 13, 13, 33, 11, 123456) + if return_type == "pl" + else Timestamp("2018-11-13 13:33:11.123456"), + "release_ms": datetime(2018, 11, 13, 13, 33, 11, 123000), + "release_sec": datetime(2018, 11, 13, 13, 33, 11), + "release_tz": datetime(2018, 11, 13, 13, 33, 11, 123456, pytz.UTC), + "film": date(2014, 9, 12), + "u8": 12, + "u16": 120, + "u32": 55, + "u64": 1, + "hugedata": Decimal(-1844674407370955161511), + }, + ], + ) + + def _test_utf8_string(_conn: kuzu.Connection, return_type: str, chunk_size: int | None = None) -> None: query = "MATCH (m:movies) RETURN m.name" - query_result = _conn.execute(query) + data = get_result(_conn.execute(query), return_type, chunk_size) - arrow_tbl = query_result.get_as_arrow(3) - assert arrow_tbl.num_columns == 1 - name_col = arrow_tbl.column(0) - assert name_col.type == pa.string() - assert name_col.length() == 3 - assert name_col.to_pylist() == ["Sóló cón tu párejâ", "The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie", "Roma"] + assert_col_names(data, ["m.name"]) + assert_column_equals( + data=data, + col_name="m.name", + return_type=return_type, + expected_values=["Sóló cón tu párejâ", "The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie", "Roma"], + ) - def _test_in_small_chunk_size(_conn): + def _test_in_small_chunk_size(_conn: kuzu.Connection, return_type: str, chunk_size: int | None = None) -> None: query = "MATCH (a:person) RETURN a.age, a.fName ORDER BY a.ID" - query_result = _conn.execute(query) - - arrow_tbl = query_result.get_as_arrow(4) - assert arrow_tbl.num_columns == 2 - age_col = arrow_tbl.column(0) - assert age_col.type == pa.int64() - assert age_col.length() == 8 - f_name_col = arrow_tbl.column(1) - assert f_name_col.type == pa.string() - assert f_name_col.length() == 8 - - assert age_col.to_pylist() == [35, 30, 45, 20, 20, 25, 40, 83] - assert f_name_col.to_pylist() == ["Alice", "Bob", "Carol", "Dan", "Elizabeth", "Farooq", "Greg", - "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"] - - def _test_with_nulls(_conn): - query = "MATCH (a:person:organisation) RETURN label(a), a.fName, a.orgCode ORDER BY a.ID" - query_result = _conn.execute(query) - arrow_tbl = query_result.get_as_arrow(12) - assert arrow_tbl.num_columns == 3 - label_col = arrow_tbl.column(0) - assert label_col.type == pa.string() - assert label_col.length() == 11 - assert label_col.to_pylist() == ["person", "organisation", "person", "person", "organisation", "person", - "organisation", "person", "person", "person", "person"] - - f_name_col = arrow_tbl.column(1) - assert f_name_col.type == pa.string() - assert f_name_col.length() == 11 - assert f_name_col.to_pylist() == ["Alice", None, "Bob", "Carol", None, "Dan", None, "Elizabeth", "Farooq", - "Greg", "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"] - - org_code_col = arrow_tbl.column(2) - assert org_code_col.type == pa.int64() - assert org_code_col.length() == 11 - assert org_code_col.to_pylist() == [None, 325, None, None, 934, None, 824, None, None, None, None] - - _test_person_table(conn) - _test_movies_table(conn) - _test_utf8_string(conn) - _test_in_small_chunk_size(conn) - _test_with_nulls(conn) - -def test_to_arrow_complex(establish_connection): - conn, db = establish_connection - - def _test_node(_conn): + data = get_result(_conn.execute(query), return_type, chunk_size) + + assert_col_names(data, ["a.age", "a.fName"]) + assert_column_equals( + data=data, + col_name="a.age", + return_type=return_type, + expected_values=[35, 30, 45, 20, 20, 25, 40, 83], + ) + + assert_column_equals( + data=data, + col_name="a.fName", + return_type=return_type, + expected_values=[ + "Alice", + "Bob", + "Carol", + "Dan", + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ], + ) + + def _test_with_nulls(_conn: kuzu.Connection, return_type: str, chunk_size: int | None = None) -> None: + query = "MATCH (a:person:organisation) RETURN label(a) AS `a.lbl`, a.fName, a.orgCode ORDER BY a.ID" + data = get_result(_conn.execute(query), return_type, chunk_size) + + assert_col_names(data, ["a.lbl", "a.fName", "a.orgCode"]) + assert_column_equals( + data=data, + col_name="a.lbl", + return_type=return_type, + expected_values=[ + "person", + "organisation", + "person", + "person", + "organisation", + "person", + "organisation", + "person", + "person", + "person", + "person", + ], + ) + + assert_column_equals( + data=data, + col_name="a.fName", + return_type=return_type, + expected_values=[ + "Alice", + None, + "Bob", + "Carol", + None, + "Dan", + None, + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ], + ) + + assert_column_equals( + data=data, + col_name="a.orgCode", + return_type=return_type, + expected_values=[None, 325, None, None, 934, None, 824, None, None, None, None], + ) + + _test_person_table(conn, "arrow", 9) + _test_person_table(conn, "pl") + _test_movies_table(conn, "arrow", 8) + _test_movies_table(conn, "pl") + _test_utf8_string(conn, "arrow", 3) + _test_utf8_string(conn, "pl") + _test_in_small_chunk_size(conn, "arrow", 4) + _test_in_small_chunk_size(conn, "pl", 4) + _test_with_nulls(conn, "arrow", 12) + _test_with_nulls(conn, "pl") + + +def test_to_arrow_complex(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + + def _test_node(_conn: kuzu.Connection) -> None: query = "MATCH (p:person) RETURN p ORDER BY p.ID" query_result = _conn.execute(query) - arrow_tbl = query_result.get_as_arrow(12) + arrow_tbl = query_result.get_as_arrow() p_col = arrow_tbl.column(0) - assert p_col.to_pylist() == [ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[0], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[2], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[3], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[5], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[7], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[8], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[9], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[10]] - - def _test_node_rel(_conn): + assert p_col.to_pylist() == [ + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[0], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[2], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[3], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[5], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[7], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[8], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[9], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[10], + ] + + def _test_node_rel(_conn: kuzu.Connection) -> None: query = "MATCH (a:person)-[e:workAt]->(b:organisation) RETURN a, e, b;" query_result = _conn.execute(query) - arrow_tbl = query_result.get_as_arrow(12) + arrow_tbl = query_result.get_as_arrow(0) assert arrow_tbl.num_columns == 3 a_col = arrow_tbl.column(0) - assert a_col.length() == 3 + assert len(a_col) == 3 e_col = arrow_tbl.column(1) - assert a_col.length() == 3 + assert len(a_col) == 3 b_col = arrow_tbl.column(2) - assert a_col.length() == 3 - assert a_col.to_pylist() == [ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[3], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[5], - ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[7]] + assert len(a_col) == 3 + assert a_col.to_pylist() == [ + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[3], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[5], + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[7], + ] assert e_col.to_pylist() == [ - {'_src': {'offset': 2, 'tableID': 0}, '_dst': {'offset': 1, 'tableID': 2}, - '_id': {'offset': 0, 'tableID': 4}, 'year': 2015}, - {'_src': {'offset': 3, 'tableID': 0}, '_dst': {'offset': 2, 'tableID': 2}, - '_id': {'offset': 1, 'tableID': 4}, 'year': 2010}, - {'_src': {'offset': 4, 'tableID': 0}, '_dst': {'offset': 2, 'tableID': 2}, - '_id': {'offset': 2, 'tableID': 4}, 'year': 2015}] - assert b_col.to_pylist() == [ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[4], - ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[6], - ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[6]] - - def _test_marries_table(_conn): + { + "_src": {"offset": 2, "tableID": 0}, + "_dst": {"offset": 1, "tableID": 2}, + "_id": {"offset": 0, "tableID": 4}, + "year": 2015, + }, + { + "_src": {"offset": 3, "tableID": 0}, + "_dst": {"offset": 2, "tableID": 2}, + "_id": {"offset": 1, "tableID": 4}, + "year": 2010, + }, + { + "_src": {"offset": 4, "tableID": 0}, + "_dst": {"offset": 2, "tableID": 2}, + "_id": {"offset": 2, "tableID": 4}, + "year": 2015, + }, + ] + assert b_col.to_pylist() == [ + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[4], + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[6], + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[6], + ] + + def _test_marries_table(_conn: kuzu.Connection) -> None: query = "MATCH (:person)-[e:marries]->(:person) RETURN e.*" - arrow_tbl = _conn.execute(query).get_as_arrow(8) + arrow_tbl = _conn.execute(query).get_as_arrow(0) assert arrow_tbl.num_columns == 3 used_addr_col = arrow_tbl.column(0) assert used_addr_col.type == pa.list_(pa.string()) - assert used_addr_col.length() == 3 - assert used_addr_col.to_pylist() == [['toronto'], None, []] + assert len(used_addr_col) == 3 + assert used_addr_col.to_pylist() == [["toronto"], None, []] - addr_col = arrow_tbl.column(1) + arrow_tbl.column(1) assert used_addr_col.type == pa.list_(pa.int16(), 2) - assert used_addr_col.length() == 3 + assert len(used_addr_col) == 3 assert used_addr_col.to_pylist() == [[4, 5], [2, 5], [3, 9]] - note_col = arrow_tbl.column(2) + arrow_tbl.column(2) assert used_addr_col.type == pa.string() - assert used_addr_col.length() == 3 + assert len(used_addr_col) == 3 assert used_addr_col.to_pylist() == [None, "long long long string", "short str"] - #_test_node(conn) - #_test_node_rel(conn) - #_test_marries_table(conn) + # _test_node(conn) + # _test_node_rel(conn) + # _test_marries_table(conn) - def test_to_arrow1(establish_connection): - conn, db = establish_connection + def test_to_arrow1(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly query = "MATCH (a:person)-[e:knows]->(:person) RETURN e.summary" - arrow_tbl = conn.execute(query).get_as_arrow(8) + arrow_tbl = conn.execute(query).get_as_arrow(-1) assert arrow_tbl == [] diff --git a/tools/python_api/test/test_datatype.py b/tools/python_api/test/test_datatype.py index 36c72dd4611..7688be736c5 100644 --- a/tools/python_api/test/test_datatype.py +++ b/tools/python_api/test/test_datatype.py @@ -1,84 +1,95 @@ +from __future__ import annotations + import datetime -import pytz from uuid import UUID -def test_bool(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:person) WHERE a.ID = 0 RETURN a.isStudent;") +import pytz +from type_aliases import ConnDB + + +def test_bool(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.isStudent;") assert result.has_next() assert result.get_next() == [True] assert not result.has_next() result.close() -def test_int(establish_connection): - conn, db = establish_connection +def test_int(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.age;") assert result.has_next() assert result.get_next() == [35] assert not result.has_next() result.close() -def test_int8(establish_connection): - conn, db = establish_connection + +def test_int8(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) -[r:studyAt]-> (b:organisation) WHERE r.length = 5 RETURN r.level;") assert result.has_next() assert result.get_next() == [5] assert not result.has_next() result.close() -def test_uint8(establish_connection): - conn, db = establish_connection + +def test_uint8(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) -[r:studyAt]-> (b:organisation) WHERE r.length = 5 RETURN r.ulevel;") assert result.has_next() assert result.get_next() == [250] assert not result.has_next() result.close() -def test_uint16(establish_connection): - conn, db = establish_connection + +def test_uint16(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) -[r:studyAt]-> (b:organisation) WHERE r.length = 5 RETURN r.ulength;") assert result.has_next() assert result.get_next() == [33768] assert not result.has_next() result.close() -def test_uint32(establish_connection): - conn, db = establish_connection + +def test_uint32(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) -[r:studyAt]-> (b:organisation) WHERE r.length = 5 RETURN r.temprature;") assert result.has_next() assert result.get_next() == [32800] assert not result.has_next() result.close() -def test_uint64(establish_connection): - conn, db = establish_connection + +def test_uint64(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) -[r:studyAt]-> (b:organisation) WHERE r.length = 5 RETURN r.code;") assert result.has_next() assert result.get_next() == [9223372036854775808] assert not result.has_next() result.close() -def test_int128(establish_connection): - conn, db = establish_connection + +def test_int128(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) -[r:studyAt]-> (b:organisation) WHERE r.length = 5 RETURN r.hugedata;") assert result.has_next() assert result.get_next() == [1844674407370955161811111111] assert not result.has_next() result.close() -def test_serial(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:moviesSerial) WHERE a.ID = 2 RETURN a.ID;") - assert result.has_next() - assert result.get_next() == [2] - assert not result.has_next() - result.close() +def test_serial(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:moviesSerial) WHERE a.ID = 2 RETURN a.ID;") + assert result.has_next() + assert result.get_next() == [2] + assert not result.has_next() + result.close() -def test_double(establish_connection): - conn, db = establish_connection + +def test_double(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.eyeSight;") assert result.has_next() assert result.get_next() == [5.0] @@ -86,17 +97,17 @@ def test_double(establish_connection): result.close() -def test_string(establish_connection): - conn, db = establish_connection +def test_string(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.fName;") assert result.has_next() - assert result.get_next() == ['Alice'] + assert result.get_next() == ["Alice"] assert not result.has_next() result.close() -def test_blob(establish_connection): - conn, db = establish_connection +def test_blob(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("RETURN BLOB('\\\\xAA\\\\xBB\\\\xCD\\\\x1A')") assert result.has_next() result_blob = result.get_next()[0] @@ -108,252 +119,250 @@ def test_blob(establish_connection): assert not result.has_next() result.close() -def test_uuid(establish_connection): - conn, db = establish_connection + +def test_uuid(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("RETURN UUID('A0EEBC99-9c0b-4ef8-bb6d-6bb9bd380a12')") assert result.has_next() - assert result.get_next() == [UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12')] + assert result.get_next() == [UUID("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12")] assert not result.has_next() result.close() -def test_date(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:person) WHERE a.ID = 0 RETURN a.birthdate;") + +def test_date(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.birthdate;") assert result.has_next() assert result.get_next() == [datetime.date(1900, 1, 1)] assert not result.has_next() result.close() -def test_timestamp(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:person) WHERE a.ID = 0 RETURN a.registerTime;") +def test_timestamp(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.registerTime;") assert result.has_next() assert result.get_next() == [datetime.datetime(2011, 8, 20, 11, 25, 30)] assert not result.has_next() result.close() -def test_timestamp_tz(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_tz;") + +def test_timestamp_tz(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_tz;") assert result.has_next() assert result.get_next() == [datetime.datetime(2011, 8, 20, 11, 25, 30, 123456, pytz.UTC)] assert not result.has_next() result.close() -def test_timestamp_ns(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_ns;") + +def test_timestamp_ns(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_ns;") assert result.has_next() assert result.get_next() == [datetime.datetime(2011, 8, 20, 11, 25, 30, 123456)] assert not result.has_next() result.close() -def test_timestamp_ms(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_ms;") + +def test_timestamp_ms(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_ms;") assert result.has_next() assert result.get_next() == [datetime.datetime(2011, 8, 20, 11, 25, 30, 123000)] assert not result.has_next() result.close() -def test_timestamp_ns(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_sec;") + +def test_timestamp_s(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:movies) WHERE a.length = 126 RETURN a.description.release_sec;") assert result.has_next() assert result.get_next() == [datetime.datetime(2011, 8, 20, 11, 25, 30)] assert not result.has_next() result.close() -def test_interval(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:person) WHERE a.ID = 0 RETURN a.lastJobDuration;") + +def test_interval(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.lastJobDuration;") assert result.has_next() assert result.get_next() == [datetime.timedelta(days=1082, seconds=46920)] assert not result.has_next() result.close() -def test_list(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:person) WHERE a.ID = 0 RETURN a.courseScoresPerTerm;") +def test_list(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.courseScoresPerTerm;") assert result.has_next() assert result.get_next() == [[[10, 8], [6, 7, 8]]] assert not result.has_next() result.close() -def test_map(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (m:movies) WHERE m.length = 2544 RETURN m.audience;") +def test_map(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (m:movies) WHERE m.length = 2544 RETURN m.audience;") assert result.has_next() - assert result.get_next() == [{'audience1': 33}] + assert result.get_next() == [{"audience1": 33}] assert not result.has_next() result.close() -def test_union(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (m:movies) WHERE m.length = 2544 RETURN m.grade;") +def test_union(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (m:movies) WHERE m.length = 2544 RETURN m.grade;") assert result.has_next() assert result.get_next() == [8.989] assert not result.has_next() result.close() -def test_node(establish_connection): - conn, db = establish_connection +def test_node(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a") assert result.has_next() n = result.get_next() - assert (len(n) == 1) + assert len(n) == 1 n = n[0] - assert (n['_label'] == 'person') - assert (n['ID'] == 0) - assert (n['fName'] == 'Alice') - assert (n['gender'] == 1) - assert (n['isStudent'] == True) - assert (n['eyeSight'] == 5.0) - assert (n['birthdate'] == datetime.date(1900, 1, 1)) - assert (n['registerTime'] == datetime.datetime(2011, 8, 20, 11, 25, 30)) - assert (n['lastJobDuration'] == datetime.timedelta( - days=1082, seconds=46920)) - assert (n['courseScoresPerTerm'] == [[10, 8], [6, 7, 8]]) - assert (n['usedNames'] == ['Aida']) + assert n["_label"] == "person" + assert n["ID"] == 0 + assert n["fName"] == "Alice" + assert n["gender"] == 1 + assert n["isStudent"] is True + assert n["eyeSight"] == 5.0 + assert n["birthdate"] == datetime.date(1900, 1, 1) + assert n["registerTime"] == datetime.datetime(2011, 8, 20, 11, 25, 30) + assert n["lastJobDuration"] == datetime.timedelta(days=1082, seconds=46920) + assert n["courseScoresPerTerm"] == [[10, 8], [6, 7, 8]] + assert n["usedNames"] == ["Aida"] assert not result.has_next() result.close() -def test_rel(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (p:person)-[r:workAt]->(o:organisation) WHERE p.ID = 5 RETURN p, r, o") +def test_rel(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (p:person)-[r:workAt]->(o:organisation) WHERE p.ID = 5 RETURN p, r, o") assert result.has_next() n = result.get_next() - assert (len(n) == 3) + assert len(n) == 3 p = n[0] r = n[1] o = n[2] - assert (p['_label'] == 'person') - assert (p['ID'] == 5) - assert (o['_label'] == 'organisation') - assert (o['ID'] == 6) - assert (r['year'] == 2010) - assert (r['_src'] == p['_id']) - assert (r['_dst'] == o['_id']) - assert (r['_label'] == 'workAt') + assert p["_label"] == "person" + assert p["ID"] == 5 + assert o["_label"] == "organisation" + assert o["ID"] == 6 + assert r["year"] == 2010 + assert r["_src"] == p["_id"] + assert r["_dst"] == o["_id"] + assert r["_label"] == "workAt" assert not result.has_next() result.close() -def test_struct(establish_connection): - conn, db = establish_connection - result = conn.execute( - 'MATCH (m:movies) WHERE m.name="Roma" RETURN m.description') +def test_struct(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute('MATCH (m:movies) WHERE m.name="Roma" RETURN m.description') assert result.has_next() n = result.get_next() - assert (len(n) == 1) + assert len(n) == 1 description = n[0] print(description) - assert (description['rating'] == 1223) - assert (description['views'] == 10003) - assert (description['release'] == - datetime.datetime(2011, 2, 11, 16, 44, 22)) - assert (description['release_ns'] == - datetime.datetime(2011, 2, 11, 16, 44, 22, 123456)) - assert (description['release_ms'] == - datetime.datetime(2011, 2, 11, 16, 44, 22, 123000)) - assert (description['release_sec'] == - datetime.datetime(2011, 2, 11, 16, 44, 22)) - assert (description['release_tz'] == - datetime.datetime(2011, 2, 11, 16, 44, 22, 123456, pytz.UTC)) - assert (description['film'] == datetime.date(2013, 2, 22)) - assert (description['stars'] == 100) - assert (description['u8'] == 1) - assert (description['u16'] == 15) - assert (description['u32'] == 200) - assert (description['u64'] == 4) - assert (description['hugedata'] == -15) + assert description["rating"] == 1223 + assert description["views"] == 10003 + assert description["release"] == datetime.datetime(2011, 2, 11, 16, 44, 22) + assert description["release_ns"] == datetime.datetime(2011, 2, 11, 16, 44, 22, 123456) + assert description["release_ms"] == datetime.datetime(2011, 2, 11, 16, 44, 22, 123000) + assert description["release_sec"] == datetime.datetime(2011, 2, 11, 16, 44, 22) + assert description["release_tz"] == datetime.datetime(2011, 2, 11, 16, 44, 22, 123456, pytz.UTC) + assert description["film"] == datetime.date(2013, 2, 22) + assert description["stars"] == 100 + assert description["u8"] == 1 + assert description["u16"] == 15 + assert description["u32"] == 200 + assert description["u64"] == 4 + assert description["hugedata"] == -15 assert not result.has_next() result.close() -def test_recursive_rel(establish_connection): - conn, db = establish_connection - result = conn.execute( - "MATCH (a:person)-[e:studyAt*1..1]->(b:organisation) WHERE a.fName = 'Alice' RETURN e;" - ) +def test_recursive_rel(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person)-[e:studyAt*1..1]->(b:organisation) WHERE a.fName = 'Alice' RETURN e;") assert result.has_next() n = result.get_next() - assert (len(n) == 1) + assert len(n) == 1 e = n[0] - assert ("_nodes" in e) - assert ("_rels" in e) - assert (len(e["_nodes"]) == 0) - assert (len(e["_rels"]) == 1) + assert "_nodes" in e + assert "_rels" in e + assert len(e["_nodes"]) == 0 + assert len(e["_rels"]) == 1 rel = e["_rels"][0] - excepted_rel = {'_src': {'offset': 0, 'table': 0}, - '_dst': {'offset': 0, 'table': 1}, - '_label': 'studyAt', - 'year': 2021, - 'places': ['wwAewsdndweusd', 'wek'], - 'length': 5, 'level': 5, 'code': 9223372036854775808, 'temprature':32800, - 'ulength':33768, 'ulevel': 250, 'hugedata': 1844674407370955161811111111, - } - assert (rel == excepted_rel) + excepted_rel = { + "_src": {"offset": 0, "table": 0}, + "_dst": {"offset": 0, "table": 1}, + "_label": "studyAt", + "year": 2021, + "places": ["wwAewsdndweusd", "wek"], + "length": 5, + "level": 5, + "code": 9223372036854775808, + "temprature": 32800, + "ulength": 33768, + "ulevel": 250, + "hugedata": 1844674407370955161811111111, + } + assert rel == excepted_rel assert not result.has_next() result.close() -def test_rdf_variant(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:T_l) RETURN a.val ORDER BY a.id") - assert result.has_next() - assert result.get_next() == [12] - assert result.has_next() - assert result.get_next() == [43] - assert result.has_next() - assert result.get_next() == [33] - assert result.has_next() - assert result.get_next() == [2] - assert result.has_next() - assert result.get_next() == [90] - assert result.has_next() - assert result.get_next() == [77] - assert result.has_next() - assert result.get_next() == [12] - assert result.has_next() - assert result.get_next() == [1] - assert result.has_next() - float_result = result.get_next()[0] - assert abs(float_result - 4.4) < 0.00001 - assert result.has_next() - float_result = result.get_next()[0] - assert abs(float_result - 1.2) < 0.00001 - assert result.has_next() - assert result.get_next() == [True] - assert result.has_next() - assert result.get_next() == ["hhh"] - assert result.has_next() - assert result.get_next() == [datetime.date(2024, 1, 1)] - assert result.has_next() - assert result.get_next() == [datetime.datetime(2024, 1, 1, 11, 25, 30)] - assert result.has_next() - assert result.get_next() == [datetime.timedelta(days=2)] - assert result.has_next() - result_blob = result.get_next()[0] - assert len(result_blob) == 1 - assert result_blob[0] == 0xB2 - assert not result.has_next() - result.close() - result = conn.execute("DROP RDFGraph T;") - result.close() + +def test_rdf_variant(conn_db_readwrite: ConnDB) -> None: + conn, db = conn_db_readwrite + + with conn.execute("MATCH (a:T_l) RETURN a.val ORDER BY a.id") as result: + assert result.has_next() + assert result.get_next() == [12] + assert result.has_next() + assert result.get_next() == [43] + assert result.has_next() + assert result.get_next() == [33] + assert result.has_next() + assert result.get_next() == [2] + assert result.has_next() + assert result.get_next() == [90] + assert result.has_next() + assert result.get_next() == [77] + assert result.has_next() + assert result.get_next() == [12] + assert result.has_next() + assert result.get_next() == [1] + assert result.has_next() + + float_result = result.get_next()[0] + assert abs(float_result - 4.4) < 0.00001 + assert result.has_next() + + float_result = result.get_next()[0] + assert abs(float_result - 1.2) < 0.00001 + assert result.has_next() + assert result.get_next() == [True] + assert result.has_next() + assert result.get_next() == ["hhh"] + assert result.has_next() + assert result.get_next() == [datetime.date(2024, 1, 1)] + assert result.has_next() + assert result.get_next() == [datetime.datetime(2024, 1, 1, 11, 25, 30)] + assert result.has_next() + assert result.get_next() == [datetime.timedelta(days=2)] + assert result.has_next() + + result_blob = result.get_next()[0] + assert len(result_blob) == 1 + assert result_blob[0] == 0xB2 + assert not result.has_next() + + with conn.execute("DROP RDFGraph T;") as result: + result.close() diff --git a/tools/python_api/test/test_df.py b/tools/python_api/test/test_df.py index 180b7621364..34293aba2f4 100644 --- a/tools/python_api/test/test_df.py +++ b/tools/python_api/test/test_df.py @@ -1,146 +1,246 @@ +from __future__ import annotations + import datetime -import pytz import math -import sys from decimal import Decimal +from typing import Any from uuid import UUID import kuzu -from pandas import Timestamp, Timedelta, isna +import pytz +from pandas import Timedelta, Timestamp +from type_aliases import ConnDB -def test_to_df(establish_connection): - conn, db = establish_connection +def test_to_df(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly - def _test_person_to_df(conn): + def _test_person_to_df(conn: kuzu.Connection) -> None: query = "MATCH (p:person) return p.* ORDER BY p.ID" pd = conn.execute(query).get_as_df() - assert pd['p.ID'].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] - assert str(pd['p.ID'].dtype) == "int64" - assert pd['p.fName'].tolist() == ["Alice", "Bob", "Carol", "Dan", "Elizabeth", "Farooq", "Greg", - "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"] - assert str(pd['p.fName'].dtype) == "object" - assert pd['p.gender'].tolist() == [1, 2, 1, 2, 1, 2, 2, 2] - assert str(pd['p.gender'].dtype) == "int64" - assert pd['p.isStudent'].tolist() == [True, True, False, False, False, True, False, False] - assert str(pd['p.isStudent'].dtype) == "bool" - assert pd['p.eyeSight'].tolist() == [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9] - assert str(pd['p.eyeSight'].dtype) == "float64" - assert pd['p.birthdate'].tolist() == [Timestamp('1900-01-01'), Timestamp('1900-01-01'), - Timestamp('1940-06-22'), Timestamp('1950-07-23 '), - Timestamp('1980-10-26'), Timestamp('1980-10-26'), - Timestamp('1980-10-26'), Timestamp('1990-11-27')] - assert str(pd['p.birthdate'].dtype) == "datetime64[us]" - assert pd['p.registerTime'].tolist() == [Timestamp('2011-08-20 11:25:30'), - Timestamp('2008-11-03 15:25:30.000526'), - Timestamp('1911-08-20 02:32:21'), Timestamp('2031-11-30 12:25:30'), - Timestamp('1976-12-23 11:21:42'), - Timestamp('1972-07-31 13:22:30.678559'), - Timestamp('1976-12-23 04:41:42'), Timestamp('2023-02-21 13:25:30')] - assert str(pd['p.registerTime'].dtype) == "datetime64[us]" - assert pd['p.lastJobDuration'].tolist() == [Timedelta('1082 days 13:02:00'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), Timedelta('0 days 00:18:00.024000'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('1082 days 13:02:00')] - assert str(pd['p.lastJobDuration'].dtype) == "timedelta64[ns]" - assert pd['p.workedHours'].tolist() == [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], - [10, 11, 12, 3, 4, 5, 6, 7]] - assert str(pd['p.workedHours'].dtype) == "object" - assert pd['p.usedNames'].tolist() == [["Aida"], ['Bobby'], ['Carmen', 'Fred'], - ['Wolfeschlegelstein', 'Daniel'], ['Ein'], ['Fesdwe'], ['Grad'], - ['Ad', 'De', 'Hi', 'Kye', 'Orlan']] - assert str(pd['p.usedNames'].dtype) == "object" - assert pd['p.courseScoresPerTerm'].tolist() == [[[10, 8], [6, 7, 8]], [[8, 9], [9, 10]], [[8, 10]], - [[7, 4], [8, 8], [9]], [[6], [7], [8]], [[8]], [[10]], - [[7], [10], [6, 7]]] - assert str(pd['p.courseScoresPerTerm'].dtype) == "object" - assert pd['p.grades'].tolist() == [[96, 54, 86, 92], [98, 42, 93, 88], [91, 75, 21, 95], [76, 88, 99, 89], - [96, 59, 65, 88], [80, 78, 34, 83], [43, 83, 67, 43], [77, 64, 100, 54]] - assert str(pd['p.grades'].dtype) == "object" + assert pd["p.ID"].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] + assert str(pd["p.ID"].dtype) == "int64" + assert pd["p.fName"].tolist() == [ + "Alice", + "Bob", + "Carol", + "Dan", + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ] + assert str(pd["p.fName"].dtype) == "object" + assert pd["p.gender"].tolist() == [1, 2, 1, 2, 1, 2, 2, 2] + assert str(pd["p.gender"].dtype) == "int64" + assert pd["p.isStudent"].tolist() == [ + True, + True, + False, + False, + False, + True, + False, + False, + ] + assert str(pd["p.isStudent"].dtype) == "bool" + assert pd["p.eyeSight"].tolist() == [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9] + assert str(pd["p.eyeSight"].dtype) == "float64" + assert pd["p.birthdate"].tolist() == [ + Timestamp("1900-01-01"), + Timestamp("1900-01-01"), + Timestamp("1940-06-22"), + Timestamp("1950-07-23 "), + Timestamp("1980-10-26"), + Timestamp("1980-10-26"), + Timestamp("1980-10-26"), + Timestamp("1990-11-27"), + ] + assert str(pd["p.birthdate"].dtype) == "datetime64[us]" + assert pd["p.registerTime"].tolist() == [ + Timestamp("2011-08-20 11:25:30"), + Timestamp("2008-11-03 15:25:30.000526"), + Timestamp("1911-08-20 02:32:21"), + Timestamp("2031-11-30 12:25:30"), + Timestamp("1976-12-23 11:21:42"), + Timestamp("1972-07-31 13:22:30.678559"), + Timestamp("1976-12-23 04:41:42"), + Timestamp("2023-02-21 13:25:30"), + ] + assert str(pd["p.registerTime"].dtype) == "datetime64[us]" + assert pd["p.lastJobDuration"].tolist() == [ + Timedelta("1082 days 13:02:00"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("0 days 00:18:00.024000"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("1082 days 13:02:00"), + ] + assert str(pd["p.lastJobDuration"].dtype) == "timedelta64[ns]" + assert pd["p.workedHours"].tolist() == [ + [10, 5], + [12, 8], + [4, 5], + [1, 9], + [2], + [3, 4, 5, 6, 7], + [1], + [10, 11, 12, 3, 4, 5, 6, 7], + ] + assert str(pd["p.workedHours"].dtype) == "object" + assert pd["p.usedNames"].tolist() == [ + ["Aida"], + ["Bobby"], + ["Carmen", "Fred"], + ["Wolfeschlegelstein", "Daniel"], + ["Ein"], + ["Fesdwe"], + ["Grad"], + ["Ad", "De", "Hi", "Kye", "Orlan"], + ] + assert str(pd["p.usedNames"].dtype) == "object" + assert pd["p.courseScoresPerTerm"].tolist() == [ + [[10, 8], [6, 7, 8]], + [[8, 9], [9, 10]], + [[8, 10]], + [[7, 4], [8, 8], [9]], + [[6], [7], [8]], + [[8]], + [[10]], + [[7], [10], [6, 7]], + ] + assert str(pd["p.courseScoresPerTerm"].dtype) == "object" + assert pd["p.grades"].tolist() == [ + [96, 54, 86, 92], + [98, 42, 93, 88], + [91, 75, 21, 95], + [76, 88, 99, 89], + [96, 59, 65, 88], + [80, 78, 34, 83], + [43, 83, 67, 43], + [77, 64, 100, 54], + ] + assert str(pd["p.grades"].dtype) == "object" expected_values = [1.731, 0.99, 1.00, 1.30, 1.463, 1.51, 1.6, 1.323] - actual_values = pd['p.height'].tolist() + actual_values = pd["p.height"].tolist() for expected, actual in zip(expected_values, actual_values): assert math.isclose(actual, expected, rel_tol=1e-5) - assert str(pd['p.height'].dtype) == "float32" + assert str(pd["p.height"].dtype) == "float32" - def _test_study_at_to_df(conn): + def _test_study_at_to_df(conn: kuzu.Connection) -> None: query = "MATCH (p:person)-[r:studyAt]->(o:organisation) return r.* order by r.length;" pd = conn.execute(query).get_as_df() - assert pd['r.year'].tolist() == [2021, 2020, 2020] - assert str(pd['r.year'].dtype) == "int64" - assert pd['r.places'].tolist() == [["wwAewsdndweusd", "wek"], ["awndsnjwejwen", "isuhuwennjnuhuhuwewe"], - ["anew", "jsdnwusklklklwewsd"]] - assert str(pd['r.places'].dtype) == "object" - assert pd['r.length'].tolist() == [5, 22, 55] - assert str(pd['r.length'].dtype) == "int16" - assert pd['r.level'].tolist() == [5, 2, 120] - assert str(pd['r.level'].dtype) == "int8" - assert pd['r.code'].tolist() == [9223372036854775808, 23, 6689] - assert str(pd['r.code'].dtype) == "uint64" - assert pd['r.temprature'].tolist() == [32800, 20, 1] - assert str(pd['r.temprature'].dtype) == "uint32" - assert pd['r.ulength'].tolist() == [33768, 180, 90] - assert str(pd['r.ulength'].dtype) == "uint16" - assert pd['r.ulevel'].tolist() == [250, 12, 220] - assert str(pd['r.ulevel'].dtype) == "uint8" - assert pd['r.hugedata'].tolist() == [1.8446744073709552e+27, -15.0, -1.8446744073709552e+21] - assert str(pd['r.hugedata'].dtype) == "float64" + assert pd["r.year"].tolist() == [2021, 2020, 2020] + assert str(pd["r.year"].dtype) == "int64" + assert pd["r.places"].tolist() == [ + ["wwAewsdndweusd", "wek"], + ["awndsnjwejwen", "isuhuwennjnuhuhuwewe"], + ["anew", "jsdnwusklklklwewsd"], + ] + assert str(pd["r.places"].dtype) == "object" + assert pd["r.length"].tolist() == [5, 22, 55] + assert str(pd["r.length"].dtype) == "int16" + assert pd["r.level"].tolist() == [5, 2, 120] + assert str(pd["r.level"].dtype) == "int8" + assert pd["r.code"].tolist() == [9223372036854775808, 23, 6689] + assert str(pd["r.code"].dtype) == "uint64" + assert pd["r.temprature"].tolist() == [32800, 20, 1] + assert str(pd["r.temprature"].dtype) == "uint32" + assert pd["r.ulength"].tolist() == [33768, 180, 90] + assert str(pd["r.ulength"].dtype) == "uint16" + assert pd["r.ulevel"].tolist() == [250, 12, 220] + assert str(pd["r.ulevel"].dtype) == "uint8" + assert pd["r.hugedata"].tolist() == [ + 1.8446744073709552e27, + -15.0, + -1.8446744073709552e21, + ] + assert str(pd["r.hugedata"].dtype) == "float64" - def _test_timestamps_to_df(conn): + def _test_timestamps_to_df(conn: kuzu.Connection) -> None: query = ( - "RETURN cast(\"2012-01-01 11:12:12.12345\", \"TIMESTAMP_NS\") as A, cast(\"2012-01-01 11:12:12.12345\", " - "\"TIMESTAMP_MS\") as B, cast(\"2012-01-01 11:12:12.12345\", \"TIMESTAMP_SEC\") as C, " - "cast(\"2012-01-01 11:12:12.12345\", \"TIMESTAMP_TZ\") as D") + 'RETURN cast("2012-01-01 11:12:12.12345", "TIMESTAMP_NS") as A, cast("2012-01-01 11:12:12.12345", ' + '"TIMESTAMP_MS") as B, cast("2012-01-01 11:12:12.12345", "TIMESTAMP_SEC") as C, ' + 'cast("2012-01-01 11:12:12.12345", "TIMESTAMP_TZ") as D' + ) pd = conn.execute(query).get_as_df() - assert pd['A'].tolist() == [Timestamp('2012-01-01 11:12:12.123450')] - assert pd['B'].tolist() == [Timestamp('2012-01-01 11:12:12.123000')] - assert pd['C'].tolist() == [Timestamp('2012-01-01 11:12:12')] - assert pd['D'].tolist() == [Timestamp('2012-01-01 11:12:12.123450')] + assert pd["A"].tolist() == [Timestamp("2012-01-01 11:12:12.123450")] + assert pd["B"].tolist() == [Timestamp("2012-01-01 11:12:12.123000")] + assert pd["C"].tolist() == [Timestamp("2012-01-01 11:12:12")] + assert pd["D"].tolist() == [Timestamp("2012-01-01 11:12:12.123450")] - def _test_movies_to_df(conn): + def _test_movies_to_df(conn: kuzu.Connection) -> None: query = "MATCH (m:movies) return m.* order by m.length;" pd = conn.execute(query).get_as_df() - assert pd['m.length'].tolist() == [126, 298, 2544] - assert str(pd['m.length'].dtype) == "int32" - assert pd['m.description'].tolist() == [{'rating': 5.3, 'stars': 2, 'views': 152, - 'release': datetime.datetime(2011, 8, 20, 11, 25, 30), - 'release_ns': datetime.datetime(2011, 8, 20, 11, 25, 30, 123456), - 'release_ms': datetime.datetime(2011, 8, 20, 11, 25, 30, 123000), - 'release_sec': datetime.datetime(2011, 8, 20, 11, 25, 30), - 'release_tz': datetime.datetime(2011, 8, 20, 11, 25, 30, 123456, - pytz.UTC), - 'film': datetime.date(2012, 5, 11), 'u8': 220, 'u16': 20, 'u32': 1, - 'u64': 180, 'hugedata': Decimal('1844674407370955161811111111')}, - {'rating': 1223.0, 'stars': 100, 'views': 10003, - 'release': datetime.datetime(2011, 2, 11, 16, 44, 22), - 'release_ns': datetime.datetime(2011, 2, 11, 16, 44, 22, 123456), - 'release_ms': datetime.datetime(2011, 2, 11, 16, 44, 22, 123000), - 'release_sec': datetime.datetime(2011, 2, 11, 16, 44, 22), - 'release_tz': datetime.datetime(2011, 2, 11, 16, 44, 22, 123456, - pytz.UTC), - 'film': datetime.date(2013, 2, 22), 'u8': 1, 'u16': 15, - 'u32': 200, - 'u64': 4, 'hugedata': Decimal(-15)}, - {'rating': 7.0, 'stars': 10, 'views': 982, - 'release': datetime.datetime(2018, 11, 13, 13, 33, 11), - 'release_ns': datetime.datetime(2018, 11, 13, 13, 33, 11, 123456), - 'release_ms': datetime.datetime(2018, 11, 13, 13, 33, 11, 123000), - 'release_sec': datetime.datetime(2018, 11, 13, 13, 33, 11), - 'release_tz': datetime.datetime(2018, 11, 13, 13, 33, 11, 123456, - pytz.UTC), - 'film': datetime.date(2014, 9, 12), 'u8': 12, - 'u16': 120, 'u32': 55, - 'u64': 1, 'hugedata': Decimal(-1844674407370955161511)}] - assert str(pd['m.description'].dtype) == "object" - assert pd['m.content'].tolist() == [b'\xaa\xabinteresting\x0b', b'pure ascii characters', b'\xab\xcd'] - assert str(pd['m.content'].dtype) == "object" - assert pd['m.audience'].tolist() == [{'audience1': 52, 'audience53': 42}, {}, {'audience1': 33}] - assert str(pd['m.audience'].dtype) == "object" - assert pd['m.grade'].tolist() == [True, 254.0, 8.989] - assert str(pd['m.grade'].dtype) == "object" + assert pd["m.length"].tolist() == [126, 298, 2544] + assert str(pd["m.length"].dtype) == "int32" + assert pd["m.description"].tolist() == [ + { + "rating": 5.3, + "stars": 2, + "views": 152, + "release": datetime.datetime(2011, 8, 20, 11, 25, 30), + "release_ns": datetime.datetime(2011, 8, 20, 11, 25, 30, 123456), + "release_ms": datetime.datetime(2011, 8, 20, 11, 25, 30, 123000), + "release_sec": datetime.datetime(2011, 8, 20, 11, 25, 30), + "release_tz": datetime.datetime(2011, 8, 20, 11, 25, 30, 123456, pytz.UTC), + "film": datetime.date(2012, 5, 11), + "u8": 220, + "u16": 20, + "u32": 1, + "u64": 180, + "hugedata": Decimal("1844674407370955161811111111"), + }, + { + "rating": 1223.0, + "stars": 100, + "views": 10003, + "release": datetime.datetime(2011, 2, 11, 16, 44, 22), + "release_ns": datetime.datetime(2011, 2, 11, 16, 44, 22, 123456), + "release_ms": datetime.datetime(2011, 2, 11, 16, 44, 22, 123000), + "release_sec": datetime.datetime(2011, 2, 11, 16, 44, 22), + "release_tz": datetime.datetime(2011, 2, 11, 16, 44, 22, 123456, pytz.UTC), + "film": datetime.date(2013, 2, 22), + "u8": 1, + "u16": 15, + "u32": 200, + "u64": 4, + "hugedata": Decimal(-15), + }, + { + "rating": 7.0, + "stars": 10, + "views": 982, + "release": datetime.datetime(2018, 11, 13, 13, 33, 11), + "release_ns": datetime.datetime(2018, 11, 13, 13, 33, 11, 123456), + "release_ms": datetime.datetime(2018, 11, 13, 13, 33, 11, 123000), + "release_sec": datetime.datetime(2018, 11, 13, 13, 33, 11), + "release_tz": datetime.datetime(2018, 11, 13, 13, 33, 11, 123456, pytz.UTC), + "film": datetime.date(2014, 9, 12), + "u8": 12, + "u16": 120, + "u32": 55, + "u64": 1, + "hugedata": Decimal(-1844674407370955161511), + }, + ] + assert str(pd["m.description"].dtype) == "object" + assert pd["m.content"].tolist() == [ + b"\xaa\xabinteresting\x0b", + b"pure ascii characters", + b"\xab\xcd", + ] + assert str(pd["m.content"].dtype) == "object" + assert pd["m.audience"].tolist() == [ + {"audience1": 52, "audience53": 42}, + {}, + {"audience1": 33}, + ] + assert str(pd["m.audience"].dtype) == "object" + assert pd["m.grade"].tolist() == [True, 254.0, 8.989] + assert str(pd["m.grade"].dtype) == "object" _test_person_to_df(conn) conn.set_max_threads_for_exec(2) @@ -149,65 +249,112 @@ def _test_movies_to_df(conn): _test_timestamps_to_df(conn) -def test_df_multiple_times(establish_connection): - conn, _ = establish_connection +def test_df_multiple_times(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:person) return p.ID ORDER BY p.ID" res = conn.execute(query) df = res.get_as_df() df_2 = res.get_as_df() df_3 = res.get_as_df() - assert df['p.ID'].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] - assert df_2['p.ID'].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] - assert df_3['p.ID'].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] + assert df["p.ID"].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] + assert df_2["p.ID"].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] + assert df_3["p.ID"].tolist() == [0, 2, 3, 5, 7, 8, 9, 10] -def test_df_get_node(establish_connection): - conn, _ = establish_connection +def test_df_get_node(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:person) return p" res = conn.execute(query) df = res.get_as_df() - p_list = df['p'].tolist() + p_list = df["p"].tolist() assert len(p_list) == 8 - ground_truth = { - 'ID': [0, 2, 3, 5, 7, 8, 9, 10], - 'fName': ["Alice", "Bob", "Carol", "Dan", "Elizabeth", "Farooq", "Greg", - "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"], - 'gender': [1, 2, 1, 2, 1, 2, 2, 2], - 'isStudent': [True, True, False, False, False, True, False, False], - 'eyeSight': [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], - 'birthdate': [datetime.date(1900, 1, 1), datetime.date(1900, 1, 1), - datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), - datetime.date(1980, 10, 26), datetime.date(1980, 10, 26), - datetime.date(1980, 10, 26), datetime.date(1990, 11, 27)], - 'registerTime': [Timestamp('2011-08-20 11:25:30'), - Timestamp('2008-11-03 15:25:30.000526'), - Timestamp( - '1911-08-20 02:32:21'), Timestamp('2031-11-30 12:25:30'), - Timestamp('1976-12-23 11:21:42'), - Timestamp('1972-07-31 13:22:30.678559'), - Timestamp('1976-12-23 04:41:42'), Timestamp('2023-02-21 13:25:30')], - 'lastJobDuration': [Timedelta('1082 days 13:02:00'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), Timedelta( - '0 days 00:18:00.024000'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('1082 days 13:02:00')], - 'workedHours': [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], - [10, 11, 12, 3, 4, 5, 6, 7]], - 'usedNames': [["Aida"], ['Bobby'], ['Carmen', 'Fred'], - ['Wolfeschlegelstein', 'Daniel'], [ - 'Ein'], ['Fesdwe'], ['Grad'], - ['Ad', 'De', 'Hi', 'Kye', 'Orlan']], - 'courseScoresPerTerm': [[[10, 8], [6, 7, 8]], [[8, 9], [9, 10]], [[8, 10]], - [[7, 4], [8, 8], [9]], [ - [6], [7], [8]], [[8]], [[10]], - [[7], [10], [6, 7]]], - '_label': ['person', 'person', 'person', 'person', 'person', 'person', - 'person', 'person'], + ground_truth: dict[str, list[Any]] = { + "ID": [0, 2, 3, 5, 7, 8, 9, 10], + "fName": [ + "Alice", + "Bob", + "Carol", + "Dan", + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ], + "gender": [1, 2, 1, 2, 1, 2, 2, 2], + "isStudent": [True, True, False, False, False, True, False, False], + "eyeSight": [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], + "birthdate": [ + datetime.date(1900, 1, 1), + datetime.date(1900, 1, 1), + datetime.date(1940, 6, 22), + datetime.date(1950, 7, 23), + datetime.date(1980, 10, 26), + datetime.date(1980, 10, 26), + datetime.date(1980, 10, 26), + datetime.date(1990, 11, 27), + ], + "registerTime": [ + Timestamp("2011-08-20 11:25:30"), + Timestamp("2008-11-03 15:25:30.000526"), + Timestamp("1911-08-20 02:32:21"), + Timestamp("2031-11-30 12:25:30"), + Timestamp("1976-12-23 11:21:42"), + Timestamp("1972-07-31 13:22:30.678559"), + Timestamp("1976-12-23 04:41:42"), + Timestamp("2023-02-21 13:25:30"), + ], + "lastJobDuration": [ + Timedelta("1082 days 13:02:00"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("0 days 00:18:00.024000"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("1082 days 13:02:00"), + ], + "workedHours": [ + [10, 5], + [12, 8], + [4, 5], + [1, 9], + [2], + [3, 4, 5, 6, 7], + [1], + [10, 11, 12, 3, 4, 5, 6, 7], + ], + "usedNames": [ + ["Aida"], + ["Bobby"], + ["Carmen", "Fred"], + ["Wolfeschlegelstein", "Daniel"], + ["Ein"], + ["Fesdwe"], + ["Grad"], + ["Ad", "De", "Hi", "Kye", "Orlan"], + ], + "courseScoresPerTerm": [ + [[10, 8], [6, 7, 8]], + [[8, 9], [9, 10]], + [[8, 10]], + [[7, 4], [8, 8], [9]], + [[6], [7], [8]], + [[8]], + [[10]], + [[7], [10], [6, 7]], + ], + "_label": [ + "person", + "person", + "person", + "person", + "person", + "person", + "person", + "person", + ], } for i in range(len(p_list)): p = p_list[i] @@ -215,123 +362,179 @@ def test_df_get_node(establish_connection): assert p[key] == ground_truth[key][i] -def test_df_get_node_rel(establish_connection): - conn, _ = establish_connection - res = conn.execute( - "MATCH (p:person)-[r:workAt]->(o:organisation) RETURN p, r, o ORDER BY p.fName") +def test_df_get_node_rel(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + res = conn.execute("MATCH (p:person)-[r:workAt]->(o:organisation) RETURN p, r, o ORDER BY p.fName") df = res.get_as_df() - p_list = df['p'].tolist() - o_list = df['o'].tolist() + p_list = df["p"].tolist() + o_list = df["o"].tolist() assert len(p_list) == 3 assert len(o_list) == 3 - ground_truth_p = { - 'ID': [3, 5, 7], - 'fName': ["Carol", "Dan", "Elizabeth"], - 'gender': [1, 2, 1], - 'isStudent': [False, False, False], - 'eyeSight': [5.0, 4.8, 4.7], - 'birthdate': [datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), - datetime.date(1980, 10, 26)], - 'registerTime': [Timestamp('1911-08-20 02:32:21'), Timestamp('2031-11-30 12:25:30'), - Timestamp('1976-12-23 11:21:42') - ], - 'lastJobDuration': [ - Timedelta('48 hours 24 minutes 11 seconds'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11')], - 'workedHours': [[4, 5], [1, 9], [2]], - 'usedNames': [["Carmen", "Fred"], ['Wolfeschlegelstein', 'Daniel'], ['Ein']], - 'courseScoresPerTerm': [[[8, 10]], [[7, 4], [8, 8], [9]], [[6], [7], [8]]], - '_label': ['person', 'person', 'person'], + ground_truth_p: dict[str, list[Any]] = { + "ID": [3, 5, 7], + "fName": ["Carol", "Dan", "Elizabeth"], + "gender": [1, 2, 1], + "isStudent": [False, False, False], + "eyeSight": [5.0, 4.8, 4.7], + "birthdate": [ + datetime.date(1940, 6, 22), + datetime.date(1950, 7, 23), + datetime.date(1980, 10, 26), + ], + "registerTime": [ + Timestamp("1911-08-20 02:32:21"), + Timestamp("2031-11-30 12:25:30"), + Timestamp("1976-12-23 11:21:42"), + ], + "lastJobDuration": [ + Timedelta("48 hours 24 minutes 11 seconds"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + ], + "workedHours": [[4, 5], [1, 9], [2]], + "usedNames": [["Carmen", "Fred"], ["Wolfeschlegelstein", "Daniel"], ["Ein"]], + "courseScoresPerTerm": [[[8, 10]], [[7, 4], [8, 8], [9]], [[6], [7], [8]]], + "_label": ["person", "person", "person"], } for i in range(len(p_list)): p = p_list[i] for key in ground_truth_p: assert p[key] == ground_truth_p[key][i] - ground_truth_o = {'ID': [4, 6, 6], - 'name': ['CsWork', 'DEsWork', 'DEsWork'], - 'orgCode': [934, 824, 824], - 'mark': [4.1, 4.1, 4.1], - 'score': [-100, 7, 7], - 'history': ['2 years 4 days 10 hours', '2 years 4 hours 22 us 34 minutes', - '2 years 4 hours 22 us 34 minutes'], - 'licenseValidInterval': [Timedelta(days=9414), - Timedelta(days=3, seconds=36000, microseconds=100000), - Timedelta(days=3, seconds=36000, microseconds=100000)], - 'rating': [0.78, 0.52, 0.52], - '_label': ['organisation', 'organisation', 'organisation'], - } + ground_truth_o: dict[str, list[Any]] = { + "ID": [4, 6, 6], + "name": ["CsWork", "DEsWork", "DEsWork"], + "orgCode": [934, 824, 824], + "mark": [4.1, 4.1, 4.1], + "score": [-100, 7, 7], + "history": [ + "2 years 4 days 10 hours", + "2 years 4 hours 22 us 34 minutes", + "2 years 4 hours 22 us 34 minutes", + ], + "licenseValidInterval": [ + Timedelta(days=9414), + Timedelta(days=3, seconds=36000, microseconds=100000), + Timedelta(days=3, seconds=36000, microseconds=100000), + ], + "rating": [0.78, 0.52, 0.52], + "_label": ["organisation", "organisation", "organisation"], + } for i in range(len(o_list)): - o = df['o'][i] + o = df["o"][i] for key in ground_truth_o: assert o[key] == ground_truth_o[key][i] - assert (df['r'][0]['year'] == 2015) - assert (df['r'][1]['year'] == 2010) - assert (df['r'][2]['year'] == 2015) + assert df["r"][0]["year"] == 2015 + assert df["r"][1]["year"] == 2010 + assert df["r"][2]["year"] == 2015 - for i in range(len(df['r'])): - assert (df['r'][i]['_src'] == df['p'][i]['_id']) - assert (df['r'][i]['_dst'] == df['o'][i]['_id']) + for i in range(len(df["r"])): + assert df["r"][i]["_src"] == df["p"][i]["_id"] + assert df["r"][i]["_dst"] == df["o"][i]["_id"] -def test_df_get_recursive_join(establish_connection): - conn, _ = establish_connection +def test_df_get_recursive_join(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly res = conn.execute( "MATCH (p:person)-[r:knows*1..2 (e, n | WHERE e.comments = ['rnme','m8sihsdnf2990nfiwf'])]-(m:person) WHERE " - "p.ID = 0 and m.ID = 0 RETURN r").get_as_df() - assert res['r'][0] == {'_nodes': [{'ID': 2, - '_id': {'offset': 1, 'table': 0}, - '_label': 'person', - 'age': 30, - 'birthdate': datetime.date(1900, 1, 1), - 'courseScoresPerTerm': [[8, 9], [9, 10]], - 'eyeSight': 5.1, - 'fName': 'Bob', - 'gender': 2, - 'grades': [98, 42, 93, 88], - 'height': 0.9900000095367432, - 'u': UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'), - 'isStudent': True, - 'isWorker': False, - 'lastJobDuration': datetime.timedelta(days=3750, seconds=46800, microseconds=24), - 'registerTime': datetime.datetime(2008, 11, 3, 15, 25, 30, 526), - 'usedNames': ['Bobby'], - 'workedHours': [12, 8]}], - '_rels': [{'_dst': {'offset': 1, 'table': 0}, - '_label': 'knows', - '_src': {'offset': 0, 'table': 0}, - 'comments': ['rnme', 'm8sihsdnf2990nfiwf'], - 'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(1986, 10, 21, 21, 8, 31, 521000), - 'notes': 1, - 'summary': {'locations': ["'toronto'", "'waterloo'"], - 'transfer': {'amount': [100, 200], - 'day': datetime.date(2021, 1, 2)}}, - 'someMap': {'a': 'b'}, - 'validInterval': datetime.timedelta(days=3750, seconds=46800, microseconds=24)}, - {'_dst': {'offset': 0, 'table': 0}, - '_label': 'knows', - '_src': {'offset': 1, 'table': 0}, - 'comments': ['rnme', 'm8sihsdnf2990nfiwf'], - 'date': datetime.date(2021, 6, 30), - 'meetTime': datetime.datetime(1986, 10, 21, 21, 8, 31, 521000), - 'notes': 1, - 'summary': {'locations': ["'toronto'", "'waterloo'"], - 'transfer': {'amount': [100, 200], - 'day': datetime.date(2021, 1, 2)}}, - 'someMap': {'a': 'b'}, - 'validInterval': datetime.timedelta(days=3750, seconds=46800, microseconds=24)}]} + "p.ID = 0 and m.ID = 0 RETURN r" + ).get_as_df() + assert res["r"][0] == { + "_nodes": [ + { + "ID": 2, + "_id": {"offset": 1, "table": 0}, + "_label": "person", + "age": 30, + "birthdate": datetime.date(1900, 1, 1), + "courseScoresPerTerm": [[8, 9], [9, 10]], + "eyeSight": 5.1, + "fName": "Bob", + "gender": 2, + "grades": [98, 42, 93, 88], + "height": 0.9900000095367432, + "u": UUID("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12"), + "isStudent": True, + "isWorker": False, + "lastJobDuration": datetime.timedelta(days=3750, seconds=46800, microseconds=24), + "registerTime": datetime.datetime(2008, 11, 3, 15, 25, 30, 526), + "usedNames": ["Bobby"], + "workedHours": [12, 8], + } + ], + "_rels": [ + { + "_dst": {"offset": 1, "table": 0}, + "_label": "knows", + "_src": {"offset": 0, "table": 0}, + "comments": ["rnme", "m8sihsdnf2990nfiwf"], + "date": datetime.date(2021, 6, 30), + "meetTime": datetime.datetime(1986, 10, 21, 21, 8, 31, 521000), + "notes": 1, + "summary": { + "locations": ["'toronto'", "'waterloo'"], + "transfer": { + "amount": [100, 200], + "day": datetime.date(2021, 1, 2), + }, + }, + "someMap": {"a": "b"}, + "validInterval": datetime.timedelta(days=3750, seconds=46800, microseconds=24), + }, + { + "_dst": {"offset": 0, "table": 0}, + "_label": "knows", + "_src": {"offset": 1, "table": 0}, + "comments": ["rnme", "m8sihsdnf2990nfiwf"], + "date": datetime.date(2021, 6, 30), + "meetTime": datetime.datetime(1986, 10, 21, 21, 8, 31, 521000), + "notes": 1, + "summary": { + "locations": ["'toronto'", "'waterloo'"], + "transfer": { + "amount": [100, 200], + "day": datetime.date(2021, 1, 2), + }, + }, + "someMap": {"a": "b"}, + "validInterval": datetime.timedelta(days=3750, seconds=46800, microseconds=24), + }, + ], + } -def test_get_rdf_variant(establish_connection): - conn, _ = establish_connection - res = conn.execute( - "MATCH (a:T_l) RETURN a.val ORDER BY a.id").get_as_df() - assert res['a.val'].tolist() == [12, 43, 33, 2, 90, 77, 12, 1, 4.4, 1.2000000476837158, True, "hhh", - datetime.date(2024, 1, 1), - datetime.datetime(2024, 1, 1, 11, 25, 30), datetime.timedelta(days=2), b'\xb2'] +def test_get_rdf_variant(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + res = conn.execute("MATCH (a:T_l) RETURN a.val ORDER BY a.id").get_as_df() + assert res["a.val"].tolist() == [ + 12, + 43, + 33, + 2, + 90, + 77, + 12, + 1, + 4.4, + 1.2000000476837158, + True, + "hhh", + datetime.date(2024, 1, 1), + datetime.datetime(2024, 1, 1, 11, 25, 30), + datetime.timedelta(days=2), + b"\xb2", + ] + + +def test_get_df_unicode(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + res = conn.execute("MATCH (m:movies) RETURN m.name").get_as_df() + assert res["m.name"].tolist() == [ + "Sóló cón tu párejâ", + "The 😂😃🧘🏻‍♂️🌍🌦️🍞🚗 movie", + "Roma", + ] diff --git a/tools/python_api/test/test_df_pyarrow.py b/tools/python_api/test/test_df_pyarrow.py new file mode 100644 index 00000000000..4feca497638 --- /dev/null +++ b/tools/python_api/test/test_df_pyarrow.py @@ -0,0 +1,340 @@ +import pandas as pd, pyarrow as pa +import pytz +import struct, random, math +from datetime import datetime, timedelta +from pandas.arrays import ArrowExtensionArray as arrowtopd +import pytest +import kuzu +from type_aliases import ConnDB +from pathlib import Path + +def generate_primitive(dtype): + if (random.randrange(0, 5) == 0): + return None + if (dtype.startswith("bool")): + return random.randrange(0, 1) == 1 + if (dtype.startswith("int32")): + return random.randrange(-2147483648, 2147483647) + if (dtype.startswith("int64")): + return random.randrange(-9223372036854775808, 9223372036854775807) + if (dtype.startswith("uint64")): + return random.randrange(0, 18446744073709551615) + if (dtype.startswith("float32")): + random_bits = random.getrandbits(32) + random_bytes = struct.pack(' None: + db = kuzu.Database(tmp_path) + conn = kuzu.Connection(db) + establish_connection = (conn, db) + # stress tests primitive reading + sfs = [100, 2048, 4000, 9000, 16000] + threads = [1, 2, 5, 10] + for sf in sfs: + for thread in threads: + pyarrow_test_helper(establish_connection, sf, thread) + +def test_pyarrow_time(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + col1 = pa.array([1000123, 2000123, 3000123], type=pa.duration('s')) + col2 = pa.array([1000123000000, 2000123000000, 3000123000000], type=pa.duration('us')) + col3 = pa.array([1000123000000000, 2000123000000000, 3000123000000000], type=pa.duration('ns')) + col4 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.timestamp('s')) + col5 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.timestamp('s')) + col6 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.timestamp('ms')) + col7 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.timestamp('us')) + col8 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.timestamp('ns')) + col9 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.date32()) + col10 = pa.array([datetime(2012, 1, 20), datetime(2000, 12, 2), datetime(1987, 5, 27)], + type=pa.date64()) + # not implemented by pandas + # col11 = pa.array([(1, 2, 3), (4, 5, -6), (100, 200, 1000000000)], type=pa.month_day_nano_interval()) + # for some reason, pyarrow doesnt support the direct creation of pure month or pure datetime + # intervals, so that will remain untested for now + df = pd.DataFrame({ + 'col1': arrowtopd(col1), + 'col2': arrowtopd(col2), + 'col3': arrowtopd(col3), + 'col4': arrowtopd(col4), + 'col5': arrowtopd(col5), + 'col6': arrowtopd(col6), + 'col7': arrowtopd(col7), + 'col8': arrowtopd(col8), + 'col9': arrowtopd(col9), + 'col10': arrowtopd(col10) + #'col11': arrowtopd(col11) + }) + result = conn.execute('CALL READ_PANDAS(df) RETURN *').get_as_df() + for colname in ['col1', 'col2', 'col3']: + for expected, actual in zip(df[colname], result[colname]): + tmp1 = expected if type(expected) is timedelta else expected.to_pytimedelta() + tmp2 = actual if type(actual) is timedelta else actual.to_pytimedelta() + assert tmp1 == tmp2 + for colname in ['col4', 'col5', 'col6', 'col7', 'col8']: + for expected, actual in zip(df[colname], result[colname]): + tmp1 = expected if type(expected) is datetime else expected.to_pydatetime() + tmp2 = actual if type(actual) is datetime else actual.to_pydatetime() + assert tmp1 == tmp2 + for colname in ['col9', 'col10']: + for expected, actual in zip(df[colname], result[colname]): + assert datetime.combine(expected, datetime.min.time()) == actual.to_pydatetime() + +def generate_blob(length): + if (random.randint(0, 5) == 0): + return None + return random.getrandbits(8*length).to_bytes(length, 'little') + +def test_pyarrow_blob(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + # blobs, blob views, and fixed size blobs + random.seed(100) + index = pa.array(range(16000), type=pa.int64()) + col1 = pa.array([generate_blob(random.randint(10, 100)) for i in range(16000)], + type=pa.binary()) + col2 = pa.array([generate_blob(random.randint(10, 100)) for i in range(16000)], + type=pa.large_binary()) + col3 = pa.array([generate_blob(32) for i in range(16000)], + type=pa.binary(32)) + col4 = col1.view(pa.binary()) + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1' : arrowtopd(col1), + 'col2' : arrowtopd(col2), + 'col3' : arrowtopd(col3), + 'col4' : arrowtopd(col4) + }).sort_values(by=['index']) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index').get_as_df() + for colname in ['col1', 'col2', 'col3', 'col4']: + for expected, actual in zip(df[colname], result[colname]): + if is_null(expected) or is_null(actual): + assert is_null(expected) + assert is_null(actual) + else: + if bytes(expected) != bytes(actual): + print(expected) + print(actual) + print(df[colname]) + print(result[colname]) + print(colname) + assert bytes(expected) == bytes(actual) + +def generate_string(length): + if (random.randint(0, 5) == 0): + return None + return ''.join([random.choice('1234567890-=qwertyuiop[]\\asdfghjkl;\'zxcvbnm,./') + for i in range(length)]) + +def test_pyarrow_string(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + # blobs, blob views, and fixed size blobs + random.seed(100) + index = pa.array(range(16000), type=pa.int64()) + col1 = pa.array([generate_string(random.randint(10, 100)) for i in range(16000)], + type=pa.string()) + col2 = pa.array([generate_string(random.randint(10, 100)) for i in range(16000)], + type=pa.large_string()) + col3 = col1.view(pa.string()) + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1' : arrowtopd(col1), + 'col2' : arrowtopd(col2), + 'col3' : arrowtopd(col3), + }).sort_values(by=['index']) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index').get_as_df() + for colname in ['col1', 'col2', 'col3']: + for expected, actual in zip(df[colname], result[colname]): + if is_null(expected) or is_null(actual): + assert is_null(expected) + assert is_null(actual) + else: + assert str(expected) == str(actual) + +def test_pyarrow_dict(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + random.seed(100) + index = pa.array(range(2000), type=pa.int64()) + col1 = pa.array([random.randint(0, 1) for i in range(2000)], type=pa.int32()).dictionary_encode() + col2 = pa.array([random.randint(-20, 20) / 10 for i in range(2000)], type=pa.float64()).dictionary_encode() + #it seems arrow hasn't implemented dictionary encoding for nested types + #col3 = pa.array([ + # [generate_string(random.randint(10, 100)) for x in range(random.randint(10, 100))] + # for i in range(3000) + #], type=pa.list_(pa.string())).dictionary_encode() + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1' : arrowtopd(col1), + 'col2' : arrowtopd(col2) + }) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index').get_as_df() + for colname in ['col1', 'col2']: + for expected, actual in zip(df[colname], result[colname]): + assert expected == actual + +def test_pyarrow_list(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + random.seed(100) + datalength = 50 + childlength = 5 + index = pa.array(range(datalength)) + col1 = pa.array( + [[generate_primitive('int32[pyarrow]') for x in range(random.randint(1, childlength))] if random.randint(0, 5) == 0 else None for i in range(datalength)]) + col2 = pa.array( + [[[generate_primitive('int32[pyarrow]') for x in range(random.randint(1, childlength))] for y in range(1, childlength)] if random.randint(0, 5) == 0 else None for i in range(datalength)]) + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1': arrowtopd(col1), + 'col2': arrowtopd(col2) + }) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index') + idx = 0 + while result.has_next(): + assert idx < len(index) + nxt = result.get_next() + proc = [idx, col1[idx].as_py(), col2[idx].as_py()] + assert proc == nxt + idx += 1 + + assert idx == len(index) + +def test_pyarrow_struct(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + random.seed(100) + datalength = 4096 + index = pa.array(range(datalength)) + col1_plaindata = [{ + 'a': generate_primitive('int32[pyarrow]'), + 'b': { 'c': generate_string(10) } if random.randint(0, 5) != 0 else None + } if random.randint(0, 5) != 0 else None for i in range(datalength)] + col1 = pa.array(col1_plaindata, pa.struct([ + ('a', pa.int32()), + ('b', pa.struct([('c', pa.string())])) + ])) + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1': arrowtopd(col1) + }) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index') + idx = 0 + while result.has_next(): + assert idx < len(index) + nxt = result.get_next() + expected = [idx, col1[idx].as_py()] + assert expected == nxt + idx += 1 + + assert idx == len(index) + +def test_pyarrow_union(conn_db_readonly : ConnDB) -> None: + pytest.skip("unions are not very well supported by kuzu in general") + conn, db = conn_db_readonly + random.seed(100) + datalength = 4096 + index = pa.array(range(datalength)) + type_codes = pa.array([random.randint(0, 2) for i in range(datalength)], type=pa.int8()) + arr1 = pa.array([generate_primitive('int32[pyarrow]') for i in range(datalength)], type=pa.int32()) + arr2 = pa.array([generate_string(random.randint(1, 10)) for i in range(datalength)]) + arr3 = pa.array([[generate_primitive('float32[pyarrow]') for i in range(10)] for j in range(datalength)]) + col1 = pa.UnionArray.from_sparse(type_codes, [arr1, arr2, arr3]) + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1': arrowtopd(col1) + }) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index') + idx = 0 + while result.has_next(): + assert idx < len(index) + nxt = result.get_next() + expected = [idx, col1[idx].as_py()] + assert expected == nxt + idx += 1 + + assert idx == len(index) + +def test_pyarrow_map(conn_db_readonly : ConnDB) -> None: + conn, db = conn_db_readonly + random.seed(100) + datalength = 4096 + index = pa.array(range(datalength)) + keySet = range(100) + valueSet = 'abcdefghijklmnopqrstuvwxyz' + col1 = pa.array([ + {str(key) : ''.join(random.sample(valueSet, random.randint(0, len(valueSet)))) + for key in random.sample(keySet, random.randint(1, len(keySet)))} + if random.randint(0, 5) != 0 else None for i in range(datalength)], + type=pa.map_(pa.string(), pa.string())) + df = pd.DataFrame({ + 'index': arrowtopd(index), + 'col1': arrowtopd(col1)}) + result = conn.execute('CALL READ_PANDAS(df) RETURN * ORDER BY index') + idx = 0 + while result.has_next(): + assert idx < len(index) + nxt = result.get_next() + expected = [idx, None if col1[idx].as_py() is None else dict(col1[idx].as_py())] + assert expected == nxt + idx += 1 + + assert idx == len(index) diff --git a/tools/python_api/test/test_exception.py b/tools/python_api/test/test_exception.py index 46f493f4ae7..16fb9fdaea5 100644 --- a/tools/python_api/test/test_exception.py +++ b/tools/python_api/test/test_exception.py @@ -1,10 +1,14 @@ -import pytest +from __future__ import annotations + import sys + import kuzu +import pytest +from type_aliases import ConnDB -def test_exception(establish_connection): - conn, db = establish_connection +def test_exception(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly with pytest.raises(RuntimeError, match="Parameter asd not found."): conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", {"asd": 1}) @@ -13,38 +17,46 @@ def test_exception(establish_connection): conn.execute("MATCH (a:person) RETURN a.dummy;") -def test_db_path_exception(): - path = '/:* /? " < > |' +def test_db_path_exception() -> None: + path = "" if sys.platform == "win32": - error_message = 'Failed to create directory' + error_message = "Failed to create directory" else: - error_message = 'filesystem error' + error_message = "filesystem error" with pytest.raises(RuntimeError, match=error_message): - kuzu.Database(str(path)) + kuzu.Database(path) -def test_read_only_exception(establish_connection): + +def test_read_only_exception(conn_db_readonly: ConnDB) -> None: # TODO: Enable this test on Windows when the read-only mode is implemented. if sys.platform == "win32": pytest.skip("Read-only mode has not been implemented on Windows yet") - _, db = establish_connection + _, db = conn_db_readonly path = db.database_path read_only_db = kuzu.Database(path, read_only=True) conn = kuzu.Connection(read_only_db) with pytest.raises(RuntimeError, match="Cannot execute write operations in a read-only database!"): conn.execute("CREATE NODE TABLE test (id INT64, PRIMARY KEY(id));") -def test_max_db_size_exception(): - with pytest.raises(RuntimeError, match="Buffer manager exception: The given max db size should be at least 4194304 bytes."): + +def test_max_db_size_exception() -> None: + with pytest.raises( + RuntimeError, match="Buffer manager exception: The given max db size should be at least 4194304 bytes." + ): kuzu.Database("test.db", max_db_size=1024) with pytest.raises(RuntimeError, match="Buffer manager exception: The given max db size should be a power of 2."): kuzu.Database("test.db", max_db_size=4194305) -def test_buffer_pool_size_exception(): - with pytest.raises(RuntimeError, match="Buffer manager exception: The given buffer pool size should be at least 4KB."): + +def test_buffer_pool_size_exception() -> None: + with pytest.raises( + RuntimeError, match="Buffer manager exception: The given buffer pool size should be at least 4KB." + ): kuzu.Database("test.db", buffer_pool_size=1024) -def test_query_exception(establish_connection): - conn, db = establish_connection + +def test_query_exception(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly with pytest.raises(RuntimeError, match="Binder exception: Table nonexisting does not exist."): conn.execute("MATCH (a:nonexisting) RETURN a;") diff --git a/tools/python_api/test/test_extension.py b/tools/python_api/test/test_extension.py index 162ebb6142f..ad2a3e5eb7e 100644 --- a/tools/python_api/test/test_extension.py +++ b/tools/python_api/test/test_extension.py @@ -1,4 +1,9 @@ -def test_install_and_load_httpfs(establish_connection): - conn, db = establish_connection +from __future__ import annotations + +from type_aliases import ConnDB + + +def test_install_and_load_httpfs(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly conn.execute("INSTALL httpfs") conn.execute("LOAD EXTENSION httpfs") diff --git a/tools/python_api/test/test_get_header.py b/tools/python_api/test/test_get_header.py index aa17b67feca..89570ed98a9 100644 --- a/tools/python_api/test/test_get_header.py +++ b/tools/python_api/test/test_get_header.py @@ -1,26 +1,49 @@ -def test_get_column_names(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person)-[e:knows]->(b:person) RETURN a.fName, e.date, b.ID;") - column_names = result.get_column_names() - assert column_names[0] == 'a.fName' - assert column_names[1] == 'e.date' - assert column_names[2] == 'b.ID' - result.close() +from __future__ import annotations +from type_aliases import ConnDB -def test_get_column_data_types(establish_connection): - conn, db = establish_connection - result = conn.execute( + +def test_get_column_names(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + with conn.execute("MATCH (a:person)-[e:knows]->(b:person) RETURN a.fName, e.date, b.ID;") as result: + column_names = result.get_column_names() + assert column_names[0] == "a.fName" + assert column_names[1] == "e.date" + assert column_names[2] == "b.ID" + + +def test_get_column_data_types(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + with conn.execute( + "MATCH (p:person) RETURN p.ID, p.fName, p.isStudent, p.eyeSight, p.birthdate, p.registerTime, " + "p.lastJobDuration, p.workedHours, p.courseScoresPerTerm;" + ) as result: + column_data_types = result.get_column_data_types() + assert column_data_types[0] == "INT64" + assert column_data_types[1] == "STRING" + assert column_data_types[2] == "BOOL" + assert column_data_types[3] == "DOUBLE" + assert column_data_types[4] == "DATE" + assert column_data_types[5] == "TIMESTAMP" + assert column_data_types[6] == "INTERVAL" + assert column_data_types[7] == "INT64[]" + assert column_data_types[8] == "INT64[][]" + + +def test_get_schema(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + with conn.execute( "MATCH (p:person) RETURN p.ID, p.fName, p.isStudent, p.eyeSight, p.birthdate, p.registerTime, " - "p.lastJobDuration, p.workedHours, p.courseScoresPerTerm;") - column_data_types = result.get_column_data_types() - assert column_data_types[0] == 'INT64' - assert column_data_types[1] == 'STRING' - assert column_data_types[2] == 'BOOL' - assert column_data_types[3] == 'DOUBLE' - assert column_data_types[4] == 'DATE' - assert column_data_types[5] == 'TIMESTAMP' - assert column_data_types[6] == 'INTERVAL' - assert column_data_types[7] == 'INT64[]' - assert column_data_types[8] == 'INT64[][]' - result.close() + "p.lastJobDuration, p.workedHours, p.courseScoresPerTerm;" + ) as result: + assert result.get_schema() == { + "p.ID": "INT64", + "p.fName": "STRING", + "p.isStudent": "BOOL", + "p.eyeSight": "DOUBLE", + "p.birthdate": "DATE", + "p.registerTime": "TIMESTAMP", + "p.lastJobDuration": "INTERVAL", + "p.workedHours": "INT64[]", + "p.courseScoresPerTerm": "INT64[][]", + } diff --git a/tools/python_api/test/test_helper.py b/tools/python_api/test/test_helper.py index 57a0696b12e..cdffb07c1e7 100644 --- a/tools/python_api/test/test_helper.py +++ b/tools/python_api/test/test_helper.py @@ -1,8 +1,8 @@ -from pathlib import Path import sys +from pathlib import Path KUZU_ROOT = Path(__file__).parent.parent.parent.parent if sys.platform == "win32": # \ in paths is not supported by kuzu's parser - KUZU_ROOT=str(KUZU_ROOT).replace("\\", "/") + KUZU_ROOT = str(KUZU_ROOT).replace("\\", "/") diff --git a/tools/python_api/test/test_networkx.py b/tools/python_api/test/test_networkx.py index d49da0be117..103a9eaaf93 100644 --- a/tools/python_api/test/test_networkx.py +++ b/tools/python_api/test/test_networkx.py @@ -1,9 +1,14 @@ +from __future__ import annotations + import datetime -from pandas import Timestamp, Timedelta +from typing import Any + +from pandas import Timedelta, Timestamp +from type_aliases import ConnDB -def test_to_networkx_node(establish_connection): - conn, _ = establish_connection +def test_to_networkx_node(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:person) return p" res = conn.execute(query) @@ -11,58 +16,94 @@ def test_to_networkx_node(establish_connection): nodes = list(nx_graph.nodes(data=True)) assert len(nodes) == 8 - ground_truth = { - 'ID': [0, 2, 3, 5, 7, 8, 9, 10], - 'fName': ["Alice", "Bob", "Carol", "Dan", "Elizabeth", "Farooq", "Greg", - "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"], - 'gender': [1, 2, 1, 2, 1, 2, 2, 2], - 'isStudent': [True, True, False, False, False, True, False, False], - 'eyeSight': [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], - 'birthdate': [datetime.date(1900, 1, 1), datetime.date(1900, 1, 1), - datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), - datetime.date(1980, 10, 26), datetime.date(1980, 10, 26), - datetime.date(1980, 10, 26), datetime.date(1990, 11, 27)], - 'registerTime': [Timestamp('2011-08-20 11:25:30'), - Timestamp('2008-11-03 15:25:30.000526'), - Timestamp( - '1911-08-20 02:32:21'), Timestamp('2031-11-30 12:25:30'), - Timestamp('1976-12-23 11:21:42'), - Timestamp('1972-07-31 13:22:30.678559'), - Timestamp('1976-12-23 04:41:42'), Timestamp('2023-02-21 13:25:30')], - 'lastJobDuration': [Timedelta('1082 days 13:02:00'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), Timedelta( - '0 days 00:18:00.024000'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('1082 days 13:02:00')], - 'workedHours': [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], - [10, 11, 12, 3, 4, 5, 6, 7]], - 'usedNames': [["Aida"], ['Bobby'], ['Carmen', 'Fred'], - ['Wolfeschlegelstein', 'Daniel'], [ - 'Ein'], ['Fesdwe'], ['Grad'], - ['Ad', 'De', 'Hi', 'Kye', 'Orlan']], - 'courseScoresPerTerm': [[[10, 8], [6, 7, 8]], [[8, 9], [9, 10]], [[8, 10]], - [[7, 4], [8, 8], [9]], [ - [6], [7], [8]], [[8]], [[10]], - [[7], [10], [6, 7]]], - 'grades': [[96, 54, 86, 92], [98, 42, 93, 88], [91, 75, 21, 95], [76, 88, 99, 89], [96, 59, 65, 88], - [80, 78, 34, 83], [43, 83, 67, 43], [77, 64, 100, 54]], - '_label': ['person', 'person', 'person', 'person', 'person', 'person', - 'person', 'person'], + ground_truth: dict[str, list[Any]] = { + "ID": [0, 2, 3, 5, 7, 8, 9, 10], + "fName": [ + "Alice", + "Bob", + "Carol", + "Dan", + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ], + "gender": [1, 2, 1, 2, 1, 2, 2, 2], + "isStudent": [True, True, False, False, False, True, False, False], + "eyeSight": [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], + "birthdate": [ + datetime.date(1900, 1, 1), + datetime.date(1900, 1, 1), + datetime.date(1940, 6, 22), + datetime.date(1950, 7, 23), + datetime.date(1980, 10, 26), + datetime.date(1980, 10, 26), + datetime.date(1980, 10, 26), + datetime.date(1990, 11, 27), + ], + "registerTime": [ + Timestamp("2011-08-20 11:25:30"), + Timestamp("2008-11-03 15:25:30.000526"), + Timestamp("1911-08-20 02:32:21"), + Timestamp("2031-11-30 12:25:30"), + Timestamp("1976-12-23 11:21:42"), + Timestamp("1972-07-31 13:22:30.678559"), + Timestamp("1976-12-23 04:41:42"), + Timestamp("2023-02-21 13:25:30"), + ], + "lastJobDuration": [ + Timedelta("1082 days 13:02:00"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("0 days 00:18:00.024000"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("1082 days 13:02:00"), + ], + "workedHours": [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], [10, 11, 12, 3, 4, 5, 6, 7]], + "usedNames": [ + ["Aida"], + ["Bobby"], + ["Carmen", "Fred"], + ["Wolfeschlegelstein", "Daniel"], + ["Ein"], + ["Fesdwe"], + ["Grad"], + ["Ad", "De", "Hi", "Kye", "Orlan"], + ], + "courseScoresPerTerm": [ + [[10, 8], [6, 7, 8]], + [[8, 9], [9, 10]], + [[8, 10]], + [[7, 4], [8, 8], [9]], + [[6], [7], [8]], + [[8]], + [[10]], + [[7], [10], [6, 7]], + ], + "grades": [ + [96, 54, 86, 92], + [98, 42, 93, 88], + [91, 75, 21, 95], + [76, 88, 99, 89], + [96, 59, 65, 88], + [80, 78, 34, 83], + [43, 83, 67, 43], + [77, 64, 100, 54], + ], + "_label": ["person", "person", "person", "person", "person", "person", "person", "person"], } for i in range(len(nodes)): node_id, node = nodes[i] - assert node_id == "%s_%d" % (node['_label'], node['ID']) + assert node_id == "%s_%d" % (node["_label"], node["ID"]) for key in ground_truth: assert node[key] == ground_truth[key][i] -def test_networkx_undirected(establish_connection): - conn, _ = establish_connection - res = conn.execute( - "MATCH (p1:person)-[r:knows]->(p2:person) WHERE p1.ID <= 3 RETURN p1, r, p2") +def test_networkx_undirected(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + res = conn.execute("MATCH (p1:person)-[r:knows]->(p2:person) WHERE p1.ID <= 3 RETURN p1, r, p2") nx_graph = res.get_as_networkx(directed=False) assert not nx_graph.is_directed() @@ -72,54 +113,91 @@ def test_networkx_undirected(establish_connection): edges = list(nx_graph.edges(data=True)) - ground_truth_p = { - 'ID': [0, 2, 3, 5, 7, 8, 9, 10], - 'fName': ["Alice", "Bob", "Carol", "Dan", "Elizabeth", "Farooq", "Greg", - "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff"], - 'gender': [1, 2, 1, 2, 1, 2, 2, 2], - 'isStudent': [True, True, False, False, False, True, False, False], - 'eyeSight': [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], - 'birthdate': [datetime.date(1900, 1, 1), datetime.date(1900, 1, 1), - datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), - datetime.date(1980, 10, 26), datetime.date(1980, 10, 26), - datetime.date(1980, 10, 26), datetime.date(1990, 11, 27)], - 'registerTime': [Timestamp('2011-08-20 11:25:30'), - Timestamp('2008-11-03 15:25:30.000526'), - Timestamp( - '1911-08-20 02:32:21'), Timestamp('2031-11-30 12:25:30'), - Timestamp('1976-12-23 11:21:42'), - Timestamp('1972-07-31 13:22:30.678559'), - Timestamp('1976-12-23 04:41:42'), Timestamp('2023-02-21 13:25:30')], - 'lastJobDuration': [Timedelta('1082 days 13:02:00'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11'), Timedelta( - '0 days 00:18:00.024000'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('1082 days 13:02:00')], - 'workedHours': [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], - [10, 11, 12, 3, 4, 5, 6, 7]], - 'usedNames': [["Aida"], ['Bobby'], ['Carmen', 'Fred'], - ['Wolfeschlegelstein', 'Daniel'], [ - 'Ein'], ['Fesdwe'], ['Grad'], - ['Ad', 'De', 'Hi', 'Kye', 'Orlan']], - 'courseScoresPerTerm': [[[10, 8], [6, 7, 8]], [[8, 9], [9, 10]], [[8, 10]], - [[7, 4], [8, 8], [9]], [ - [6], [7], [8]], [[8]], [[10]], - [[7], [10], [6, 7]]], - 'grades': [[96, 54, 86, 92], [98, 42, 93, 88], [91, 75, 21, 95], [76, 88, 99, 89], [96, 59, 65, 88], - [80, 78, 34, 83], [43, 83, 67, 43], [77, 64, 100, 54]], - '_label': ['person', 'person', 'person', 'person', 'person', 'person', - 'person', 'person'], + ground_truth_p: dict[str, list[Any]] = { + "ID": [0, 2, 3, 5, 7, 8, 9, 10], + "fName": [ + "Alice", + "Bob", + "Carol", + "Dan", + "Elizabeth", + "Farooq", + "Greg", + "Hubert Blaine Wolfeschlegelsteinhausenbergerdorff", + ], + "gender": [1, 2, 1, 2, 1, 2, 2, 2], + "isStudent": [True, True, False, False, False, True, False, False], + "eyeSight": [5.0, 5.1, 5.0, 4.8, 4.7, 4.5, 4.9, 4.9], + "birthdate": [ + datetime.date(1900, 1, 1), + datetime.date(1900, 1, 1), + datetime.date(1940, 6, 22), + datetime.date(1950, 7, 23), + datetime.date(1980, 10, 26), + datetime.date(1980, 10, 26), + datetime.date(1980, 10, 26), + datetime.date(1990, 11, 27), + ], + "registerTime": [ + Timestamp("2011-08-20 11:25:30"), + Timestamp("2008-11-03 15:25:30.000526"), + Timestamp("1911-08-20 02:32:21"), + Timestamp("2031-11-30 12:25:30"), + Timestamp("1976-12-23 11:21:42"), + Timestamp("1972-07-31 13:22:30.678559"), + Timestamp("1976-12-23 04:41:42"), + Timestamp("2023-02-21 13:25:30"), + ], + "lastJobDuration": [ + Timedelta("1082 days 13:02:00"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + Timedelta("0 days 00:18:00.024000"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("1082 days 13:02:00"), + ], + "workedHours": [[10, 5], [12, 8], [4, 5], [1, 9], [2], [3, 4, 5, 6, 7], [1], [10, 11, 12, 3, 4, 5, 6, 7]], + "usedNames": [ + ["Aida"], + ["Bobby"], + ["Carmen", "Fred"], + ["Wolfeschlegelstein", "Daniel"], + ["Ein"], + ["Fesdwe"], + ["Grad"], + ["Ad", "De", "Hi", "Kye", "Orlan"], + ], + "courseScoresPerTerm": [ + [[10, 8], [6, 7, 8]], + [[8, 9], [9, 10]], + [[8, 10]], + [[7, 4], [8, 8], [9]], + [[6], [7], [8]], + [[8]], + [[10]], + [[7], [10], [6, 7]], + ], + "grades": [ + [96, 54, 86, 92], + [98, 42, 93, 88], + [91, 75, 21, 95], + [76, 88, 99, 89], + [96, 59, 65, 88], + [80, 78, 34, 83], + [43, 83, 67, 43], + [77, 64, 100, 54], + ], + "_label": ["person", "person", "person", "person", "person", "person", "person", "person"], } - for (node_id, node) in nodes: - assert node_id == "%s_%d" % (node['_label'], node['ID']) + for node_id, node in nodes: + assert node_id == "%s_%d" % (node["_label"], node["ID"]) - for (_, node) in nodes: + for _, node in nodes: found = False - for i in range(len(ground_truth_p['ID'])): - if node['ID'] != ground_truth_p['ID'][i]: + for i in range(len(ground_truth_p["ID"])): + if node["ID"] != ground_truth_p["ID"][i]: continue found = True for key in ground_truth_p: @@ -135,10 +213,9 @@ def test_networkx_undirected(establish_connection): assert nx_graph.has_edge(nodes[i][0], nodes[j][0]) -def test_networkx_directed(establish_connection): - conn, _ = establish_connection - res = conn.execute( - "MATCH (p:person)-[r:workAt]->(o:organisation) RETURN p, r, o") +def test_networkx_directed(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + res = conn.execute("MATCH (p:person)-[r:workAt]->(o:organisation) RETURN p, r, o") nx_graph = res.get_as_networkx(directed=True) assert nx_graph.is_directed() @@ -148,61 +225,63 @@ def test_networkx_directed(establish_connection): edges = list(nx_graph.edges(data=True)) - ground_truth_p = { - 'ID': [3, 5, 7], - 'fName': ["Carol", "Dan", "Elizabeth"], - 'gender': [1, 2, 1], - 'isStudent': [False, False, False], - 'eyeSight': [5.0, 4.8, 4.7], - 'birthdate': [datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), - datetime.date(1980, 10, 26)], - 'registerTime': [Timestamp('1911-08-20 02:32:21'), Timestamp('2031-11-30 12:25:30'), - Timestamp('1976-12-23 11:21:42') - ], - 'lastJobDuration': [ - Timedelta('48 hours 24 minutes 11 seconds'), - Timedelta('3750 days 13:00:00.000024'), - Timedelta('2 days 00:24:11')], - 'workedHours': [[4, 5], [1, 9], [2]], - 'usedNames': [["Carmen", "Fred"], ['Wolfeschlegelstein', 'Daniel'], ['Ein']], - 'courseScoresPerTerm': [[[8, 10]], [[7, 4], [8, 8], [9]], [[6], [7], [8]]], - 'grades': [[91, 75, 21, 95], [76, 88, 99, 89], [96, 59, 65, 88]], - '_label': ['person', 'person', 'person'], + ground_truth_p: dict[str, list[Any]] = { + "ID": [3, 5, 7], + "fName": ["Carol", "Dan", "Elizabeth"], + "gender": [1, 2, 1], + "isStudent": [False, False, False], + "eyeSight": [5.0, 4.8, 4.7], + "birthdate": [datetime.date(1940, 6, 22), datetime.date(1950, 7, 23), datetime.date(1980, 10, 26)], + "registerTime": [ + Timestamp("1911-08-20 02:32:21"), + Timestamp("2031-11-30 12:25:30"), + Timestamp("1976-12-23 11:21:42"), + ], + "lastJobDuration": [ + Timedelta("48 hours 24 minutes 11 seconds"), + Timedelta("3750 days 13:00:00.000024"), + Timedelta("2 days 00:24:11"), + ], + "workedHours": [[4, 5], [1, 9], [2]], + "usedNames": [["Carmen", "Fred"], ["Wolfeschlegelstein", "Daniel"], ["Ein"]], + "courseScoresPerTerm": [[[8, 10]], [[7, 4], [8, 8], [9]], [[6], [7], [8]]], + "grades": [[91, 75, 21, 95], [76, 88, 99, 89], [96, 59, 65, 88]], + "_label": ["person", "person", "person"], } - for (node_id, node) in nodes: - assert node_id == "%s_%d" % (node['_label'], node['ID']) + for node_id, node in nodes: + assert node_id == "%s_%d" % (node["_label"], node["ID"]) - for (_, node) in nodes: - if 'person' not in node: + for _, node in nodes: + if "person" not in node: continue found = False - for i in range(len(ground_truth_p['ID'])): - if node['ID'] != ground_truth_p['ID'][i]: + for i in range(len(ground_truth_p["ID"])): + if node["ID"] != ground_truth_p["ID"][i]: continue found = True for key in ground_truth_p: assert node[key] == ground_truth_p[key][i] assert found - ground_truth_o = {'ID': [4, 6], - 'name': ['CsWork', 'DEsWork'], - 'orgCode': [934, 824], - 'mark': [4.1, 4.1], - 'score': [-100, 7], - 'history': ['2 years 4 days 10 hours', '2 years 4 hours 22 us 34 minutes'], - 'licenseValidInterval': [Timedelta(days=9414), - Timedelta(days=3, seconds=36000, microseconds=100000)], - 'rating': [0.78, 0.52], - '_label': ['organisation', 'organisation'], - } - - for (_, node) in nodes: - if 'organisation' not in node: + ground_truth_o: dict[str, list[Any]] = { + "ID": [4, 6], + "name": ["CsWork", "DEsWork"], + "orgCode": [934, 824], + "mark": [4.1, 4.1], + "score": [-100, 7], + "history": ["2 years 4 days 10 hours", "2 years 4 hours 22 us 34 minutes"], + "licenseValidInterval": [Timedelta(days=9414), Timedelta(days=3, seconds=36000, microseconds=100000)], + "rating": [0.78, 0.52], + "_label": ["organisation", "organisation"], + } + + for _, node in nodes: + if "organisation" not in node: continue found = False - for i in range(len(ground_truth_o['ID'])): - if node['ID'] != ground_truth_o['ID'][i]: + for i in range(len(ground_truth_o["ID"])): + if node["ID"] != ground_truth_o["ID"][i]: continue found = True for key in ground_truth_o: @@ -214,17 +293,16 @@ def test_networkx_directed(establish_connection): assert len(edges) == 3 years_ground_truth = [2010, 2015, 2015] - for (src, dst, edge) in edges: - assert nodes_dict[dst]['_label'] == 'organisation' - assert nodes_dict[dst]['ID'] in [4, 6] - - assert nodes_dict[src]['_label'] == 'person' - assert nodes_dict[src]['ID'] in [3, 5, 7] - assert edge['year'] in years_ground_truth + for src, dst, edge in edges: + assert nodes_dict[dst]["_label"] == "organisation" + assert nodes_dict[dst]["ID"] in [4, 6] + assert nodes_dict[src]["_label"] == "person" + assert nodes_dict[src]["ID"] in [3, 5, 7] + assert edge["year"] in years_ground_truth # If the edge is found, remove it from ground truth so we can check # that all edges were found and no extra edges were found - del years_ground_truth[years_ground_truth.index(edge['year'])] + del years_ground_truth[years_ground_truth.index(edge["year"])] del nodes_dict[src] assert len(years_ground_truth) == 0 diff --git a/tools/python_api/test/test_parameter.py b/tools/python_api/test/test_parameter.py index b2a677617bb..fa8b0876d0a 100644 --- a/tools/python_api/test/test_parameter.py +++ b/tools/python_api/test/test_parameter.py @@ -1,77 +1,211 @@ -import datetime -import pytest +from __future__ import annotations +import datetime -def test_bool_param(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person) WHERE a.isStudent = $1 AND a.isWorker = $k RETURN COUNT(*)", - {"1": False, "k": False}) +import pytest +from type_aliases import ConnDB +from typing import TYPE_CHECKING +# required by python-lint +if TYPE_CHECKING: + from pathlib import Path +import kuzu + + +def test_bool_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute( + "MATCH (a:person) WHERE a.isStudent = $1 AND a.isWorker = $k RETURN COUNT(*)", {"1": False, "k": False} + ) assert result.has_next() assert result.get_next() == [1] assert not result.has_next() result.close() -def test_int_param(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person) WHERE a.age < $AGE RETURN COUNT(*)", { "AGE": 1 }) +def test_int_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.age < $AGE RETURN COUNT(*)", {"AGE": 1}) assert result.has_next() assert result.get_next() == [0] assert not result.has_next() result.close() -def test_double_param(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person) WHERE a.eyeSight = $E RETURN COUNT(*)", { "E": 5.0 }) +def test_double_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.eyeSight = $E RETURN COUNT(*)", {"E": 5.0}) assert result.has_next() assert result.get_next() == [2] assert not result.has_next() result.close() -def test_str_param(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN concat(a.fName, $S);", { "S": "HH" }) +def test_str_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN concat(a.fName, $S);", {"S": "HH"}) assert result.has_next() assert result.get_next() == ["AliceHH"] assert not result.has_next() result.close() -def test_date_param(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person) WHERE a.birthdate = $1 RETURN COUNT(*);", - { "1": datetime.date(1900, 1, 1) }) +def test_date_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute("MATCH (a:person) WHERE a.birthdate = $1 RETURN COUNT(*);", {"1": datetime.date(1900, 1, 1)}) assert result.has_next() assert result.get_next() == [2] assert not result.has_next() result.close() -def test_timestamp_param(establish_connection): - conn, db = establish_connection - result = conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", - { "1": datetime.datetime(2011, 8, 20, 11, 25, 30) }) +def test_timestamp_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute( + "MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", + {"1": datetime.datetime(2011, 8, 20, 11, 25, 30)}, + ) + assert result.has_next() + assert result.get_next() == [1] + assert not result.has_next() + result.close() + +def test_int64_list_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute( + "MATCH (a:person {workedHours: $1}) RETURN COUNT(*);", + {"1": [3, 4, 5, 6, 7]}) assert result.has_next() assert result.get_next() == [1] assert not result.has_next() result.close() +def test_int64_list_list_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute( + "MATCH (a:person) WHERE a.courseScoresPerTerm = $1 OR a.courseScoresPerTerm = $2 RETURN COUNT(*);", + {"1": [[8, 10]], "2": [[7, 4], [8, 8], [9]]}) + assert result.has_next() + assert result.get_next() == [2] + assert not result.has_next() + result.close() + +def test_string_list_param(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + result = conn.execute( + "MATCH (a:person {usedNames: $1}) RETURN COUNT(*);", + {"1": ["Carmen", "Fred"]}) + assert result.has_next() + assert result.get_next() == [1] + assert not result.has_next() + result.close() -def test_param_error1(establish_connection): - conn, db = establish_connection - with pytest.raises(RuntimeError, match="Parameter name must be of type string but get "): +def test_map_param(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) + conn = kuzu.Connection(db) + conn.execute("CREATE NODE TABLE tab(id int64, mp MAP(double, int64), mp2 MAP(int64, double), mp3 MAP(string, string), mp4 MAP(string, string)[], primary key(id))") + result = conn.execute( + "MERGE (t:tab {id: 0, mp: $1, mp2: $2, mp3: $3, mp4: $4}) RETURN t.*", + {"1": {1.0: 5, 2: 3, 2.2: -1}, + "2": {5: -0.5, 4: 0, 0: 2.2}, + "3": {'a': 1, 'b': '2', 'c': '3'}, + "4": [{}, {'a': 'b'}]}) + assert result.has_next() + assert result.get_next() == [0, {1.0: 5, 2.0: 3, 2.2: -1}, {5: -0.5, 4: -0.0, 0: 2.2}, {'a': '1', 'b': '2', 'c': '3'}, [{}, {'a': 'b'}]] + assert not result.has_next() + result.close() + +def test_general_list_param(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) + conn = kuzu.Connection(db) + conn.execute( + "CREATE NODE TABLE tab(id int64, lst1 BOOL[], lst2 DOUBLE[], lst3 TIMESTAMP[], lst4 DATE[], lst5 INTERVAL[], lst6 STRING[], PRIMARY KEY(id))") + lst1 = [True, False] + lst2 = [1.0, 2.0] + lst3 = [datetime.datetime(2019, 11, 12, 11, 25, 30), datetime.datetime(1987, 2, 15, 3, 0, 2)] + lst4 = [datetime.date(2019, 11, 12), datetime.date(1987, 2, 15)] + lst5 = [lst3[0] - lst3[1]] + lst6 = [1, 'a', 'b'] + lst6ToString = ['1', 'a', 'b'] + result = conn.execute( + "MERGE (t:tab {id: 0, lst1: $1, lst2: $2, lst3: $3, lst4: $4, lst5: $5, lst6: $6}) RETURN t.*", + { + "1": lst1, "2": lst2, "3": lst3, "4": lst4, "5": lst5, "6": lst6 + }) + assert result.has_next() + assert result.get_next() == [0, lst1, lst2, lst3, lst4, lst5, lst6ToString] + assert not result.has_next() + result.close() + +def test_null_resolution(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) + conn = kuzu.Connection(db) + conn.execute( + "CREATE NODE TABLE tab(id SERIAL, lst1 INT64[], mp1 MAP(STRING, STRING), nest MAP(STRING, MAP(STRING, INT64))[], PRIMARY KEY(id))") + lst1 = [1, 2, 3, None] + mp1 = {'a': 'x', 'b': 'y', 'c': 'z', 'o': None} + nest = [{'a': {'foo' : 1, 'bar' : 2}}, {1: {}}] + result = conn.execute( + "MERGE (t:tab {lst1: $1, mp1: $2, nest: $3}) RETURN t.*", + {'1': lst1, '2': mp1, '3': nest}) + assert result.has_next() + assert result.get_next() == [0, lst1, mp1, [{'a': {'foo' : 1, 'bar' : 2}}, {'1': {}}]] + assert not result.has_next() + result.close() + +# def test_param_empty(tmp_path: Path) -> None: +# db = kuzu.Database(tmp_path) +# conn = kuzu.Connection(db) +# lst = [[]] +# result = conn.execute("CREATE NODE TABLE tab(id SERIAL, lst INT64[][], PRIMARY KEY(id))") +# result = conn.execute( +# "MERGE (t:tab {lst: $1}) RETURN t.*", +# {'1': lst}) +# assert result.has_next() +# assert result.get_next == [0, lst] +# assert not result.has_next() +# result.close() + +def test_param_error1(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + with pytest.raises(RuntimeError, match="Parameter name must be of type string but got "): conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", {1: 1}) -def test_param_error2(establish_connection): - conn, db = establish_connection +def test_param_error2(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly with pytest.raises(RuntimeError, match="Parameters must be a dict"): conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", ["asd"]) -def test_param_error3(establish_connection): - conn, db = establish_connection +def test_param_error3(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly with pytest.raises(RuntimeError, match="Parameters must be a dict"): conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", [("asd", 1, 1)]) + +def test_param(conn_db_readwrite: ConnDB) -> None: + conn, db = conn_db_readwrite + conn.execute("CREATE NODE TABLE NodeOne(id INT64, name STRING, PRIMARY KEY(id));"); + conn.execute("CREATE NODE TABLE NodeTwo(id INT64, name STRING, PRIMARY KEY(id));"); + conn.execute("CREATE Rel TABLE RelA(from NodeOne to NodeOne);"); + conn.execute("CREATE Rel TABLE RelB(from NodeTwo to NodeOne, id int64, name String);"); + conn.execute("CREATE (t: NodeOne {id:1, name: \"Alice\"});"); + conn.execute("CREATE (t: NodeOne {id:2, name: \"Jack\"});"); + conn.execute("CREATE (t: NodeTwo {id:3, name: \"Bob\"});"); + result = conn.execute( + "MATCH (a:NodeOne { id: $a_id })," + "(b:NodeTwo { id: $b_id })," + "(c: NodeOne{ id: $c_id } )" + " MERGE" + " (a)-[:RelA]->(c)," + " (b)-[r:RelB { id: 2, name: $my_param }]->(c)" + " return r.*;", {"a_id": 1, "b_id": 3, "c_id": 2, "my_param": None} + ) + assert result.has_next() + assert result.get_next() == [2, None] + result.close() + +def test_param_error4(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + with pytest.raises(RuntimeError, match="Runtime exception: Cannot convert Python object to Kuzu value : INT64 is incompatible with TIMESTAMP"): + conn.execute("MATCH (a:person {workedHours: $1}) RETURN COUNT(*);", {'1': [1, 2, datetime.datetime(2023, 3, 25)]}) + diff --git a/tools/python_api/test/test_prepared_statement.py b/tools/python_api/test/test_prepared_statement.py index e5c59e37306..4a2841ee296 100644 --- a/tools/python_api/test/test_prepared_statement.py +++ b/tools/python_api/test/test_prepared_statement.py @@ -1,13 +1,14 @@ -import uuid +from __future__ import annotations -import pytest import datetime +import uuid +from type_aliases import ConnDB -def test_read(establish_connection): - conn, _ = establish_connection - prepared_statement = conn.prepare( - "MATCH (a:person) WHERE a.isStudent = $1 AND a.isWorker = $k RETURN COUNT(*)") + +def test_read(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + prepared_statement = conn.prepare("MATCH (a:person) WHERE a.isStudent = $1 AND a.isWorker = $k RETURN COUNT(*)") assert prepared_statement.is_success() assert prepared_statement.get_error_message() == "" @@ -31,8 +32,21 @@ def test_read(establish_connection): assert result.get_next() == [0] assert not result.has_next() -def test_write(establish_connection): - conn, _ = establish_connection + +def test_null_value(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly + prepared_statement = conn.prepare("RETURN [4, $1, 2, $3, 4]") + assert prepared_statement.is_success() + assert prepared_statement.get_error_message() == "" + + result = conn.execute(prepared_statement, {"1": None, "3": 5}) + assert result.has_next() + assert result.get_next() == [[4, None, 2, 5, 4]] + assert not result.has_next() + + +def test_write(conn_db_readwrite: ConnDB) -> None: + conn, _ = conn_db_readwrite orgs = [ { "ID": 1001, @@ -42,7 +56,7 @@ def test_write(establish_connection): "score": 1, "history": "history1", "licenseValidInterval": datetime.timedelta(days=1), - "rating": 1.0 + "rating": 1.0, }, { "ID": 1002, @@ -52,7 +66,7 @@ def test_write(establish_connection): "score": 2, "history": "history2", "licenseValidInterval": datetime.timedelta(days=2), - "rating": 2.0 + "rating": 2.0, }, { "ID": 1003, @@ -62,12 +76,13 @@ def test_write(establish_connection): "score": 3, "history": "history3", "licenseValidInterval": datetime.timedelta(days=3), - "rating": 3.0 + "rating": 3.0, }, ] prepared_statement = conn.prepare( - "CREATE (n:organisation {ID: $ID, name: $name, orgCode: $orgCode, mark: $mark, score: $score, history: $history, licenseValidInterval: $licenseValidInterval, rating: $rating})") + "CREATE (n:organisation {ID: $ID, name: $name, orgCode: $orgCode, mark: $mark, score: $score, history: $history, licenseValidInterval: $licenseValidInterval, rating: $rating})" + ) assert prepared_statement.is_success() for org in orgs: org_dict = {str(k): v for k, v in org.items()} @@ -76,35 +91,31 @@ def test_write(establish_connection): all_orgs_res = conn.execute("MATCH (n:organisation) RETURN n") while all_orgs_res.has_next(): n = all_orgs_res.get_next()[0] - if n['ID'] not in [o['ID'] for o in orgs]: + if n["ID"] not in [o["ID"] for o in orgs]: continue for expected_org in orgs: - if n['ID'] == expected_org['ID']: - assert n['ID'] == expected_org['ID'] - assert n['name'] == expected_org['name'] - assert n['orgCode'] == expected_org['orgCode'] - assert n['mark'] == expected_org['mark'] - assert n['score'] == expected_org['score'] - assert n['history'] == expected_org['history'] - assert n['licenseValidInterval'] == expected_org['licenseValidInterval'] - assert n['rating'] == expected_org['rating'] + if n["ID"] == expected_org["ID"]: + assert n["ID"] == expected_org["ID"] + assert n["name"] == expected_org["name"] + assert n["orgCode"] == expected_org["orgCode"] + assert n["mark"] == expected_org["mark"] + assert n["score"] == expected_org["score"] + assert n["history"] == expected_org["history"] + assert n["licenseValidInterval"] == expected_org["licenseValidInterval"] + assert n["rating"] == expected_org["rating"] break - conn.execute('CREATE NODE TABLE uuid_table (id UUID, PRIMARY KEY(id));') - conn.execute('CREATE (:uuid_table {id: $1});', {'1': uuid.uuid5(uuid.NAMESPACE_DNS, 'kuzu')}) - result = conn.execute('MATCH (n:uuid_table) RETURN n.id;') - assert result.get_next() == [uuid.uuid5(uuid.NAMESPACE_DNS, 'kuzu')] + conn.execute("CREATE NODE TABLE uuid_table (id UUID, PRIMARY KEY(id));") + conn.execute("CREATE (:uuid_table {id: $1});", {"1": uuid.uuid5(uuid.NAMESPACE_DNS, "kuzu")}) + result = conn.execute("MATCH (n:uuid_table) RETURN n.id;") + assert result.get_next() == [uuid.uuid5(uuid.NAMESPACE_DNS, "kuzu")] -def test_error(establish_connection): - prepared_statement = establish_connection[0].prepare( - "MATCH (d:dog) WHERE d.isServiceDog = $1 RETURN COUNT(*)") +def test_error(conn_db_readonly: ConnDB) -> None: + prepared_statement = conn_db_readonly[0].prepare("MATCH (d:dog) WHERE d.isServiceDog = $1 RETURN COUNT(*)") assert not prepared_statement.is_success() - assert prepared_statement.get_error_message( - ) == "Binder exception: Table dog does not exist." + assert prepared_statement.get_error_message() == "Binder exception: Table dog does not exist." - prepared_statement = establish_connection[0].prepare( - "SELECT * FROM person") + prepared_statement = conn_db_readonly[0].prepare("SELECT * FROM person") assert not prepared_statement.is_success() - assert prepared_statement.get_error_message( - ).startswith("Parser exception: extraneous input 'SELECT'") + assert prepared_statement.get_error_message().startswith("Parser exception: extraneous input 'SELECT'") diff --git a/tools/python_api/test/test_query_result.py b/tools/python_api/test/test_query_result.py index 468bd45db66..372fcb358e0 100644 --- a/tools/python_api/test/test_query_result.py +++ b/tools/python_api/test/test_query_result.py @@ -1,26 +1,42 @@ -def test_get_execution_time(establish_connection): - conn, db = establish_connection +from __future__ import annotations + +from type_aliases import ConnDB + + +def test_get_execution_time(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a") assert result.get_execution_time() > 0 result.close() -def test_get_compiling_time(establish_connection): - conn, db = establish_connection +def test_get_compiling_time(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a") assert result.get_compiling_time() > 0 result.close() -def test_get_num_tuples(establish_connection): - conn, db = establish_connection +def test_get_num_tuples(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a") assert result.get_num_tuples() == 1 result.close() -def test_explain(establish_connection): - conn, db = establish_connection +def test_explain(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly result = conn.execute("EXPLAIN MATCH (a:person) WHERE a.ID = 0 RETURN a") assert result.get_num_tuples() == 1 result.close() + + +def test_context_manager(conn_db_readonly: ConnDB) -> None: + conn, db = conn_db_readonly + with conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a") as result: + assert result.get_num_tuples() == 1 + assert result.get_compiling_time() > 0 + + # context exit guarantees immediately 'close' of the underlying QueryResult + # (don't have to wait for __del__, which may not ever actually get called) + assert result.is_closed diff --git a/tools/python_api/test/test_query_result_close.py b/tools/python_api/test/test_query_result_close.py index c68abb61b47..d3a9bf5811b 100644 --- a/tools/python_api/test/test_query_result_close.py +++ b/tools/python_api/test/test_query_result_close.py @@ -1,23 +1,42 @@ import subprocess import sys +from pathlib import Path +from textwrap import dedent + from test_helper import KUZU_ROOT -def test_query_result_close(get_tmp_path): - code = [ - 'import kuzu', - # Note: Windows paths include backslashes, which need to be raw strings or escaped. - 'db = kuzu.Database(r"' + get_tmp_path + '")', - 'conn = kuzu.Connection(db)', - 'conn.execute(\'CREATE NODE TABLE person (ID INT64, fName STRING, gender INT64,\ - isStudent BOOLEAN, isWorker BOOLEAN, age INT64, eyeSight DOUBLE,\ - birthdate DATE, registerTime TIMESTAMP, lastJobDuration INTERVAL,\ - workedHours INT64[], usedNames STRING[], courseScoresPerTerm INT64[][], grades INT64[4], height float, u UUID, \ - PRIMARY KEY (ID))\')', - f'conn.execute(\'COPY person FROM \"{KUZU_ROOT}/dataset/tinysnb/vPerson.csv\" (HEADER=true)\')', - 'result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.isStudent;")', - # 'result.close()', - ] - code = ';'.join(code) - result = subprocess.run([sys.executable, '-c', code]) +def test_query_result_close(tmp_path: Path, build_dir: Path) -> None: + code = dedent(f""" + import sys + sys.path.append(r"{build_dir!s}") + + import kuzu + db = kuzu.Database(r"{tmp_path!s}") + conn = kuzu.Connection(db) + conn.execute(''' + CREATE NODE TABLE person ( + ID INT64, + fName STRING, + gender INT64, + isStudent BOOLEAN, + isWorker BOOLEAN, + age INT64, + eyeSight DOUBLE, + birthdate DATE, + registerTime TIMESTAMP, + lastJobDuration INTERVAL, + workedHours INT64[], + usedNames STRING[], + courseScoresPerTerm INT64[][], + grades INT64[4], + height float, + u UUID, + PRIMARY KEY (ID)) + ''') + conn.execute('COPY person FROM "{KUZU_ROOT}/dataset/tinysnb/vPerson.csv" (HEADER=true)') + result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.isStudent;") + # result.close() + """) + result = subprocess.run([sys.executable, "-c", code]) assert result.returncode == 0 diff --git a/tools/python_api/test/test_scan_pandas.py b/tools/python_api/test/test_scan_pandas.py index bcc2e31784d..0ce23232122 100644 --- a/tools/python_api/test/test_scan_pandas.py +++ b/tools/python_api/test/test_scan_pandas.py @@ -1,131 +1,218 @@ +import datetime +import re +from pathlib import Path + import numpy as np import pandas as pd -import datetime import pytest -import re + try: from zoneinfo import ZoneInfo except ImportError: - from backports.zoneinfo import ZoneInfo + from backports.zoneinfo import ZoneInfo # type: ignore[no-redef] + import kuzu -def validate_scan_pandas_results(results): - assert results.get_next() == [True, 1, 10, 100, 1000, -1, -10, -100, -1000, -0.5199999809265137, 5132.12321, - datetime.datetime(1996, 4, 1, 12, 0, 11, 500001), - datetime.datetime(1996, 4, 1, 12, 0, 11, 500001, ZoneInfo("US/Eastern")), - datetime.datetime(1996, 4, 1, 12, 0, 11, 500001), - datetime.datetime(1996, 4, 1, 12, 0, 11, 500000), - datetime.datetime(1996, 4, 1, 12, 0, 11), - datetime.timedelta(microseconds=500), None, [], 528, 3.562, ['Alice', None], - datetime.date(1996, 2, 15), '12331'] - assert results.get_next() == [False, 2, 20, 200, 2000, -2, -20, -200, -2000, None, 24.222, - datetime.datetime(1981, 11, 13, 22, 2, 52, 2), - datetime.datetime(1981, 11, 13, 22, 2, 52, 2, ZoneInfo("US/Eastern")), - datetime.datetime(1981, 11, 13, 22, 2, 52, 2), - datetime.datetime(1981, 11, 13, 22, 2, 52), - datetime.datetime(1981, 11, 13, 22, 2, 52), - datetime.timedelta(seconds=1), 'Ascii only', [40, 20, 10], -9999, 4.213, [], - datetime.date(2013, 2, 22), 'test string'] - assert results.get_next() == [None, 3, 30, 300, 3000, -3, -30, -300, -3000, -3.299999952316284, None, - datetime.datetime(1972, 12, 21, 12, 5, 44, 500003), - datetime.datetime(1972, 12, 21, 12, 5, 44, 500003, ZoneInfo("US/Eastern")), - datetime.datetime(1972, 12, 21, 12, 5, 44, 500003), - datetime.datetime(1972, 12, 21, 12, 5, 44, 500000), - datetime.datetime(1972, 12, 21, 12, 5, 44), - datetime.timedelta(seconds=2, milliseconds=500), 'ñ中国字', [30, None], None, None, - None, datetime.date(2055, 1, 14), '5.623'] - assert results.get_next() == [False, 4, 40, 400, 4000, -4, -40, -400, -4000, 4.400000095367432, 4.444, - datetime.datetime(2008, 1, 11, 22, 10, 3, 4), - datetime.datetime(2008, 1, 11, 22, 10, 3, 4, ZoneInfo("US/Eastern")), - datetime.datetime(2008, 1, 11, 22, 10, 3, 4), - datetime.datetime(2008, 1, 11, 22, 10, 3), - datetime.datetime(2008, 1, 11, 22, 10, 3), - datetime.timedelta(seconds=3, milliseconds=22), '😂', None, 56677, 67.13, - ['Dan, Ella', 'George'], datetime.date(2018, 3, 17), - None] - - -def test_scan_pandas(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def validate_scan_pandas_results(results: kuzu.QueryResult) -> None: + assert results.get_next() == [ + True, + 1, + 10, + 100, + 1000, + -1, + -10, + -100, + -1000, + -0.5199999809265137, + 5132.12321, + datetime.datetime(1996, 4, 1, 12, 0, 11, 500001), + datetime.datetime(1996, 4, 1, 12, 0, 11, 500001, ZoneInfo("US/Eastern")), + datetime.datetime(1996, 4, 1, 12, 0, 11, 500001), + datetime.datetime(1996, 4, 1, 12, 0, 11, 500000), + datetime.datetime(1996, 4, 1, 12, 0, 11), + datetime.timedelta(microseconds=500), + None, + [], + 528, + 3.562, + ["Alice", None], + datetime.date(1996, 2, 15), + "12331", + ] + assert results.get_next() == [ + False, + 2, + 20, + 200, + 2000, + -2, + -20, + -200, + -2000, + None, + 24.222, + datetime.datetime(1981, 11, 13, 22, 2, 52, 2), + datetime.datetime(1981, 11, 13, 22, 2, 52, 2, ZoneInfo("US/Eastern")), + datetime.datetime(1981, 11, 13, 22, 2, 52, 2), + datetime.datetime(1981, 11, 13, 22, 2, 52), + datetime.datetime(1981, 11, 13, 22, 2, 52), + datetime.timedelta(seconds=1), + "Ascii only", + [40, 20, 10], + -9999, + 4.213, + [], + datetime.date(2013, 2, 22), + "test string", + ] + assert results.get_next() == [ + None, + 3, + 30, + 300, + 3000, + -3, + -30, + -300, + -3000, + -3.299999952316284, + None, + datetime.datetime(1972, 12, 21, 12, 5, 44, 500003), + datetime.datetime(1972, 12, 21, 12, 5, 44, 500003, ZoneInfo("US/Eastern")), + datetime.datetime(1972, 12, 21, 12, 5, 44, 500003), + datetime.datetime(1972, 12, 21, 12, 5, 44, 500000), + datetime.datetime(1972, 12, 21, 12, 5, 44), + datetime.timedelta(seconds=2, milliseconds=500), + "ñ中国字", + [30, None], + None, + None, + None, + datetime.date(2055, 1, 14), + "5.623", + ] + assert results.get_next() == [ + False, + 4, + 40, + 400, + 4000, + -4, + -40, + -400, + -4000, + 4.400000095367432, + 4.444, + datetime.datetime(2008, 1, 11, 22, 10, 3, 4), + datetime.datetime(2008, 1, 11, 22, 10, 3, 4, ZoneInfo("US/Eastern")), + datetime.datetime(2008, 1, 11, 22, 10, 3, 4), + datetime.datetime(2008, 1, 11, 22, 10, 3), + datetime.datetime(2008, 1, 11, 22, 10, 3), + datetime.timedelta(seconds=3, milliseconds=22), + "😂", + None, + 56677, + 67.13, + ["Dan, Ella", "George"], + datetime.date(2018, 3, 17), + None, + ] + + +def test_scan_pandas(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) data = { - 'BOOL': [True, False, None, False], - 'UINT8': np.array([1, 2, 3, 4], dtype=np.uint8), - 'UINT16': np.array([10, 20, 30, 40], dtype=np.uint16), - 'UINT32': np.array([100, 200, 300, 400], dtype=np.uint32), - 'UINT64': np.array([1000, 2000, 3000, 4000], dtype=np.uint64), - 'INT8': np.array([-1, -2, -3, -4], dtype=np.int8), - 'INT16': np.array([-10, -20, -30, -40], dtype=np.int16), - 'INT32': np.array([-100, -200, -300, -400], dtype=np.int32), - 'INT64': np.array([-1000, -2000, -3000, -4000], dtype=np.int64), - 'FLOAT_32': np.array([-0.5199999809265137, float("nan"), -3.299999952316284, 4.400000095367432], - dtype=np.float32), - 'FLOAT_64': np.array([5132.12321, 24.222, float("nan"), 4.444], dtype=np.float64), - 'datetime_microseconds': np.array([ - np.datetime64('1996-04-01T12:00:11.500001000'), - np.datetime64('1981-11-13T22:02:52.000002000'), - np.datetime64('1972-12-21T12:05:44.500003000'), - np.datetime64('2008-01-11T22:10:03.000004000') - ]).astype('datetime64[us]'), - 'datetime_microseconds_tz': np.array([ - np.datetime64('1996-04-01T12:00:11.500001000'), - np.datetime64('1981-11-13T22:02:52.000002000'), - np.datetime64('1972-12-21T12:05:44.500003000'), - np.datetime64('2008-01-11T22:10:03.000004000'), - ]).astype('datetime64[us]'), - 'datetime_nanoseconds': np.array([ - np.datetime64('1996-04-01T12:00:11.500001'), - np.datetime64('1981-11-13T22:02:52.000002'), - np.datetime64('1972-12-21T12:05:44.500003'), - np.datetime64('2008-01-11T22:10:03.000004') - ]).astype('datetime64[ns]'), - 'datetime_milliseconds': np.array([ - np.datetime64('1996-04-01T12:00:11.500001'), - np.datetime64('1981-11-13T22:02:52.000002'), - np.datetime64('1972-12-21T12:05:44.500003'), - np.datetime64('2008-01-11T22:10:03.000004') - ]).astype('datetime64[ms]'), - 'datetime_seconds': np.array([ - np.datetime64('1996-04-01T12:00:11'), - np.datetime64('1981-11-13T22:02:52'), - np.datetime64('1972-12-21T12:05:44'), - np.datetime64('2008-01-11T22:10:03') - ]).astype('datetime64[s]'), - 'timedelta_nanoseconds': [ - np.timedelta64(500000, 'ns'), - np.timedelta64(1000000000, 'ns'), - np.timedelta64(2500000000, 'ns'), - np.timedelta64(3022000000, 'ns') + "BOOL": [True, False, None, False], + "UINT8": np.array([1, 2, 3, 4], dtype=np.uint8), + "UINT16": np.array([10, 20, 30, 40], dtype=np.uint16), + "UINT32": np.array([100, 200, 300, 400], dtype=np.uint32), + "UINT64": np.array([1000, 2000, 3000, 4000], dtype=np.uint64), + "INT8": np.array([-1, -2, -3, -4], dtype=np.int8), + "INT16": np.array([-10, -20, -30, -40], dtype=np.int16), + "INT32": np.array([-100, -200, -300, -400], dtype=np.int32), + "INT64": np.array([-1000, -2000, -3000, -4000], dtype=np.int64), + "FLOAT_32": np.array( + [-0.5199999809265137, float("nan"), -3.299999952316284, 4.400000095367432], dtype=np.float32 + ), + "FLOAT_64": np.array([5132.12321, 24.222, float("nan"), 4.444], dtype=np.float64), + "datetime_microseconds": np.array([ + np.datetime64("1996-04-01T12:00:11.500001000"), + np.datetime64("1981-11-13T22:02:52.000002000"), + np.datetime64("1972-12-21T12:05:44.500003000"), + np.datetime64("2008-01-11T22:10:03.000004000"), + ]).astype("datetime64[us]"), + "datetime_microseconds_tz": np.array([ + np.datetime64("1996-04-01T12:00:11.500001000"), + np.datetime64("1981-11-13T22:02:52.000002000"), + np.datetime64("1972-12-21T12:05:44.500003000"), + np.datetime64("2008-01-11T22:10:03.000004000"), + ]).astype("datetime64[us]"), + "datetime_nanoseconds": np.array([ + np.datetime64("1996-04-01T12:00:11.500001"), + np.datetime64("1981-11-13T22:02:52.000002"), + np.datetime64("1972-12-21T12:05:44.500003"), + np.datetime64("2008-01-11T22:10:03.000004"), + ]).astype("datetime64[ns]"), + "datetime_milliseconds": np.array([ + np.datetime64("1996-04-01T12:00:11.500001"), + np.datetime64("1981-11-13T22:02:52.000002"), + np.datetime64("1972-12-21T12:05:44.500003"), + np.datetime64("2008-01-11T22:10:03.000004"), + ]).astype("datetime64[ms]"), + "datetime_seconds": np.array([ + np.datetime64("1996-04-01T12:00:11"), + np.datetime64("1981-11-13T22:02:52"), + np.datetime64("1972-12-21T12:05:44"), + np.datetime64("2008-01-11T22:10:03"), + ]).astype("datetime64[s]"), + "timedelta_nanoseconds": [ + np.timedelta64(500000, "ns"), + np.timedelta64(1000000000, "ns"), + np.timedelta64(2500000000, "ns"), + np.timedelta64(3022000000, "ns"), ], - 'name': [None, 'Ascii only', 'ñ中国字', '😂'], - 'worked_hours': [[], [40, 20, 10], [30, None], None], - 'int_object': np.array([528, -9999, None, 56677], dtype=object), - 'float_object': np.array([3.562, 4.213, None, 67.13], dtype=object), - 'used_names': np.array([['Alice', None], [], None, ['Dan, Ella', 'George']], dtype=object), - 'past_date': np.array([datetime.date(1996, 2, 15), datetime.date(2013, 2, 22), - datetime.date(2055, 1, 14), datetime.date(2018, 3, 17)], dtype=object), - 'mixed_type': np.array([12331, 'test string', 5.623, None], dtype='object') + "name": [None, "Ascii only", "ñ中国字", "😂"], + "worked_hours": [[], [40, 20, 10], [30, None], None], + "int_object": np.array([528, -9999, None, 56677], dtype=object), + "float_object": np.array([3.562, 4.213, None, 67.13], dtype=object), + "used_names": np.array([["Alice", None], [], None, ["Dan, Ella", "George"]], dtype=object), + "past_date": np.array( + [ + datetime.date(1996, 2, 15), + datetime.date(2013, 2, 22), + datetime.date(2055, 1, 14), + datetime.date(2018, 3, 17), + ], + dtype=object, + ), + "mixed_type": np.array([12331, "test string", 5.623, None], dtype="object"), } df = pd.DataFrame(data) - df['datetime_microseconds_tz'] = df['datetime_microseconds_tz'].dt.tz_localize("US/Eastern") + df["datetime_microseconds_tz"] = df["datetime_microseconds_tz"].dt.tz_localize("US/Eastern") results = conn.execute("CALL READ_PANDAS(df) RETURN *") validate_scan_pandas_results(results) results2 = conn.execute("LOAD FROM df RETURN *") validate_scan_pandas_results(results2) -def test_scan_pandas_timestamp(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_scan_pandas_timestamp(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) ts = np.array( - [datetime.datetime(1996, 2, 15, hour=12, minute=22, second=54), - datetime.datetime(2011, 3, 11, minute=11, hour=5), - None, - datetime.datetime(2033, 2, 11, microsecond=55)], dtype='object') - df = pd.DataFrame({'timestamp': ts}) - # Pandas will automatically convert the column from object to timestamp, so we need to manually cast back to object. - df = df.astype({'timestamp': 'object'}, copy=False) + [ + datetime.datetime(1996, 2, 15, hour=12, minute=22, second=54), + datetime.datetime(2011, 3, 11, minute=11, hour=5), + None, + datetime.datetime(2033, 2, 11, microsecond=55), + ], + dtype="object", + ) + df = pd.DataFrame({"timestamp": ts}) + # Pandas automatically converts the column from object to timestamp, so we need to manually cast back to object. + df = df.astype({"timestamp": "object"}, copy=False) results = conn.execute("CALL READ_PANDAS(df) RETURN *") assert results.get_next() == [datetime.datetime(1996, 2, 15, hour=12, minute=22, second=54)] assert results.get_next() == [datetime.datetime(2011, 3, 11, minute=11, hour=5)] @@ -133,59 +220,70 @@ def test_scan_pandas_timestamp(get_tmp_path): assert results.get_next() == [datetime.datetime(2033, 2, 11, microsecond=55)] -def test_replace_failure(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_replace_failure(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) with pytest.raises(RuntimeError, match=re.escape("Binder exception: Variable x is not in scope.")): conn.execute("LOAD FROM x RETURN *;") - with pytest.raises(RuntimeError, - match=re.escape("Binder exception: Cannot match a built-in function for given function " - "READ_PANDAS(STRING). Supported inputs are\n(POINTER)\n")): + with pytest.raises( + RuntimeError, + match=re.escape( + "Binder exception: Cannot match a built-in function for given function " + "READ_PANDAS(STRING). Supported inputs are\n(POINTER)\n" + ), + ): conn.execute("CALL READ_PANDAS('df213') WHERE id > 20 RETURN id + 5, weight") -def test_int64_overflow(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_int64_overflow(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) - overflow_pd = pd.DataFrame({'id': [4, 2 ** 125]}) - with pytest.raises(RuntimeError, match=re.escape( + overflowpd = pd.DataFrame({"id": [4, 2**125]}) + with pytest.raises( + RuntimeError, + match=re.escape( "Conversion exception: Failed to cast value: " - "Python value '42535295865117307932921825928971026432' to INT64")): - conn.execute("LOAD FROM overflow_pd RETURN *;") + "Python value '42535295865117307932921825928971026432' to INT64" + ), + ): + conn.execute("LOAD FROM overflowpd RETURN *;") -def test_scan_pandas_with_filter(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_scan_pandas_with_filter(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) data = { - 'id': np.array([22, 3, 100], dtype=np.uint8), - 'weight': np.array([23.2, 31.7, 42.9], dtype=np.float64), - 'name': ['ñ', '日本字', '😊'] + "id": np.array([22, 3, 100], dtype=np.uint8), + "weight": np.array([23.2, 31.7, 42.9], dtype=np.float64), + "name": ["ñ", "日本字", "😊"], } df = pd.DataFrame(data) # Dummy query to ensure the READ_PANDAS function is persistent after a write transaction. conn.execute("CREATE NODE TABLE PERSON1(ID INT64, PRIMARY KEY(ID))") results = conn.execute("CALL READ_PANDAS(df) WHERE id > 20 RETURN id + 5, weight, name") - assert results.get_next() == [27, 23.2, 'ñ'] - assert results.get_next() == [105, 42.9, '😊'] + assert results.get_next() == [27, 23.2, "ñ"] + assert results.get_next() == [105, 42.9, "😊"] -def test_large_pd(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_large_pd(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) num_rows = 40000 odd_numbers = [2 * i + 1 for i in range(num_rows)] even_numbers = [2 * i for i in range(num_rows)] - df = pd.DataFrame({'odd': np.array(odd_numbers, dtype=np.int64), 'even': np.array(even_numbers, dtype=np.int64)}) + df = pd.DataFrame({ + "odd": np.array(odd_numbers, dtype=np.int64), + "even": np.array(even_numbers, dtype=np.int64), + }) result = conn.execute("CALL READ_PANDAS(df) RETURN *").get_as_df() - assert result['odd'].to_list() == odd_numbers - assert result['even'].to_list() == even_numbers + assert result["odd"].to_list() == odd_numbers + assert result["even"].to_list() == even_numbers -def test_pandas_scan_demo(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_pandas_scan_demo(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) conn.execute("CREATE NODE TABLE student (ID int64, height int32, PRIMARY KEY(ID))") @@ -198,31 +296,43 @@ def test_pandas_scan_demo(get_tmp_path): age = np.array([42, 23, 33, 57, 67, 39, 11], dtype=np.uint16) height_in_cm = np.array([167, 172, 183, 199, 149, 154, 165], dtype=np.uint32) is_student = np.array([False, True, False, False, False, False, True], dtype=bool) - person = pd.DataFrame({'id': id, 'age': age, 'height': height_in_cm, 'is_student': is_student}) + person = pd.DataFrame({"id": id, "age": age, "height": height_in_cm, "is_student": is_student}) result = conn.execute( - 'CALL READ_PANDAS(person) with avg(height / 2.54) as height_in_inch MATCH (s:student) WHERE s.height > ' - 'height_in_inch RETURN s').get_as_df() + "CALL READ_PANDAS(person) with avg(height / 2.54) as height_in_inch MATCH (s:student) WHERE s.height > " + "height_in_inch RETURN s" + ).get_as_df() assert len(result) == 2 - assert result['s'][0] == {'ID': 0, '_id': {'offset': 0, 'table': 0}, '_label': 'student', 'height': 70} - assert result['s'][1] == {'ID': 4, '_id': {'offset': 2, 'table': 0}, '_label': 'student', 'height': 67} + assert result["s"][0] == {"ID": 0, "_id": {"offset": 0, "table": 0}, "_label": "student", "height": 70} + assert result["s"][1] == {"ID": 4, "_id": {"offset": 2, "table": 0}, "_label": "student", "height": 67} - conn.execute('CREATE NODE TABLE person(ID INT64, age UINT16, height UINT32, is_student BOOLean, PRIMARY KEY(ID))') + conn.execute("CREATE NODE TABLE person(ID INT64, age UINT16, height UINT32, is_student BOOLean, PRIMARY KEY(ID))") conn.execute( - 'CALL READ_PANDAS(person) CREATE (p:person {ID: id, age: age, height: height, is_student: is_student})') + "CALL READ_PANDAS(person) CREATE (p:person {ID: id, age: age, height: height, is_student: is_student})" + ) result = conn.execute("MATCH (p:person) return p.*").get_as_df() - assert np.all(result['p.ID'].to_list() == id) - assert np.all(result['p.age'].to_list() == age) - assert np.all(result['p.height'].to_list() == height_in_cm) - assert np.all(result['p.is_student'].to_list() == is_student) + assert np.all(result["p.ID"].to_list() == id) + assert np.all(result["p.age"].to_list() == age) + assert np.all(result["p.height"].to_list() == height_in_cm) + assert np.all(result["p.is_student"].to_list() == is_student) -def test_scan_all_null(get_tmp_path): - db = kuzu.Database(get_tmp_path) +def test_scan_pandas_copy_subquery(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) conn = kuzu.Connection(db) - data = { - 'id': np.array([None, None, None], dtype=object) - } + data = {"id": np.array([22, 3, 100], dtype=np.int64), "name": ["A", "B", "C"]} + df = pd.DataFrame(data) + conn.execute("CREATE NODE TABLE person(ID INT64, NAME STRING, PRIMARY KEY(ID))") + conn.execute("COPY person FROM (LOAD FROM df RETURN *)") + result = conn.execute("MATCH (p:person) RETURN p.*").get_as_df() + assert result["p.ID"].to_list() == [22, 3, 100] + assert result["p.NAME"].to_list() == ["A", "B", "C"] + + +def test_scan_all_null(tmp_path: Path) -> None: + db = kuzu.Database(tmp_path) + conn = kuzu.Connection(db) + data = {"id": np.array([None, None, None], dtype=object)} df = pd.DataFrame(data) result = conn.execute("CALL READ_PANDAS(df) RETURN *") assert result.get_next() == [None] diff --git a/tools/python_api/test/test_timeout.py b/tools/python_api/test/test_timeout.py index 01f359b7253..683aef30b71 100644 --- a/tools/python_api/test/test_timeout.py +++ b/tools/python_api/test/test_timeout.py @@ -1,7 +1,11 @@ -def test_timeout(establish_connection): - conn, _ = establish_connection +from __future__ import annotations + +import pytest +from type_aliases import ConnDB + + +def test_timeout(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly conn.set_query_timeout(1000) - try: + with pytest.raises(RuntimeError, match="Interrupted."): conn.execute("MATCH (a:person)-[:knows*1..28]->(b:person) RETURN COUNT(*);") - except RuntimeError as err: - assert str(err) == "Interrupted." diff --git a/tools/python_api/test/test_torch_geometric.py b/tools/python_api/test/test_torch_geometric.py index 81123576191..cd4a14f948c 100644 --- a/tools/python_api/test/test_torch_geometric.py +++ b/tools/python_api/test/test_torch_geometric.py @@ -1,15 +1,20 @@ -import torch +from __future__ import annotations + import warnings + import ground_truth +import torch +from type_aliases import ConnDB + -def test_to_torch_geometric_nodes_only(establish_connection): - conn, _ = establish_connection +def test_to_torch_geometric_nodes_only(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:person) return p" res = conn.execute(query) with warnings.catch_warnings(record=True) as ws: torch_geometric_data, pos_to_idx, unconverted_properties, _ = res.get_as_torch_geometric() - warnings_ground_truth = set([ + warnings_ground_truth = { "Property person.courseScoresPerTerm cannot be converted to Tensor (likely due to nested list of variable length). The property is marked as unconverted.", "Property person.height of type FLOAT is not supported by torch_geometric. The property is marked as unconverted.", "Property person.u of type UUID is not supported by torch_geometric. The property is marked as unconverted.", @@ -19,7 +24,7 @@ def test_to_torch_geometric_nodes_only(establish_connection): "Property person.fName of type STRING is not supported by torch_geometric. The property is marked as unconverted.", "Property person.workedHours has an inconsistent shape. The property is marked as unconverted.", "Property person.usedNames of type STRING is not supported by torch_geometric. The property is marked as unconverted.", - ]) + } assert len(ws) == 9 for w in ws: assert str(w.message) in warnings_ground_truth @@ -27,79 +32,97 @@ def test_to_torch_geometric_nodes_only(establish_connection): assert torch_geometric_data.ID.shape == torch.Size([8]) assert torch_geometric_data.ID.dtype == torch.int64 for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['ID'] == torch_geometric_data.ID[i].item() + assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["ID"] == torch_geometric_data.ID[i].item() assert torch_geometric_data.gender.shape == torch.Size([8]) assert torch_geometric_data.gender.dtype == torch.int64 for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['gender'] == torch_geometric_data.gender[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["gender"] + == torch_geometric_data.gender[i].item() + ) assert torch_geometric_data.isStudent.shape == torch.Size([8]) assert torch_geometric_data.isStudent.dtype == torch.bool for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['isStudent'] == torch_geometric_data.isStudent[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["isStudent"] + == torch_geometric_data.isStudent[i].item() + ) assert torch_geometric_data.isWorker.shape == torch.Size([8]) assert torch_geometric_data.isWorker.dtype == torch.bool for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['isWorker'] == torch_geometric_data.isWorker[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["isWorker"] + == torch_geometric_data.isWorker[i].item() + ) assert torch_geometric_data.age.shape == torch.Size([8]) assert torch_geometric_data.age.dtype == torch.int64 for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['age'] == torch_geometric_data.age[i].item() + assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["age"] == torch_geometric_data.age[i].item() assert torch_geometric_data.eyeSight.shape == torch.Size([8]) assert torch_geometric_data.eyeSight.dtype == torch.float32 for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]['eyeSight'] - \ - torch_geometric_data.eyeSight[i].item() < 1e-6 + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["eyeSight"] + - torch_geometric_data.eyeSight[i].item() + < 1e-6 + ) assert len(unconverted_properties) == 9 - assert 'courseScoresPerTerm' in unconverted_properties + assert "courseScoresPerTerm" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['courseScoresPerTerm'] == unconverted_properties['courseScoresPerTerm'][i] - assert 'lastJobDuration' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["courseScoresPerTerm"] + == unconverted_properties["courseScoresPerTerm"][i] + ) + assert "lastJobDuration" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['lastJobDuration'] == unconverted_properties['lastJobDuration'][i] - assert 'registerTime' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["lastJobDuration"] + == unconverted_properties["lastJobDuration"][i] + ) + assert "registerTime" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['registerTime'] == unconverted_properties['registerTime'][i] - assert 'birthdate' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["registerTime"] + == unconverted_properties["registerTime"][i] + ) + assert "birthdate" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['birthdate'] == unconverted_properties['birthdate'][i] - assert 'fName' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["birthdate"] + == unconverted_properties["birthdate"][i] + ) + assert "fName" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['fName'] == unconverted_properties['fName'][i] - assert 'usedNames' in unconverted_properties + assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["fName"] == unconverted_properties["fName"][i] + assert "usedNames" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['usedNames'] == unconverted_properties['usedNames'][i] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["usedNames"] + == unconverted_properties["usedNames"][i] + ) - assert 'workedHours' in unconverted_properties + assert "workedHours" in unconverted_properties for i in range(8): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['workedHours'] == unconverted_properties['workedHours'][i] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["workedHours"] + == unconverted_properties["workedHours"][i] + ) -def test_to_torch_geometric_homogeneous_graph(establish_connection): - conn, _ = establish_connection +def test_to_torch_geometric_homogeneous_graph(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:person)-[r:knows]->(q:person) RETURN p, r, q" res = conn.execute(query) with warnings.catch_warnings(record=True) as ws: torch_geometric_data, pos_to_idx, unconverted_properties, edge_properties = res.get_as_torch_geometric() - warnings_ground_truth = set([ + warnings_ground_truth = { "Property person.courseScoresPerTerm cannot be converted to Tensor (likely due to nested list of variable length). The property is marked as unconverted.", "Property person.height of type FLOAT is not supported by torch_geometric. The property is marked as unconverted.", "Property person.u of type UUID is not supported by torch_geometric. The property is marked as unconverted.", @@ -109,7 +132,7 @@ def test_to_torch_geometric_homogeneous_graph(establish_connection): "Property person.fName of type STRING is not supported by torch_geometric. The property is marked as unconverted.", "Property person.workedHours has an inconsistent shape. The property is marked as unconverted.", "Property person.usedNames of type STRING is not supported by torch_geometric. The property is marked as unconverted.", - ]) + } assert len(ws) == 9 for w in ws: assert str(w.message) in warnings_ground_truth @@ -117,111 +140,141 @@ def test_to_torch_geometric_homogeneous_graph(establish_connection): assert torch_geometric_data.ID.shape == torch.Size([7]) assert torch_geometric_data.ID.dtype == torch.int64 for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['ID'] == torch_geometric_data.ID[i].item() + assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["ID"] == torch_geometric_data.ID[i].item() assert torch_geometric_data.gender.shape == torch.Size([7]) assert torch_geometric_data.gender.dtype == torch.int64 for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['gender'] == torch_geometric_data.gender[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["gender"] + == torch_geometric_data.gender[i].item() + ) assert torch_geometric_data.isStudent.shape == torch.Size([7]) assert torch_geometric_data.isStudent.dtype == torch.bool for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['isStudent'] == torch_geometric_data.isStudent[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["isStudent"] + == torch_geometric_data.isStudent[i].item() + ) assert torch_geometric_data.isWorker.shape == torch.Size([7]) assert torch_geometric_data.isWorker.dtype == torch.bool for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['isWorker'] == torch_geometric_data.isWorker[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["isWorker"] + == torch_geometric_data.isWorker[i].item() + ) assert torch_geometric_data.age.shape == torch.Size([7]) assert torch_geometric_data.age.dtype == torch.int64 for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['age'] == torch_geometric_data.age[i].item() + assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["age"] == torch_geometric_data.age[i].item() assert torch_geometric_data.eyeSight.shape == torch.Size([7]) assert torch_geometric_data.eyeSight.dtype == torch.float32 for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]['eyeSight'] - \ - torch_geometric_data.eyeSight[i].item() < 1e-6 + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["eyeSight"] + - torch_geometric_data.eyeSight[i].item() + < 1e-6 + ) assert len(unconverted_properties) == 9 - assert 'courseScoresPerTerm' in unconverted_properties + assert "courseScoresPerTerm" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['courseScoresPerTerm'] == unconverted_properties['courseScoresPerTerm'][i] - assert 'lastJobDuration' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["courseScoresPerTerm"] + == unconverted_properties["courseScoresPerTerm"][i] + ) + assert "lastJobDuration" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['lastJobDuration'] == unconverted_properties['lastJobDuration'][i] - assert 'registerTime' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["lastJobDuration"] + == unconverted_properties["lastJobDuration"][i] + ) + assert "registerTime" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['registerTime'] == unconverted_properties['registerTime'][i] - assert 'birthdate' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["registerTime"] + == unconverted_properties["registerTime"][i] + ) + assert "birthdate" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['birthdate'] == unconverted_properties['birthdate'][i] - assert 'fName' in unconverted_properties + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["birthdate"] + == unconverted_properties["birthdate"][i] + ) + assert "fName" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['fName'] == unconverted_properties['fName'][i] - assert 'usedNames' in unconverted_properties + assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["fName"] == unconverted_properties["fName"][i] + assert "usedNames" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['usedNames'] == unconverted_properties['usedNames'][i] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["usedNames"] + == unconverted_properties["usedNames"][i] + ) - assert 'workedHours' in unconverted_properties + assert "workedHours" in unconverted_properties for i in range(7): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i] - ]['workedHours'] == unconverted_properties['workedHours'][i] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx[i]]["workedHours"] + == unconverted_properties["workedHours"][i] + ) assert torch_geometric_data.edge_index.shape == torch.Size([2, 14]) for i in range(14): - src, dst = torch_geometric_data.edge_index[0][i].item( - ), torch_geometric_data.edge_index[1][i].item() + src, dst = torch_geometric_data.edge_index[0][i].item(), torch_geometric_data.edge_index[1][i].item() assert src in pos_to_idx assert dst in pos_to_idx assert src != dst assert pos_to_idx[dst] in ground_truth.TINY_SNB_KNOWS_GROUND_TRUTH[pos_to_idx[src]] assert len(edge_properties) == 8 - assert 'date' in edge_properties - assert 'meetTime' in edge_properties - assert 'validInterval' in edge_properties - assert 'comments' in edge_properties - assert 'summary' in edge_properties - assert 'notes' in edge_properties + assert "date" in edge_properties + assert "meetTime" in edge_properties + assert "validInterval" in edge_properties + assert "comments" in edge_properties + assert "summary" in edge_properties + assert "notes" in edge_properties for i in range(14): - src, dst = torch_geometric_data.edge_index[0][i].item( - ), torch_geometric_data.edge_index[1][i].item() + src, dst = torch_geometric_data.edge_index[0][i].item(), torch_geometric_data.edge_index[1][i].item() orginal_src = pos_to_idx[src] orginal_dst = pos_to_idx[dst] assert (orginal_src, orginal_dst) in ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['date'] == edge_properties['date'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['meetTime'] == edge_properties['meetTime'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['validInterval'] == edge_properties['validInterval'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['comments'] == edge_properties['comments'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['summary'] == edge_properties['summary'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['notes'] == edge_properties['notes'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - orginal_src, orginal_dst)]['someMap'] == edge_properties['someMap'][i] - - -def test_to_torch_geometric_heterogeneous_graph(establish_connection): - conn, _ = establish_connection + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["date"] + == edge_properties["date"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["meetTime"] + == edge_properties["meetTime"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["validInterval"] + == edge_properties["validInterval"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["comments"] + == edge_properties["comments"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["summary"] + == edge_properties["summary"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["notes"] + == edge_properties["notes"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(orginal_src, orginal_dst)]["someMap"] + == edge_properties["someMap"][i] + ) + + +def test_to_torch_geometric_heterogeneous_graph(conn_db_readonly: ConnDB) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:person)-[r1:knows]->(q:person)-[r2:workAt]->(o:organisation) RETURN p, q, o, r1, r2" res = conn.execute(query) @@ -229,7 +282,7 @@ def test_to_torch_geometric_heterogeneous_graph(establish_connection): torch_geometric_data, pos_to_idx, unconverted_properties, edge_properties = res.get_as_torch_geometric() assert len(ws) == 13 - warnings_ground_truth = set([ + warnings_ground_truth = { "Property organisation.name of type STRING is not supported by torch_geometric. The property is marked as unconverted.", "Property person.height of type FLOAT is not supported by torch_geometric. The property is marked as unconverted.", "Property person.u of type UUID is not supported by torch_geometric. The property is marked as unconverted.", @@ -242,190 +295,260 @@ def test_to_torch_geometric_heterogeneous_graph(establish_connection): "Property person.usedNames of type STRING is not supported by torch_geometric. The property is marked as unconverted.", "Property organisation.licenseValidInterval of type INTERVAL is not supported by torch_geometric. The property is marked as unconverted.", "Property organisation.state of type STRUCT(revenue:INT16, location:STRING is not supported by torch_geometric. The property is marked as unconverted.", - "Property organisation.info of type UNION(price:FLOAT, movein:DATE, note:STRING) is not supported by torch_geometric. The property is marked as unconverted." - ]) + "Property organisation.info of type UNION(price:FLOAT, movein:DATE, note:STRING) is not supported by torch_geometric. The property is marked as unconverted.", + } for w in ws: assert str(w.message) in warnings_ground_truth - assert torch_geometric_data['person'].ID.shape == torch.Size([4]) - assert torch_geometric_data['person'].ID.dtype == torch.int64 + assert torch_geometric_data["person"].ID.shape == torch.Size([4]) + assert torch_geometric_data["person"].ID.dtype == torch.int64 for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['ID'] == torch_geometric_data['person'].ID[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["ID"] + == torch_geometric_data["person"].ID[i].item() + ) - assert torch_geometric_data['person'].gender.shape == torch.Size([4]) - assert torch_geometric_data['person'].gender.dtype == torch.int64 + assert torch_geometric_data["person"].gender.shape == torch.Size([4]) + assert torch_geometric_data["person"].gender.dtype == torch.int64 for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['gender'] == torch_geometric_data['person'].gender[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["gender"] + == torch_geometric_data["person"].gender[i].item() + ) - assert torch_geometric_data['person'].isStudent.shape == torch.Size([4]) - assert torch_geometric_data['person'].isStudent.dtype == torch.bool + assert torch_geometric_data["person"].isStudent.shape == torch.Size([4]) + assert torch_geometric_data["person"].isStudent.dtype == torch.bool for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['isStudent'] == torch_geometric_data['person'].isStudent[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["isStudent"] + == torch_geometric_data["person"].isStudent[i].item() + ) - assert torch_geometric_data['person'].isWorker.shape == torch.Size([4]) - assert torch_geometric_data['person'].isWorker.dtype == torch.bool + assert torch_geometric_data["person"].isWorker.shape == torch.Size([4]) + assert torch_geometric_data["person"].isWorker.dtype == torch.bool for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['isWorker'] == torch_geometric_data['person'].isWorker[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["isWorker"] + == torch_geometric_data["person"].isWorker[i].item() + ) - assert torch_geometric_data['person'].age.shape == torch.Size([4]) - assert torch_geometric_data['person'].age.dtype == torch.int64 + assert torch_geometric_data["person"].age.shape == torch.Size([4]) + assert torch_geometric_data["person"].age.dtype == torch.int64 for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['age'] == torch_geometric_data['person'].age[i].item() + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["age"] + == torch_geometric_data["person"].age[i].item() + ) - assert torch_geometric_data['person'].eyeSight.shape == torch.Size([4]) - assert torch_geometric_data['person'].eyeSight.dtype == torch.float32 + assert torch_geometric_data["person"].eyeSight.shape == torch.Size([4]) + assert torch_geometric_data["person"].eyeSight.dtype == torch.float32 for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i]]['eyeSight'] - \ - torch_geometric_data['person'].eyeSight[i].item() < 1e-6 - - assert 'person' in unconverted_properties - assert len(unconverted_properties['person']) == 8 - assert 'courseScoresPerTerm' in unconverted_properties['person'] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["eyeSight"] + - torch_geometric_data["person"].eyeSight[i].item() + < 1e-6 + ) + + assert "person" in unconverted_properties + assert len(unconverted_properties["person"]) == 8 + assert "courseScoresPerTerm" in unconverted_properties["person"] for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['courseScoresPerTerm'] == unconverted_properties['person']['courseScoresPerTerm'][i] - assert 'lastJobDuration' in unconverted_properties['person'] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["courseScoresPerTerm"] + == unconverted_properties["person"]["courseScoresPerTerm"][i] + ) + assert "lastJobDuration" in unconverted_properties["person"] for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['lastJobDuration'] == unconverted_properties['person']['lastJobDuration'][i] - assert 'registerTime' in unconverted_properties['person'] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["lastJobDuration"] + == unconverted_properties["person"]["lastJobDuration"][i] + ) + assert "registerTime" in unconverted_properties["person"] for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['registerTime'] == unconverted_properties['person']['registerTime'][i] - assert 'birthdate' in unconverted_properties['person'] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["registerTime"] + == unconverted_properties["person"]["registerTime"][i] + ) + assert "birthdate" in unconverted_properties["person"] for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['birthdate'] == unconverted_properties['person']['birthdate'][i] - assert 'fName' in unconverted_properties['person'] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["birthdate"] + == unconverted_properties["person"]["birthdate"][i] + ) + assert "fName" in unconverted_properties["person"] for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['fName'] == unconverted_properties['person']['fName'][i] - assert 'usedNames' in unconverted_properties['person'] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["fName"] + == unconverted_properties["person"]["fName"][i] + ) + assert "usedNames" in unconverted_properties["person"] for i in range(4): - assert ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx['person'][i] - ]['usedNames'] == unconverted_properties['person']['usedNames'][i] + assert ( + ground_truth.TINY_SNB_PERSONS_GROUND_TRUTH[pos_to_idx["person"][i]]["usedNames"] + == unconverted_properties["person"]["usedNames"][i] + ) - assert torch_geometric_data['person', 'person'].edge_index.shape == torch.Size([ - 2, 6]) + assert torch_geometric_data["person", "person"].edge_index.shape == torch.Size([2, 6]) for i in range(3): - src, dst = torch_geometric_data['person', 'person'].edge_index[0][i].item( - ), torch_geometric_data['person', 'person'].edge_index[1][i].item() - assert src in pos_to_idx['person'] - assert dst in pos_to_idx['person'] + src, dst = ( + torch_geometric_data["person", "person"].edge_index[0][i].item(), + torch_geometric_data["person", "person"].edge_index[1][i].item(), + ) + assert src in pos_to_idx["person"] + assert dst in pos_to_idx["person"] assert src != dst - assert pos_to_idx['person'][dst] in ground_truth.TINY_SNB_KNOWS_GROUND_TRUTH[pos_to_idx['person'][src]] - - assert len(edge_properties['person', 'person']) == 8 - assert 'date' in edge_properties['person', 'person'] - assert 'meetTime' in edge_properties['person', 'person'] - assert 'validInterval' in edge_properties['person', 'person'] - assert 'comments' in edge_properties['person', 'person'] - assert 'summary' in edge_properties['person', 'person'] - assert 'notes' in edge_properties['person', 'person'] - assert '_label' in edge_properties['person', 'person'] + assert pos_to_idx["person"][dst] in ground_truth.TINY_SNB_KNOWS_GROUND_TRUTH[pos_to_idx["person"][src]] + + assert len(edge_properties["person", "person"]) == 8 + assert "date" in edge_properties["person", "person"] + assert "meetTime" in edge_properties["person", "person"] + assert "validInterval" in edge_properties["person", "person"] + assert "comments" in edge_properties["person", "person"] + assert "summary" in edge_properties["person", "person"] + assert "notes" in edge_properties["person", "person"] + assert "_label" in edge_properties["person", "person"] for i in range(3): - src, dst = torch_geometric_data['person', 'person'].edge_index[0][i].item( - ), torch_geometric_data['person', 'person'].edge_index[1][i].item() - original_src, original_dst = pos_to_idx['person'][src], pos_to_idx['person'][dst] + src, dst = ( + torch_geometric_data["person", "person"].edge_index[0][i].item(), + torch_geometric_data["person", "person"].edge_index[1][i].item(), + ) + original_src, original_dst = pos_to_idx["person"][src], pos_to_idx["person"][dst] assert (original_src, original_dst) in ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['date'] == edge_properties['person', 'person']['date'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['meetTime'] == edge_properties['person', 'person']['meetTime'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['validInterval'] == edge_properties['person', 'person']['validInterval'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['comments'] == edge_properties['person', 'person']['comments'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['summary'] == edge_properties['person', 'person']['summary'][i] - assert ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['notes'] == edge_properties['person', 'person']['notes'][i] - assert edge_properties['person', 'person']['_label'][i] == 'knows' - - assert torch_geometric_data['organisation'].ID.shape == torch.Size([2]) - assert torch_geometric_data['organisation'].ID.dtype == torch.int64 + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["date"] + == edge_properties["person", "person"]["date"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["meetTime"] + == edge_properties["person", "person"]["meetTime"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["validInterval"] + == edge_properties["person", "person"]["validInterval"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["comments"] + == edge_properties["person", "person"]["comments"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["summary"] + == edge_properties["person", "person"]["summary"][i] + ) + assert ( + ground_truth.TINY_SNB_KNOWS_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["notes"] + == edge_properties["person", "person"]["notes"][i] + ) + assert edge_properties["person", "person"]["_label"][i] == "knows" + + assert torch_geometric_data["organisation"].ID.shape == torch.Size([2]) + assert torch_geometric_data["organisation"].ID.dtype == torch.int64 for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['ID'] == torch_geometric_data['organisation'].ID[i].item() + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["ID"] + == torch_geometric_data["organisation"].ID[i].item() + ) - assert torch_geometric_data['organisation'].orgCode.shape == torch.Size([ - 2]) - assert torch_geometric_data['organisation'].orgCode.dtype == torch.int64 + assert torch_geometric_data["organisation"].orgCode.shape == torch.Size([2]) + assert torch_geometric_data["organisation"].orgCode.dtype == torch.int64 for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['orgCode'] == torch_geometric_data['organisation'].orgCode[i].item() + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["orgCode"] + == torch_geometric_data["organisation"].orgCode[i].item() + ) - assert torch_geometric_data['organisation'].mark.shape == torch.Size([2]) - assert torch_geometric_data['organisation'].mark.dtype == torch.float32 + assert torch_geometric_data["organisation"].mark.shape == torch.Size([2]) + assert torch_geometric_data["organisation"].mark.dtype == torch.float32 for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['mark'] - torch_geometric_data['organisation'].mark[i].item() < 1e-6 - - assert torch_geometric_data['organisation'].score.shape == torch.Size([2]) - assert torch_geometric_data['organisation'].score.dtype == torch.int64 + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["mark"] + - torch_geometric_data["organisation"].mark[i].item() + < 1e-6 + ) + + assert torch_geometric_data["organisation"].score.shape == torch.Size([2]) + assert torch_geometric_data["organisation"].score.dtype == torch.int64 for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['score'] - torch_geometric_data['organisation'].score[i].item() < 1e-6 - - assert torch_geometric_data['organisation'].rating.shape == torch.Size([2]) - assert torch_geometric_data['organisation'].rating.dtype == torch.float32 + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["score"] + - torch_geometric_data["organisation"].score[i].item() + < 1e-6 + ) + + assert torch_geometric_data["organisation"].rating.shape == torch.Size([2]) + assert torch_geometric_data["organisation"].rating.dtype == torch.float32 for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['rating'] - torch_geometric_data['organisation'].rating[i].item() < 1e-6 - - assert 'organisation' in unconverted_properties - assert len(unconverted_properties['organisation']) == 5 - assert 'name' in unconverted_properties['organisation'] + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["rating"] + - torch_geometric_data["organisation"].rating[i].item() + < 1e-6 + ) + + assert "organisation" in unconverted_properties + assert len(unconverted_properties["organisation"]) == 5 + assert "name" in unconverted_properties["organisation"] for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['name'] == unconverted_properties['organisation']['name'][i] + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["name"] + == unconverted_properties["organisation"]["name"][i] + ) - assert 'history' in unconverted_properties['organisation'] + assert "history" in unconverted_properties["organisation"] for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['history'] == unconverted_properties['organisation']['history'][i] + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["history"] + == unconverted_properties["organisation"]["history"][i] + ) - assert 'licenseValidInterval' in unconverted_properties['organisation'] + assert "licenseValidInterval" in unconverted_properties["organisation"] for i in range(2): - assert ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx['organisation'][i] - ]['licenseValidInterval'] == unconverted_properties['organisation']['licenseValidInterval'][i] + assert ( + ground_truth.TINY_SNB_ORGANISATIONS_GROUND_TRUTH[pos_to_idx["organisation"][i]]["licenseValidInterval"] + == unconverted_properties["organisation"]["licenseValidInterval"][i] + ) - assert torch_geometric_data['person', 'organisation'].edge_index.shape == torch.Size([ - 2, 2]) + assert torch_geometric_data["person", "organisation"].edge_index.shape == torch.Size([2, 2]) for i in range(2): - src, dst = torch_geometric_data['person', 'organisation'].edge_index[0][i].item( - ), torch_geometric_data['person', 'organisation'].edge_index[1][i].item() - assert src in pos_to_idx['person'] - assert dst in pos_to_idx['organisation'] + src, dst = ( + torch_geometric_data["person", "organisation"].edge_index[0][i].item(), + torch_geometric_data["person", "organisation"].edge_index[1][i].item(), + ) + assert src in pos_to_idx["person"] + assert dst in pos_to_idx["organisation"] assert src != dst - assert pos_to_idx['organisation'][dst] in ground_truth.TINY_SNB_WORKS_AT_GROUND_TRUTH[pos_to_idx['person'][src]] - assert len(edge_properties['person', 'organisation']) == 4 - assert 'year' in edge_properties['person', 'organisation'] - assert '_label' in edge_properties['person', 'organisation'] + assert ( + pos_to_idx["organisation"][dst] in ground_truth.TINY_SNB_WORKS_AT_GROUND_TRUTH[pos_to_idx["person"][src]] + ) + assert len(edge_properties["person", "organisation"]) == 4 + assert "year" in edge_properties["person", "organisation"] + assert "_label" in edge_properties["person", "organisation"] for i in range(2): - src, dst = torch_geometric_data['person', 'organisation'].edge_index[0][i].item( - ), torch_geometric_data['person', 'organisation'].edge_index[1][i].item() - original_src, original_dst = pos_to_idx['person'][src], pos_to_idx['organisation'][dst] - assert ground_truth.TINY_SNB_WORKS_AT_PROPERTIES_GROUND_TRUTH[( - original_src, original_dst)]['year'] == edge_properties['person', 'organisation']['year'][i] - assert edge_properties['person', 'organisation']['_label'][i] == 'workAt' - - -def test_to_torch_geometric_multi_dimensional_lists(establish_connection): - conn, _ = establish_connection + src, dst = ( + torch_geometric_data["person", "organisation"].edge_index[0][i].item(), + torch_geometric_data["person", "organisation"].edge_index[1][i].item(), + ) + original_src, original_dst = pos_to_idx["person"][src], pos_to_idx["organisation"][dst] + assert ( + ground_truth.TINY_SNB_WORKS_AT_PROPERTIES_GROUND_TRUTH[(original_src, original_dst)]["year"] + == edge_properties["person", "organisation"]["year"][i] + ) + assert edge_properties["person", "organisation"]["_label"][i] == "workAt" + + +def test_to_torch_geometric_multi_dimensional_lists( + conn_db_readonly: ConnDB, +) -> None: + conn, _ = conn_db_readonly query = "MATCH (t:tensor) RETURN t" res = conn.execute(query) with warnings.catch_warnings(record=True) as ws: torch_geometric_data, pos_to_idx, unconverted_properties, _ = res.get_as_torch_geometric() assert len(ws) == 1 - assert str(ws[0].message) == "Property tensor.oneDimInt has a null value. torch_geometric does not support null values. The property is marked as unconverted." + assert ( + str(ws[0].message) + == "Property tensor.oneDimInt has a null value. torch_geometric does not support null values. The property is marked as unconverted." + ) bool_list = [] float_list = [] @@ -433,9 +556,9 @@ def test_to_torch_geometric_multi_dimensional_lists(establish_connection): for i in range(len(pos_to_idx)): idx = pos_to_idx[i] - bool_list.append(ground_truth.TENSOR_LIST_GROUND_TRUTH[idx]['boolTensor']) - float_list.append(ground_truth.TENSOR_LIST_GROUND_TRUTH[idx]['doubleTensor']) - int_list.append(ground_truth.TENSOR_LIST_GROUND_TRUTH[idx]['intTensor']) + bool_list.append(ground_truth.TENSOR_LIST_GROUND_TRUTH[idx]["boolTensor"]) + float_list.append(ground_truth.TENSOR_LIST_GROUND_TRUTH[idx]["doubleTensor"]) + int_list.append(ground_truth.TENSOR_LIST_GROUND_TRUTH[idx]["intTensor"]) bool_tensor = torch.tensor(bool_list, dtype=torch.bool) float_tensor = torch.tensor(float_list, dtype=torch.float32) @@ -464,42 +587,53 @@ def test_to_torch_geometric_multi_dimensional_lists(establish_connection): assert unconverted_properties["oneDimInt"] == [1, 2, None, None, 5, 6] -def test_to_torch_geometric_no_properties_converted(establish_connection): - conn, _ = establish_connection +def test_to_torch_geometric_no_properties_converted( + conn_db_readonly: ConnDB, +) -> None: + conn, _ = conn_db_readonly query = "MATCH (p:personLongString)-[r:knowsLongString]->(q:personLongString) RETURN p, r, q" res = conn.execute(query) with warnings.catch_warnings(record=True) as ws: torch_geometric_data, pos_to_idx, unconverted_properties, _ = res.get_as_torch_geometric() assert len(ws) == 3 - warnings_ground_truth = set([ + warnings_ground_truth = { "Property personLongString.name of type STRING is not supported by torch_geometric. The property is marked as unconverted.", "Property personLongString.spouse of type STRING is not supported by torch_geometric. The property is marked as unconverted.", - "No nodes found or all node properties are not converted."]) + "No nodes found or all node properties are not converted.", + } for w in ws: assert str(w.message) in warnings_ground_truth - assert torch_geometric_data['personLongString'] == {} - assert torch_geometric_data['personLongString', - 'personLongString'].edge_index.shape == torch.Size([2, 1]) + assert torch_geometric_data["personLongString"] == {} + assert torch_geometric_data["personLongString", "personLongString"].edge_index.shape == torch.Size([2, 1]) for i in range(1): - src, dst = torch_geometric_data['personLongString', 'personLongString'].edge_index[0][i].item( - ), torch_geometric_data['personLongString', 'personLongString'].edge_index[1][i].item() - assert src in pos_to_idx['personLongString'] - assert dst in pos_to_idx['personLongString'] + src, dst = ( + torch_geometric_data["personLongString", "personLongString"].edge_index[0][i].item(), + torch_geometric_data["personLongString", "personLongString"].edge_index[1][i].item(), + ) + assert src in pos_to_idx["personLongString"] + assert dst in pos_to_idx["personLongString"] assert src != dst - assert pos_to_idx['personLongString'][dst] in ground_truth.PERSONLONGSTRING_KNOWS_GROUND_TRUTH[pos_to_idx['personLongString'][src]] + assert ( + pos_to_idx["personLongString"][dst] + in ground_truth.PERSONLONGSTRING_KNOWS_GROUND_TRUTH[pos_to_idx["personLongString"][src]] + ) assert len(unconverted_properties) == 1 - assert len(unconverted_properties['personLongString']) == 2 + assert len(unconverted_properties["personLongString"]) == 2 - assert 'spouse' in unconverted_properties['personLongString'] - assert len(unconverted_properties['personLongString']['spouse']) == 2 + assert "spouse" in unconverted_properties["personLongString"] + assert len(unconverted_properties["personLongString"]["spouse"]) == 2 for i in range(2): - assert ground_truth.PERSONLONGSTRING_GROUND_TRUTH[pos_to_idx['personLongString'][i] - ]['spouse'] == unconverted_properties['personLongString']['spouse'][i] + assert ( + ground_truth.PERSONLONGSTRING_GROUND_TRUTH[pos_to_idx["personLongString"][i]]["spouse"] + == unconverted_properties["personLongString"]["spouse"][i] + ) - assert 'name' in unconverted_properties['personLongString'] + assert "name" in unconverted_properties["personLongString"] for i in range(2): - assert ground_truth.PERSONLONGSTRING_GROUND_TRUTH[pos_to_idx['personLongString'][i] - ]['name'] == unconverted_properties['personLongString']['name'][i] + assert ( + ground_truth.PERSONLONGSTRING_GROUND_TRUTH[pos_to_idx["personLongString"][i]]["name"] + == unconverted_properties["personLongString"]["name"][i] + ) diff --git a/tools/python_api/test/test_torch_geometric_remote_backend.py b/tools/python_api/test/test_torch_geometric_remote_backend.py index e44b0ff959b..ccd90288e69 100644 --- a/tools/python_api/test/test_torch_geometric_remote_backend.py +++ b/tools/python_api/test/test_torch_geometric_remote_backend.py @@ -1,9 +1,11 @@ -import torch +from __future__ import annotations + import random -import sys -from test_helper import KUZU_ROOT import kuzu +import torch +from test_helper import KUZU_ROOT +from type_aliases import ConnDB TINY_SNB_KNOWS_GROUND_TRUTH = { 0: [2, 3, 5], @@ -16,95 +18,101 @@ TINY_SNB_PERSON_IDS_GROUND_TRUTH = [0, 2, 3, 5, 7, 8, 9, 10] -def test_remote_backend_graph_store(establish_connection): - _, db = establish_connection +def test_remote_backend_graph_store(conn_db_readonly: ConnDB) -> None: + _, db = conn_db_readonly fs, gs = db.get_torch_geometric_remote_backend() - edge_idx = gs.get_edge_index( - ('person', 'knows', 'person'), layout='coo', is_sorted=False) + edge_idx = gs.get_edge_index(("person", "knows", "person"), layout="coo", is_sorted=False) assert edge_idx.shape == torch.Size([2, 14]) for i in range(14): src = edge_idx[0, i].item() - src_id = fs['person', 'ID', src].item() + src_id = fs["person", "ID", src].item() dst = edge_idx[1, i].item() - dst_id = fs['person', 'ID', dst].item() + dst_id = fs["person", "ID", dst].item() assert src_id in TINY_SNB_KNOWS_GROUND_TRUTH assert dst_id in TINY_SNB_KNOWS_GROUND_TRUTH[src_id] -def test_remote_backend_feature_store_idx(establish_connection): - _, db = establish_connection +def test_remote_backend_feature_store_idx(conn_db_readonly: ConnDB) -> None: + _, db = conn_db_readonly fs, _ = db.get_torch_geometric_remote_backend() id_set = set(TINY_SNB_PERSON_IDS_GROUND_TRUTH) index_to_id = {} # Individual index access for i in range(len(id_set)): - assert fs['person', 'ID', i].item() in id_set - id_set.remove(fs['person', 'ID', i].item()) - index_to_id[i] = fs['person', 'ID', i].item() + assert fs["person", "ID", i].item() in id_set + id_set.remove(fs["person", "ID", i].item()) + index_to_id[i] = fs["person", "ID", i].item() # Range index access - for i in range(len(index_to_id)-3): - ids = fs['person', 'ID', i:i+3] + for i in range(len(index_to_id) - 3): + ids = fs["person", "ID", i : i + 3] for j in range(3): - assert ids[j].item() == index_to_id[i+j] + assert ids[j].item() == index_to_id[i + j] # Multiple index access indicies = random.sample(range(len(index_to_id)), 4) - ids = fs['person', 'ID', indicies] + ids = fs["person", "ID", indicies] for i in range(4): idx = indicies[i] assert ids[i].item() == index_to_id[idx] # No index access - ids = fs['person', 'ID', None] + ids = fs["person", "ID", None] assert len(ids) == len(index_to_id) for i in range(len(ids)): assert ids[i].item() == index_to_id[i] -def test_remote_backend_feature_store_types_1d(establish_connection): - _, db = establish_connection +def test_remote_backend_feature_store_types_1d(conn_db_readonly: ConnDB) -> None: + _, db = conn_db_readonly fs, _ = db.get_torch_geometric_remote_backend() for i in range(3): - assert fs['npyoned', 'i64', i].item() - i == 1 - assert fs['npyoned', 'i32', i].item() - i == 1 - assert fs['npyoned', 'i16', i].item() - i == 1 - assert fs['npyoned', 'f64', i].item() - i - 1 < 1e-6 - assert fs['npyoned', 'f32', i].item() - i - 1 < 1e-6 + assert fs["npyoned", "i64", i].item() - i == 1 + assert fs["npyoned", "i32", i].item() - i == 1 + assert fs["npyoned", "i16", i].item() - i == 1 + assert fs["npyoned", "f64", i].item() - i - 1 < 1e-6 + assert fs["npyoned", "f32", i].item() - i - 1 < 1e-6 -def test_remote_backend_feature_store_types_2d(establish_connection): - _, db = establish_connection +def test_remote_backend_feature_store_types_2d(conn_db_readonly: ConnDB) -> None: + _, db = conn_db_readonly fs, _ = db.get_torch_geometric_remote_backend() for i in range(3): - i64 = fs['npytwod', 'i64', i] + i64 = fs["npytwod", "i64", i] assert i64.shape == torch.Size([1, 3]) base_number = (i * 3) + 1 for j in range(3): assert i64[0, j].item() == base_number + j - i32 = fs['npytwod', 'i32', i] + i32 = fs["npytwod", "i32", i] assert i32.shape == torch.Size([1, 3]) for j in range(3): assert i32[0, j].item() == base_number + j - i16 = fs['npytwod', 'i16', i] + i16 = fs["npytwod", "i16", i] assert i16.shape == torch.Size([1, 3]) for j in range(3): assert i16[0, j].item() == base_number + j - f64 = fs['npytwod', 'f64', i] + f64 = fs["npytwod", "f64", i] assert f64.shape == torch.Size([1, 3]) for j in range(3): assert f64[0, j].item() - (base_number + j) - 1 < 1e-6 - f32 = fs['npytwod', 'f32', i] + f32 = fs["npytwod", "f32", i] assert f32.shape == torch.Size([1, 3]) for j in range(3): assert f32[0, j].item() - (base_number + j) - 1 < 1e-6 -def test_remote_backend_20k(establish_connection): - _, db = establish_connection + +def test_remote_backend_20k(conn_db_readwrite: ConnDB) -> None: + _, db = conn_db_readwrite conn = kuzu.Connection(db, num_threads=1) - conn.execute('create node table npy20k (id INT64,f32 FLOAT[10],PRIMARY KEY(id));') - conn.execute(f'copy npy20k from ("{KUZU_ROOT}/dataset/npy-20k/id_int64.npy", "{KUZU_ROOT}/dataset/npy-20k/two_dim_float.npy") by column;') + conn.execute("CREATE NODE TABLE npy20k (id INT64,f32 FLOAT[10],PRIMARY KEY(id));") + conn.execute( + f""" + COPY npy20k FROM ( + "{KUZU_ROOT}/dataset/npy-20k/id_int64.npy", + "{KUZU_ROOT}/dataset/npy-20k/two_dim_float.npy") BY COLUMN; + """ + ) del conn fs, _ = db.get_torch_geometric_remote_backend(8) for i in range(20000): - assert fs['npy20k', 'id', i].item() == i + assert fs["npy20k", "id", i].item() == i diff --git a/tools/python_api/test/test_version.py b/tools/python_api/test/test_version.py index f5ed761d02e..7ac987129f7 100644 --- a/tools/python_api/test/test_version.py +++ b/tools/python_api/test/test_version.py @@ -1,4 +1,6 @@ -def test_version(): +def test_version() -> None: import kuzu + assert kuzu.version != "" assert kuzu.storage_version > 0 + assert kuzu.version == kuzu.__version__ diff --git a/tools/python_api/test/type_aliases.py b/tools/python_api/test/type_aliases.py new file mode 100644 index 00000000000..8baf0dc57b4 --- /dev/null +++ b/tools/python_api/test/type_aliases.py @@ -0,0 +1,10 @@ +import sys + +from kuzu import Connection, Database + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +ConnDB: TypeAlias = tuple[Connection, Database] diff --git a/tools/rust_api/Cargo.lock b/tools/rust_api/Cargo.lock index 5ca7ff68fc2..ad0d80540a6 100644 --- a/tools/rust_api/Cargo.lock +++ b/tools/rust_api/Cargo.lock @@ -426,7 +426,7 @@ dependencies = [ [[package]] name = "kuzu" -version = "0.3.1" +version = "0.3.2" dependencies = [ "anyhow", "arrow", diff --git a/tools/rust_api/Cargo.toml b/tools/rust_api/Cargo.toml index 9e9577e772f..02bd46173e0 100644 --- a/tools/rust_api/Cargo.toml +++ b/tools/rust_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kuzu" -version = "0.3.1" +version = "0.3.2" description = "An in-process property graph database management system built for query speed and scalability" # Note: 1.72 required for testing due to latest dependencies of the arrow feature rust-version = "1.60" @@ -14,7 +14,6 @@ include = [ "build.rs", "/src", "/include", - "/kuzu-src/extension", "/kuzu-src/src", "/kuzu-src/third_party", "/kuzu-src/Makefile", diff --git a/tools/rust_api/include/kuzu_rs.h b/tools/rust_api/include/kuzu_rs.h index e5661ef45aa..0155aa4d97b 100644 --- a/tools/rust_api/include/kuzu_rs.h +++ b/tools/rust_api/include/kuzu_rs.h @@ -11,7 +11,7 @@ #include "common/types/value/rel.h" #include "common/types/value/value.h" #include "main/kuzu.h" -#include "storage/storage_info.h" +#include "storage/storage_version_info.h" #else #include #endif @@ -39,9 +39,9 @@ struct QueryParams { std::unique_ptr new_params(); std::unique_ptr create_logical_type(kuzu::common::LogicalTypeID id); -std::unique_ptr create_logical_type_var_list( +std::unique_ptr create_logical_type_list( std::unique_ptr childType); -std::unique_ptr create_logical_type_fixed_list( +std::unique_ptr create_logical_type_array( std::unique_ptr childType, uint64_t numElements); inline std::unique_ptr create_logical_type_struct( @@ -68,11 +68,11 @@ inline std::unique_ptr create_logical_type_rdf_varian return kuzu::common::LogicalType::RDF_VARIANT(); } -const kuzu::common::LogicalType& logical_type_get_var_list_child_type( +const kuzu::common::LogicalType& logical_type_get_list_child_type( const kuzu::common::LogicalType& logicalType); -const kuzu::common::LogicalType& logical_type_get_fixed_list_child_type( +const kuzu::common::LogicalType& logical_type_get_array_child_type( const kuzu::common::LogicalType& logicalType); -uint64_t logical_type_get_fixed_list_num_elements(const kuzu::common::LogicalType& logicalType); +uint64_t logical_type_get_array_num_elements(const kuzu::common::LogicalType& logicalType); rust::Vec logical_type_get_struct_field_names(const kuzu::common::LogicalType& value); std::unique_ptr> logical_type_get_struct_field_types( diff --git a/tools/rust_api/src/connection.rs b/tools/rust_api/src/connection.rs index a10394fe226..853d941f287 100644 --- a/tools/rust_api/src/connection.rs +++ b/tools/rust_api/src/connection.rs @@ -128,7 +128,7 @@ impl<'a> Connection<'a> { // should be generic. // // E.g. - // let result: QueryResult> = conn.query("...")?; + // let result: QueryResult> = conn.query("...")?; // let result: QueryResult = conn.query("...")?; // // But this would really just be syntactic sugar wrapping the current system @@ -258,31 +258,6 @@ Invalid input : expected rule oC_SingleQuery (line: 1, o Ok(()) } - #[test] - fn test_params_invalid_type() -> Result<()> { - let temp_dir = tempfile::tempdir()?; - let db = Database::new(temp_dir.path(), SystemConfig::default())?; - let conn = Connection::new(&db)?; - conn.query("CREATE NODE TABLE Person(name STRING, age INT16, PRIMARY KEY(name));")?; - conn.query("CREATE (:Person {name: 'Alice', age: 25});")?; - conn.query("CREATE (:Person {name: 'Bob', age: 30});")?; - - let mut statement = conn.prepare("MATCH (a:Person) WHERE a.age = $age RETURN a.name;")?; - let result: Error = conn - .execute( - &mut statement, - vec![("age", Value::String("25".to_string()))], - ) - .expect_err("Age should be an int16!") - .into(); - assert_eq!( - result.to_string(), - "Query execution failed: Parameter age has data type STRING but expects INT16." - ); - temp_dir.close()?; - Ok(()) - } - #[test] fn test_multithreaded_single_conn() -> Result<()> { let temp_dir = tempfile::tempdir()?; diff --git a/tools/rust_api/src/ffi.rs b/tools/rust_api/src/ffi.rs index a547c398911..f906838285b 100644 --- a/tools/rust_api/src/ffi.rs +++ b/tools/rust_api/src/ffi.rs @@ -72,20 +72,20 @@ pub(crate) mod ffi { TIMESTAMP_NS = 38, TIMESTAMP_TZ = 39, INTERVAL = 40, - FIXED_LIST = 41, INTERNAL_ID = 42, // variable size types STRING = 50, BLOB = 51, - VAR_LIST = 52, - STRUCT = 53, - MAP = 54, - UNION = 55, - RDF_VARIANT = 56, - - UUID = 58, + LIST = 52, + ARRAY = 53, + STRUCT = 54, + MAP = 55, + UNION = 56, + RDF_VARIANT = 57, + + UUID = 59, } #[namespace = "kuzu::common"] @@ -205,10 +205,8 @@ pub(crate) mod ffi { fn getLogicalTypeID(&self) -> LogicalTypeID; fn create_logical_type(id: LogicalTypeID) -> UniquePtr; - fn create_logical_type_var_list( - child_type: UniquePtr, - ) -> UniquePtr; - fn create_logical_type_fixed_list( + fn create_logical_type_list(child_type: UniquePtr) -> UniquePtr; + fn create_logical_type_array( child_type: UniquePtr, num_elements: u64, ) -> UniquePtr; @@ -225,9 +223,9 @@ pub(crate) mod ffi { valueType: UniquePtr, ) -> UniquePtr; - fn logical_type_get_var_list_child_type(value: &LogicalType) -> &LogicalType; - fn logical_type_get_fixed_list_child_type(value: &LogicalType) -> &LogicalType; - fn logical_type_get_fixed_list_num_elements(value: &LogicalType) -> u64; + fn logical_type_get_list_child_type(value: &LogicalType) -> &LogicalType; + fn logical_type_get_array_child_type(value: &LogicalType) -> &LogicalType; + fn logical_type_get_array_num_elements(value: &LogicalType) -> u64; fn logical_type_get_struct_field_names(value: &LogicalType) -> Vec; fn logical_type_get_struct_field_types( value: &LogicalType, diff --git a/tools/rust_api/src/kuzu_rs.cpp b/tools/rust_api/src/kuzu_rs.cpp index d06ef995868..545291d3424 100644 --- a/tools/rust_api/src/kuzu_rs.cpp +++ b/tools/rust_api/src/kuzu_rs.cpp @@ -1,6 +1,6 @@ #include "kuzu_rs.h" -using kuzu::common::FixedListTypeInfo; +using kuzu::common::ArrayTypeInfo; using kuzu::common::Interval; using kuzu::common::LogicalType; using kuzu::common::LogicalTypeID; @@ -8,7 +8,7 @@ using kuzu::common::NodeVal; using kuzu::common::RelVal; using kuzu::common::StructField; using kuzu::common::Value; -using kuzu::common::VarListTypeInfo; +using kuzu::common::ListTypeInfo; using kuzu::main::Connection; using kuzu::main::Database; using kuzu::main::SystemConfig; @@ -22,13 +22,13 @@ std::unique_ptr new_params() { std::unique_ptr create_logical_type(kuzu::common::LogicalTypeID id) { return std::make_unique(id); } -std::unique_ptr create_logical_type_var_list(std::unique_ptr childType) { - return LogicalType::VAR_LIST(std::move(childType)); +std::unique_ptr create_logical_type_list(std::unique_ptr childType) { + return LogicalType::LIST(std::move(childType)); } -std::unique_ptr create_logical_type_fixed_list( +std::unique_ptr create_logical_type_array( std::unique_ptr childType, uint64_t numElements) { - return LogicalType::FIXED_LIST(std::move(childType), numElements); + return LogicalType::ARRAY(std::move(childType), numElements); } std::unique_ptr create_logical_type_map( @@ -36,14 +36,14 @@ std::unique_ptr create_logical_type_map( return LogicalType::MAP(std::move(keyType), std::move(valueType)); } -const LogicalType& logical_type_get_var_list_child_type(const LogicalType& logicalType) { - return *kuzu::common::VarListType::getChildType(&logicalType); +const LogicalType& logical_type_get_list_child_type(const LogicalType& logicalType) { + return *kuzu::common::ListType::getChildType(&logicalType); } -const LogicalType& logical_type_get_fixed_list_child_type(const LogicalType& logicalType) { - return *kuzu::common::FixedListType::getChildType(&logicalType); +const LogicalType& logical_type_get_array_child_type(const LogicalType& logicalType) { + return *kuzu::common::ArrayType::getChildType(&logicalType); } -uint64_t logical_type_get_fixed_list_num_elements(const LogicalType& logicalType) { - return kuzu::common::FixedListType::getNumValuesInList(&logicalType); +uint64_t logical_type_get_array_num_elements(const LogicalType& logicalType) { + return kuzu::common::ArrayType::getNumElements(&logicalType); } rust::Vec logical_type_get_struct_field_names( diff --git a/tools/rust_api/src/lib.rs b/tools/rust_api/src/lib.rs index 883a01432b1..0775a451f59 100644 --- a/tools/rust_api/src/lib.rs +++ b/tools/rust_api/src/lib.rs @@ -23,13 +23,15 @@ //! //! ## Safety //! -//! Generally, use of of this API is safe, however creating multiple databases in the same -//! scope is not safe. +//! Generally, use of this API is safe - however creating multiple databases in the same +//! scope is not considered safe. //! If you need to access multiple databases you will need to do so in separate processes. //! //! ## Building //! //! By default, the kuzu C++ library will be compiled from source and statically linked. +//! If the kuzu C++ library is not being built using multiple threads by default, you can set the +//! CMAKE_BUILD_PARALLEL_LEVEL environment variable to potentially speed up the build process. //! //! If you want to instead link against a pre-built version of the library, the following environment //! variables can be used to configure the build process: diff --git a/tools/rust_api/src/logical_type.rs b/tools/rust_api/src/logical_type.rs index c16b8d53bab..2b562b8707d 100644 --- a/tools/rust_api/src/logical_type.rs +++ b/tools/rust_api/src/logical_type.rs @@ -54,12 +54,12 @@ pub enum LogicalType { String, /// Correponds to [Value::Blob](crate::value::Value::Blob) Blob, - /// Correponds to [Value::VarList](crate::value::Value::VarList) - VarList { + /// Correponds to [Value::List](crate::value::Value::List) + List { child_type: Box, }, - /// Correponds to [Value::FixedList](crate::value::Value::FixedList) - FixedList { + /// Correponds to [Value::Array](crate::value::Value::Array) + Array { child_type: Box, num_elements: u64, }, @@ -118,16 +118,12 @@ impl From<&ffi::LogicalType> for LogicalType { LogicalTypeID::TIMESTAMP_MS => LogicalType::TimestampMs, LogicalTypeID::TIMESTAMP_SEC => LogicalType::TimestampSec, LogicalTypeID::INTERNAL_ID => LogicalType::InternalID, - LogicalTypeID::VAR_LIST => LogicalType::VarList { - child_type: Box::new( - ffi::logical_type_get_var_list_child_type(logical_type).into(), - ), + LogicalTypeID::LIST => LogicalType::List { + child_type: Box::new(ffi::logical_type_get_list_child_type(logical_type).into()), }, - LogicalTypeID::FIXED_LIST => LogicalType::FixedList { - child_type: Box::new( - ffi::logical_type_get_fixed_list_child_type(logical_type).into(), - ), - num_elements: ffi::logical_type_get_fixed_list_num_elements(logical_type), + LogicalTypeID::ARRAY => LogicalType::Array { + child_type: Box::new(ffi::logical_type_get_array_child_type(logical_type).into()), + num_elements: ffi::logical_type_get_array_num_elements(logical_type), }, LogicalTypeID::STRUCT => { let names = ffi::logical_type_get_struct_field_names(logical_type); @@ -143,7 +139,7 @@ impl From<&ffi::LogicalType> for LogicalType { LogicalTypeID::REL => LogicalType::Rel, LogicalTypeID::RECURSIVE_REL => LogicalType::RecursiveRel, LogicalTypeID::MAP => { - let child_types = ffi::logical_type_get_var_list_child_type(logical_type); + let child_types = ffi::logical_type_get_list_child_type(logical_type); let types = ffi::logical_type_get_struct_field_types(child_types); let key_type = types .as_ref() @@ -214,13 +210,13 @@ impl From<&LogicalType> for cxx::UniquePtr { | LogicalType::Rel | LogicalType::RecursiveRel | LogicalType::UUID => ffi::create_logical_type(typ.id()), - LogicalType::VarList { child_type } => { - ffi::create_logical_type_var_list(child_type.as_ref().into()) + LogicalType::List { child_type } => { + ffi::create_logical_type_list(child_type.as_ref().into()) } - LogicalType::FixedList { + LogicalType::Array { child_type, num_elements, - } => ffi::create_logical_type_fixed_list(child_type.as_ref().into(), *num_elements), + } => ffi::create_logical_type_array(child_type.as_ref().into(), *num_elements), LogicalType::Struct { fields } => { let mut builder = ffi::create_type_list(); let mut names = vec![]; @@ -278,8 +274,8 @@ impl LogicalType { LogicalType::TimestampMs => LogicalTypeID::TIMESTAMP_MS, LogicalType::TimestampSec => LogicalTypeID::TIMESTAMP_SEC, LogicalType::InternalID => LogicalTypeID::INTERNAL_ID, - LogicalType::VarList { .. } => LogicalTypeID::VAR_LIST, - LogicalType::FixedList { .. } => LogicalTypeID::FIXED_LIST, + LogicalType::List { .. } => LogicalTypeID::LIST, + LogicalType::Array { .. } => LogicalTypeID::ARRAY, LogicalType::Struct { .. } => LogicalTypeID::STRUCT, LogicalType::Node => LogicalTypeID::NODE, LogicalType::Rel => LogicalTypeID::REL, diff --git a/tools/rust_api/src/value.rs b/tools/rust_api/src/value.rs index ab5853c6b1c..9f07af1bed9 100644 --- a/tools/rust_api/src/value.rs +++ b/tools/rust_api/src/value.rs @@ -244,10 +244,10 @@ pub enum Value { // LogicalType is necessary so that we can pass the correct type to the C++ API if the list is empty. /// These must contain elements which are all the given type. /// - VarList(LogicalType, Vec), + List(LogicalType, Vec), /// These must contain elements which are all the same type. /// - FixedList(LogicalType, Vec), + Array(LogicalType, Vec), /// Struct(Vec<(String, Value)>), Node(NodeVal), @@ -300,7 +300,7 @@ impl std::fmt::Display for Value { Value::String(x) => write!(f, "{x}"), Value::Blob(x) => write!(f, "{x:x?}"), Value::Null(_) => write!(f, ""), - Value::VarList(_, x) | Value::FixedList(_, x) => display_list(f, x), + Value::List(_, x) | Value::Array(_, x) => display_list(f, x), // Note: These don't match kuzu's toString, but we probably don't want them to Value::Interval(x) => write!(f, "{x}"), Value::Timestamp(x) => write!(f, "{x}"), @@ -373,10 +373,10 @@ impl From<&Value> for LogicalType { Value::String(_) => LogicalType::String, Value::Blob(_) => LogicalType::Blob, Value::Null(x) => x.clone(), - Value::VarList(x, _) => LogicalType::VarList { + Value::List(x, _) => LogicalType::List { child_type: Box::new(x.clone()), }, - Value::FixedList(x, value) => LogicalType::FixedList { + Value::Array(x, value) => LogicalType::Array { child_type: Box::new(x.clone()), num_elements: value.len() as u64, }, @@ -497,26 +497,26 @@ impl TryFrom<&ffi::Value> for Value { .map(Value::TimestampSec) .ok_or(ConversionError::TimestampSec(sec)) } - LogicalTypeID::VAR_LIST => { + LogicalTypeID::LIST => { let mut result = vec![]; for index in 0..ffi::value_get_children_size(value) { let value: Value = ffi::value_get_child(value, index).try_into()?; result.push(value); } - if let LogicalType::VarList { child_type } = value.into() { - Ok(Value::VarList(*child_type, result)) + if let LogicalType::List { child_type } = value.into() { + Ok(Value::List(*child_type, result)) } else { unreachable!() } } - LogicalTypeID::FIXED_LIST => { + LogicalTypeID::ARRAY => { let mut result = vec![]; for index in 0..ffi::value_get_children_size(value) { let value: Value = ffi::value_get_child(value, index).try_into()?; result.push(value); } - if let LogicalType::FixedList { child_type, .. } = value.into() { - Ok(Value::FixedList(*child_type, result)) + if let LogicalType::Array { child_type, .. } = value.into() { + Ok(Value::Array(*child_type, result)) } else { unreachable!() } @@ -612,7 +612,7 @@ impl TryFrom<&ffi::Value> for Value { LogicalTypeID::RECURSIVE_REL => { let nodes: Value = ffi::recursive_rel_get_nodes(value).try_into()?; let rels: Value = ffi::recursive_rel_get_rels(value).try_into()?; - let nodes = if let Value::VarList(LogicalType::Node, nodes) = nodes { + let nodes = if let Value::List(LogicalType::Node, nodes) = nodes { nodes.into_iter().map(|x| { if let Value::Node(x) = x { x @@ -623,7 +623,7 @@ impl TryFrom<&ffi::Value> for Value { } else { panic!("Unexpected value in RecursiveRel's rels: {}", rels) }; - let rels = if let Value::VarList(LogicalType::Rel, rels) = rels { + let rels = if let Value::List(LogicalType::Rel, rels) = rels { rels.into_iter().map(|x| { if let Value::Rel(x) = x { x @@ -811,13 +811,13 @@ impl TryInto> for Value { let (months, days, micros) = get_interval_t(value); Ok(ffi::create_value_interval(months, days, micros)) } - Value::VarList(typ, value) => { + Value::List(typ, value) => { let mut builder = ffi::create_list(); for elem in value { builder.pin_mut().insert(elem.try_into()?); } Ok(ffi::get_list_value( - (&LogicalType::VarList { + (&LogicalType::List { child_type: Box::new(typ), }) .into(), @@ -848,14 +848,14 @@ impl TryInto> for Value { builder, )) } - Value::FixedList(typ, value) => { + Value::Array(typ, value) => { let mut builder = ffi::create_list(); let len = value.len(); for elem in value { builder.pin_mut().insert(elem.try_into()?); } Ok(ffi::get_list_value( - (&LogicalType::FixedList { + (&LogicalType::Array { child_type: Box::new(typ), num_elements: len as u64, }) @@ -1122,8 +1122,8 @@ mod tests { } type_tests! { - convert_var_list_type: LogicalType::VarList { child_type: Box::new(LogicalType::String) }, - convert_fixed_list_type: LogicalType::FixedList { child_type: Box::new(LogicalType::Int64), num_elements: 3 }, + convert_list_type: LogicalType::List { child_type: Box::new(LogicalType::String) }, + convert_array_type: LogicalType::Array { child_type: Box::new(LogicalType::Int64), num_elements: 3 }, convert_int8_type: LogicalType::Int8, convert_int16_type: LogicalType::Int16, convert_int32_type: LogicalType::Int32, @@ -1157,9 +1157,9 @@ mod tests { } value_tests! { - convert_var_list: Value::VarList(LogicalType::String, vec!["Alice".into(), "Bob".into()]), - convert_var_list_empty: Value::VarList(LogicalType::String, vec![]), - convert_fixed_list: Value::FixedList(LogicalType::String, vec!["Alice".into(), "Bob".into()]), + convert_list: Value::List(LogicalType::String, vec!["Alice".into(), "Bob".into()]), + convert_list_empty: Value::List(LogicalType::String, vec![]), + convert_array: Value::Array(LogicalType::String, vec!["Alice".into(), "Bob".into()]), convert_int8: Value::Int8(0), convert_int16: Value::Int16(1), convert_int32: Value::Int32(2), @@ -1186,8 +1186,8 @@ mod tests { convert_string: Value::String("Hello World".to_string()), convert_blob: Value::Blob("Hello World".into()), convert_bool: Value::Bool(false), - convert_null: Value::Null(LogicalType::VarList { - child_type: Box::new(LogicalType::FixedList { child_type: Box::new(LogicalType::Int16), num_elements: 3 }) + convert_null: Value::Null(LogicalType::List { + child_type: Box::new(LogicalType::Array { child_type: Box::new(LogicalType::Int16), num_elements: 3 }) }), convert_struct: Value::Struct(vec![("NAME".to_string(), "Alice".into()), ("AGE".to_string(), 25.into())]), convert_internal_id: Value::InternalID(InternalID { table_id: 0, offset: 0 }), @@ -1200,9 +1200,9 @@ mod tests { } display_tests! { - display_var_list: Value::VarList(LogicalType::String, vec!["Alice".into(), "Bob".into()]), - display_var_list_empty: Value::VarList(LogicalType::String, vec![]), - display_fixed_list: Value::FixedList(LogicalType::String, vec!["Alice".into(), "Bob".into()]), + display_list: Value::List(LogicalType::String, vec!["Alice".into(), "Bob".into()]), + display_list_empty: Value::List(LogicalType::String, vec![]), + display_array: Value::Array(LogicalType::String, vec!["Alice".into(), "Bob".into()]), display_int8: Value::Int8(0), display_int16: Value::Int16(1), display_int32: Value::Int32(2), @@ -1218,8 +1218,8 @@ mod tests { // The C++ API escapes data in the blob as hex display_string: Value::String("Hello World".to_string()), display_bool: Value::Bool(false), - display_null: Value::Null(LogicalType::VarList { - child_type: Box::new(LogicalType::FixedList { child_type: Box::new(LogicalType::Int16), num_elements: 3 }) + display_null: Value::Null(LogicalType::List { + child_type: Box::new(LogicalType::Array { child_type: Box::new(LogicalType::Int16), num_elements: 3 }) }), display_struct: Value::Struct(vec![("NAME".to_string(), "Alice".into()), ("AGE".to_string(), 25.into())]), display_internal_id: Value::InternalID(InternalID { table_id: 0, offset: 0 }), @@ -1237,10 +1237,10 @@ mod tests { database_tests! { // Passing these values as arguments is not yet implemented in kuzu: - // db_var_list_string: Value::VarList(LogicalType::String, vec!["Alice".into(), "Bob".into()]), "STRING[]", - // db_var_list_int: Value::VarList(LogicalType::Int64, vec![0i64.into(), 1i64.into(), 2i64.into()]), "INT64[]", + // db_list_string: Value::List(LogicalType::String, vec!["Alice".into(), "Bob".into()]), "STRING[]", + // db_list_int: Value::List(LogicalType::Int64, vec![0i64.into(), 1i64.into(), 2i64.into()]), "INT64[]", // db_map: Value::Map((LogicalType::String, LogicalType::Int64), vec![(Value::String("key".to_string()), Value::Int64(24))]), "MAP(STRING,INT64)", - // db_fixed_list: Value::FixedList(LogicalType::Int64, vec![1i64.into(), 2i64.into(), 3i64.into()]), "INT64[3]", + // db_array: Value::Array(LogicalType::Int64, vec![1i64.into(), 2i64.into(), 3i64.into()]), "INT64[3]", // db_union: Value::Union { // types: vec![("Num".to_string(), LogicalType::Int8), ("duration".to_string(), LogicalType::Interval)], // value: Box::new(Value::Int8(-127)) @@ -1250,8 +1250,8 @@ mod tests { "STRUCT(item STRING, count INT32)", db_null_string: Value::Null(LogicalType::String), "STRING", db_null_int: Value::Null(LogicalType::Int64), "INT64", - db_null_list: Value::Null(LogicalType::VarList { - child_type: Box::new(LogicalType::FixedList { child_type: Box::new(LogicalType::Int16), num_elements: 3 }) + db_null_list: Value::Null(LogicalType::List { + child_type: Box::new(LogicalType::Array { child_type: Box::new(LogicalType::Int16), num_elements: 3 }) }), "INT16[3][]", db_int8: Value::Int8(0), "INT8", db_int16: Value::Int16(1), "INT16", @@ -1280,7 +1280,7 @@ mod tests { #[test] /// Tests that the list value is correctly constructed - fn test_var_list_get() -> Result<()> { + fn test_list_get() -> Result<()> { let temp_dir = tempfile::tempdir()?; let db = Database::new(temp_dir.path(), SystemConfig::default())?; let conn = Connection::new(&db)?; @@ -1288,7 +1288,7 @@ mod tests { assert_eq!(result.len(), 1); assert_eq!( result[0], - Value::VarList(LogicalType::String, vec!["Alice".into(), "Bob".into(),]) + Value::List(LogicalType::String, vec!["Alice".into(), "Bob".into(),]) ); } temp_dir.close()?; diff --git a/tools/shell/embedded_shell.cpp b/tools/shell/embedded_shell.cpp index 0f0ab431c4d..7ea9103d9a1 100644 --- a/tools/shell/embedded_shell.cpp +++ b/tools/shell/embedded_shell.cpp @@ -18,6 +18,8 @@ #include "utf8proc.h" #include "utf8proc_wrapper.h" +#include "common/task_system/progress_bar.h" + using namespace kuzu::common; using namespace kuzu::utf8proc; @@ -42,9 +44,9 @@ struct ShellCommand { const char* HELP = ":help"; const char* CLEAR = ":clear"; const char* QUIT = ":quit"; - const char* MAXROWS = ":max_rows"; - const char* MAXWIDTH = ":max_width"; - const std::array commandList = {HELP, CLEAR, QUIT, MAXROWS, MAXWIDTH}; + const char* MAX_ROWS = ":max_rows"; + const char* MAX_WIDTH = ":max_width"; + const std::array commandList = {HELP, CLEAR, QUIT, MAX_ROWS, MAX_WIDTH}; } shellCommand; const char* TAB = " "; @@ -273,10 +275,10 @@ int EmbeddedShell::processShellCommands(std::string lineStr) { linenoiseClearScreen(); } else if (lineStr == shellCommand.QUIT) { return -1; - } else if (lineStr.rfind(shellCommand.MAXROWS) == 0) { - setMaxRows(lineStr.substr(strlen(shellCommand.MAXROWS))); - } else if (lineStr.rfind(shellCommand.MAXWIDTH) == 0) { - setMaxWidth(lineStr.substr(strlen(shellCommand.MAXWIDTH))); + } else if (lineStr.rfind(shellCommand.MAX_ROWS) == 0) { + setMaxRows(lineStr.substr(strlen(shellCommand.MAX_ROWS))); + } else if (lineStr.rfind(shellCommand.MAX_WIDTH) == 0) { + setMaxWidth(lineStr.substr(strlen(shellCommand.MAX_WIDTH))); } else { printf("Error: Unknown command: \"%s\". Enter \":help\" for help\n", lineStr.c_str()); printf("Did you mean: \"%s\"?\n", findClosestCommand(lineStr).c_str()); @@ -425,15 +427,15 @@ void EmbeddedShell::printHelp() { printf("%s%s %sclear shell\n", TAB, shellCommand.CLEAR, TAB); printf("%s%s %sexit from shell\n", TAB, shellCommand.QUIT, TAB); printf("%s%s [max_rows] %sset maximum number of rows for display (default: 20)\n", TAB, - shellCommand.MAXROWS, TAB); + shellCommand.MAX_ROWS, TAB); printf("%s%s [max_width] %sset maximum width in characters for display\n", TAB, - shellCommand.MAXWIDTH, TAB); + shellCommand.MAX_WIDTH, TAB); printf("\n"); printf("%sNote: you can change and see several system configurations, such as num-threads, \n", TAB); - printf("%s%s timeout, and logging_level using Cypher CALL statements.\n", TAB, TAB); + printf("%s%s timeout, and progress_bar using Cypher CALL statements.\n", TAB, TAB); printf("%s%s e.g. CALL THREADS=5; or CALL current_setting('threads') return *;\n", TAB, TAB); - printf("%s%s See: https://kuzudb.com/docusaurus/cypher/configuration\n", TAB, TAB); + printf("%s%s See: https://docs.kuzudb.com/cypher/configuration\n", TAB, TAB); } void EmbeddedShell::printExecutionResult(QueryResult& queryResult) const { @@ -480,11 +482,16 @@ void EmbeddedShell::printExecutionResult(QueryResult& queryResult) const { uint32_t sumGoal = minTruncatedWidth; uint32_t maxWidth = minTruncatedWidth; if (colsWidth.size() == 1) { - sumGoal = colsWidth[0] + 2; + uint32_t minDisplayWidth = minTruncatedWidth + SMALL_TABLE_SEPERATOR_LENGTH; + if (maxPrintWidth > minDisplayWidth) { + sumGoal = maxPrintWidth - 2; + } else { + sumGoal = std::max( + (uint32_t)(getColumns(STDIN_FILENO, STDOUT_FILENO) - colsWidth.size() - 1), + minDisplayWidth); + } } else if (colsWidth.size() > 1) { - uint32_t minDisplayWidth = SMALL_TABLE_SEPERATOR_LENGTH; - minDisplayWidth += (colsWidth[0] < minTruncatedWidth) ? colsWidth[0] : minTruncatedWidth; - minDisplayWidth += (colsWidth.back() < minTruncatedWidth) ? colsWidth.back() : minTruncatedWidth; + uint32_t minDisplayWidth = SMALL_TABLE_SEPERATOR_LENGTH + minTruncatedWidth * 2; if (maxPrintWidth > minDisplayWidth) { sumGoal = maxPrintWidth - colsWidth.size() - 1; } else { diff --git a/tools/shell/linenoise.cpp b/tools/shell/linenoise.cpp index dcd32d6d535..a3f55c4a901 100644 --- a/tools/shell/linenoise.cpp +++ b/tools/shell/linenoise.cpp @@ -1369,6 +1369,7 @@ static void searchNext(linenoiseState* l) { bool pastedInput(int ifd) { #ifdef _WIN32 fd_set readfds; + FD_ZERO(&readfds); FD_SET(ifd, &readfds); int isPasted = select(0, &readfds, NULL, NULL, NULL); return (isPasted != 0 && isPasted != SOCKET_ERROR); @@ -2349,6 +2350,8 @@ int linenoiseHistoryLoad(const char* filename) { // add the full line to the history linenoiseHistoryAdd(buf); continue; + } else if (result.empty() && buf[0] == '\0') { + continue; } // else we are parsing a Cypher statement result += buf; diff --git a/tools/shell/test/conftest.py b/tools/shell/test/conftest.py index 0c0673fb993..b90a48e8200 100644 --- a/tools/shell/test/conftest.py +++ b/tools/shell/test/conftest.py @@ -1,18 +1,24 @@ -from encodings import utf_8 -import pytest +from __future__ import annotations + import os import shutil import subprocess + import pexpect -from test_helper import * -from typing import List, Union +import pytest +from test_helper import KUZU_EXEC_PATH, KUZU_ROOT, deleteIfExists -def pytest_addoption(parser): - parser.addoption("--start-offset", action="store", type=int, help="Skip the first 'n' tests") +def pytest_addoption(parser) -> None: + parser.addoption( + "--start-offset", + action="store", + type=int, + help="Skip the first 'n' tests", + ) -def pytest_collection_modifyitems(config, items): +def pytest_collection_modifyitems(config, items) -> None: start_offset = config.getoption("--start-offset") if not start_offset: # --skiplist not given in cli, therefore move on @@ -25,32 +31,32 @@ def pytest_collection_modifyitems(config, items): class TestResult: - def __init__(self, stdout, stderr, status_code): - self.stdout: Union[str, bytes] = stdout - self.stderr: Union[str, bytes] = stderr + def __init__(self, stdout, stderr, status_code) -> None: + self.stdout: str | bytes = stdout + self.stderr: str | bytes = stderr self.status_code: int = status_code - def check_stdout(self, expected: Union[str, List[str], bytes]): + def check_stdout(self, expected: str | list[str] | bytes) -> None: if isinstance(expected, list): - expected = '\n'.join(expected) + expected = "\n".join(expected) assert self.status_code == 0 assert expected in self.stdout - - def check_not_stdout(self, expected: Union[str, List[str], bytes]): + + def check_not_stdout(self, expected: str | list[str] | bytes) -> None: if isinstance(expected, list): - expected = '\n'.join(expected) + expected = "\n".join(expected) assert self.status_code == 0 assert expected not in self.stdout - def check_stderr(self, expected: str): + def check_stderr(self, expected: str) -> None: assert expected in self.stderr class ShellTest: - def __init__(self): + def __init__(self) -> None: self.shell = KUZU_EXEC_PATH self.arguments = [self.shell] - self.statements: List[str] = [] + self.statements: list[str] = [] self.input = None self.output = None self.environment = {} @@ -78,7 +84,7 @@ def output_file(self, file_path): # Test Running methods - def get_command(self, cmd: str) -> List[str]: + def get_command(self, cmd: str) -> list[str]: command = self.arguments if self.input: command += [cmd] @@ -86,29 +92,30 @@ def get_command(self, cmd: str) -> List[str]: def get_input_data(self, cmd: str): if self.input: - input_data = open(self.input, 'rb').read() + with open(self.input, "rb") as f: + input_data = f.read() else: - input_data = bytearray(cmd, 'utf8') + input_data = bytearray(cmd, "utf8") return input_data def get_output_pipe(self): output_pipe = subprocess.PIPE if self.output: - output_pipe = open(self.output, 'w+') + output_pipe = open(self.output, "w+") return output_pipe def get_statements(self): statements = [] for statement in self.statements: statements.append(statement) - return '\n'.join(statements) + return "\n".join(statements) def get_output_data(self, res): if self.output: - stdout = open(self.output, 'r').read() + stdout = open(self.output).read() else: - stdout = res.stdout.decode('utf8').strip() - stderr = res.stderr.decode('utf8').strip() + stdout = res.stdout.decode("utf8").strip() + stderr = res.stderr.decode("utf8").strip() return stdout, stderr def run(self): @@ -121,56 +128,62 @@ def run(self): for key, val in self.environment.items(): my_env[key] = val - res = subprocess.run(command, input=input_data, stdout=output_pipe, stderr=subprocess.PIPE, env=my_env) + res = subprocess.run( + command, + input=input_data, + stdout=output_pipe, + stderr=subprocess.PIPE, + env=my_env, + check=False, + ) stdout, stderr = self.get_output_data(res) return TestResult(stdout, stderr, res.returncode) - - def start(self): + + def start(self) -> None: command = " ".join(self.arguments) my_env = os.environ.copy() for key, val in self.environment.items(): my_env[key] = val - - self.shell_process = pexpect.spawn(command, encoding = "utf_8", env = my_env) - def send_finished_statement(self, stmt: str): + self.shell_process = pexpect.spawn(command, encoding="utf_8", env=my_env) + + def send_finished_statement(self, stmt: str) -> None: if self.shell_process: assert self.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 self.shell_process.send(stmt) assert self.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 - def send_statement(self, stmt: str): + def send_statement(self, stmt: str) -> None: if self.shell_process: assert self.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 self.shell_process.send(stmt) - def send_control_statement(self, stmt: str): + def send_control_statement(self, stmt: str) -> None: if self.shell_process: assert self.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 self.shell_process.sendcontrol(stmt) -@pytest.fixture +@pytest.fixture() def temp_db(tmp_path): shutil.rmtree(tmp_path, ignore_errors=True) - output_path = str(tmp_path) - return output_path + return str(tmp_path) -@pytest.fixture +@pytest.fixture() def get_tmp_path(tmp_path): return str(tmp_path) -@pytest.fixture +@pytest.fixture() def history_path(): - path = os.path.join(KUZU_ROOT, 'tools', 'shell', 'test', 'files') - deleteIfExists(os.path.join(path, 'history.txt')) + path = os.path.join(KUZU_ROOT, "tools", "shell", "test", "files") + deleteIfExists(os.path.join(path, "history.txt")) return path -@pytest.fixture +@pytest.fixture() def csv_path(): - return os.path.join(KUZU_ROOT, 'tools', 'shell', 'test', 'files', 'vPerson.csv') + return os.path.join(KUZU_ROOT, "tools", "shell", "test", "files", "vPerson.csv") diff --git a/tools/shell/test/test_helper.py b/tools/shell/test/test_helper.py index 45a4152ee5e..d438145b516 100644 --- a/tools/shell/test/test_helper.py +++ b/tools/shell/test/test_helper.py @@ -1,49 +1,60 @@ import os -from pathlib import Path import sys from enum import Enum +from pathlib import Path KUZU_ROOT = Path(__file__).parent.parent.parent.parent if sys.platform == "win32": # \ in paths is not supported by kuzu's parser - KUZU_ROOT=str(KUZU_ROOT).replace("\\", "/") + KUZU_ROOT = str(KUZU_ROOT).replace("\\", "/") + +KUZU_EXEC_PATH = os.path.join( + KUZU_ROOT, + "build", + "release", + "tools", + "shell", + "kuzu_shell", +) -KUZU_EXEC_PATH = os.path.join(KUZU_ROOT, 'build', 'release', 'tools', 'shell', 'kuzu_shell') def _get_kuzu_version(): - cmake_file = os.path.join(KUZU_ROOT, 'CMakeLists.txt') + cmake_file = os.path.join(KUZU_ROOT, "CMakeLists.txt") with open(cmake_file) as f: for line in f: - if line.startswith('project(Kuzu VERSION'): - return line.split(' ')[2].strip() + if line.startswith("project(Kuzu VERSION"): + return line.split(" ")[2].strip() + return None + KUZU_VERSION = _get_kuzu_version() + class KEY_ACTION(Enum): - KEY_NULL = '\0' # NULL - CTRL_A = 'a' # Ctrl-a - CTRL_B = 'b' # Ctrl-b - CTRL_C = 'c' # Ctrl-c - CTRL_D = 'd' # Ctrl-d - CTRL_E = 'e' # Ctrl-e - CTRL_F = 'f' # Ctrl-f - CTRL_G = 'g' # Ctrl-g - CTRL_H = chr(8) # Ctrl-h - TAB = '\t' # Tab - CTRL_K = 'k' # Ctrl-k - CTRL_L = 'l' # Ctrl-l - ENTER = '\r' # Enter - CTRL_N = 'n' # Ctrl-n - CTRL_P = 'p' # Ctrl-p - CTRL_R = 'r' # Ctrl-r - CTRL_S = 's' # Ctrl-s - CTRL_T = 't' # Ctrl-t - CTRL_U = 'u' # Ctrl-u - CTRL_W = chr(23) # Ctrl-w - ESC = '\27' # Escape - BACKSPACE = chr(127) # Backspace - - -def deleteIfExists(file): + KEY_NULL = "\0" # NULL + CTRL_A = "a" # Ctrl-a + CTRL_B = "b" # Ctrl-b + CTRL_C = "c" # Ctrl-c + CTRL_D = "d" # Ctrl-d + CTRL_E = "e" # Ctrl-e + CTRL_F = "f" # Ctrl-f + CTRL_G = "g" # Ctrl-g + CTRL_H = chr(8) # Ctrl-h + TAB = "\t" # Tab + CTRL_K = "k" # Ctrl-k + CTRL_L = "l" # Ctrl-l + ENTER = "\r" # Enter + CTRL_N = "n" # Ctrl-n + CTRL_P = "p" # Ctrl-p + CTRL_R = "r" # Ctrl-r + CTRL_S = "s" # Ctrl-s + CTRL_T = "t" # Ctrl-t + CTRL_U = "u" # Ctrl-u + CTRL_W = chr(23) # Ctrl-w + ESC = "\27" # Escape + BACKSPACE = chr(127) # Backspace + + +def deleteIfExists(file) -> None: if os.path.exists(file): os.remove(file) diff --git a/tools/shell/test/test_shell_basics.py b/tools/shell/test/test_shell_basics.py index bbb475babcf..cda3660d132 100644 --- a/tools/shell/test/test_shell_basics.py +++ b/tools/shell/test/test_shell_basics.py @@ -1,47 +1,37 @@ +import os + import pytest -from test_helper import * from conftest import ShellTest +from test_helper import deleteIfExists -def test_basic(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .statement('RETURN "databases rule" AS a;') - ) +def test_basic(temp_db) -> None: + test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" AS a;') result = test.run() result.check_stdout("databases rule") -def test_range(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .statement('RETURN RANGE(0, 10) AS a;') - ) +def test_range(temp_db) -> None: + test = ShellTest().add_argument(temp_db).statement("RETURN RANGE(0, 10) AS a;") result = test.run() result.check_stdout("[0,1,2,3,4,5,6,7,8,9,10]") @pytest.mark.parametrize( - ["input", "output"], + ("input", "output"), [ ("RETURN LIST_CREATION(1,2);", "[1,2]"), ("RETURN STRUCT_PACK(x:=2,y:=3);", "{x: 2, y: 3}"), ("RETURN STRUCT_PACK(x:=2,y:=LIST_CREATION(1,2));", "{x: 2, y: [1,2]}"), ], ) -def test_nested_types(temp_db, input, output): - test = ( - ShellTest() - .add_argument(temp_db) - .statement(input) - ) +def test_nested_types(temp_db, input, output) -> None: + test = ShellTest().add_argument(temp_db).statement(input) result = test.run() result.check_stdout(output) - -def test_invalid_cast(temp_db): + +def test_invalid_cast(temp_db) -> None: test = ( ShellTest() .add_argument(temp_db) @@ -50,10 +40,12 @@ def test_invalid_cast(temp_db): .statement('MATCH (t:a) RETURN CAST(t.i, "INT8");') ) result = test.run() - result.check_stdout('Error: Conversion exception: Cast failed. Could not convert "****" to INT8.') - + result.check_stdout( + 'Error: Conversion exception: Cast failed. Could not convert "****" to INT8.', + ) -def test_multiline(temp_db): + +def test_multiline(temp_db) -> None: test = ( ShellTest() .add_argument(temp_db) @@ -65,62 +57,50 @@ def test_multiline(temp_db): ) result = test.run() result.check_stdout("databases rule") - -def test_multi_queries_one_line(temp_db): + +def test_multi_queries_one_line(temp_db) -> None: # two successful queries - test = ( - ShellTest() - .add_argument(temp_db) - .statement('RETURN "databases rule" AS a; RETURN "kuzu is cool" AS b;') - ) + test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" AS a; RETURN "kuzu is cool" AS b;') result = test.run() - result.check_stdout("databases rule") + result.check_stdout("databases rule") result.check_stdout("kuzu is cool") - + # one success one failure - test = ( - ShellTest() - .add_argument(temp_db) - .statement('RETURN "databases rule" AS a; ;') - ) + test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" AS a; ;') result = test.run() result.check_stdout("databases rule") - result.check_stdout(["Error: Parser exception: mismatched input '' expecting {CALL, COMMENT, COPY, EXPORT, DROP, ALTER, BEGIN, COMMIT, COMMIT_SKIP_CHECKPOINT, ROLLBACK, ROLLBACK_SKIP_CHECKPOINT, INSTALL, LOAD, OPTIONAL, MATCH, UNWIND, CREATE, MERGE, SET, DETACH, DELETE, WITH, RETURN} (line: 1, offset: 6)", - '" "']) - - # two failing queries - test = ( - ShellTest() - .add_argument(temp_db) - .statement('RETURN "databases rule" S a; ;') + result.check_stdout( + [ + "Error: Parser exception: mismatched input '' expecting {ATTACH, CALL, COMMENT_, COPY, EXPORT, IMPORT, DROP, ALTER, BEGIN, COMMIT, COMMIT_SKIP_CHECKPOINT, ROLLBACK, ROLLBACK_SKIP_CHECKPOINT, INSTALL, LOAD, OPTIONAL, MATCH, UNWIND, CREATE, MERGE, SET, DETACH, DELETE, WITH, RETURN} (line: 1, offset: 6)", + '" "', + ], ) + + # two failing queries + test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" S a; ;') result = test.run() - result.check_stdout(["Error: Parser exception: Invalid input < S>: expected rule ku_Statements (line: 1, offset: 24)", - '"RETURN "databases rule" S a"', - " ^", - "Error: Parser exception: mismatched input '' expecting {CALL, COMMENT, COPY, EXPORT, DROP, ALTER, BEGIN, COMMIT, COMMIT_SKIP_CHECKPOINT, ROLLBACK, ROLLBACK_SKIP_CHECKPOINT, INSTALL, LOAD, OPTIONAL, MATCH, UNWIND, CREATE, MERGE, SET, DETACH, DELETE, WITH, RETURN} (line: 1, offset: 6)", - '" "']) + result.check_stdout( + [ + "Error: Parser exception: Invalid input < S>: expected rule ku_Statements (line: 1, offset: 24)", + '"RETURN "databases rule" S a"', + " ^", + "Error: Parser exception: mismatched input '' expecting {ATTACH, CALL, COMMENT_, COPY, EXPORT, IMPORT, DROP, ALTER, BEGIN, COMMIT, COMMIT_SKIP_CHECKPOINT, ROLLBACK, ROLLBACK_SKIP_CHECKPOINT, INSTALL, LOAD, OPTIONAL, MATCH, UNWIND, CREATE, MERGE, SET, DETACH, DELETE, WITH, RETURN} (line: 1, offset: 6)", + '" "', + ], + ) -def test_row_truncation(temp_db, csv_path): - test = ( - ShellTest() - .add_argument(temp_db) - .statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN id;') - ) +def test_row_truncation(temp_db, csv_path) -> None: + test = ShellTest().add_argument(temp_db).statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN id;') result = test.run() result.check_stdout("(21 tuples, 20 shown)") result.check_stdout(["| . |", "| . |", "| . |"]) - -def test_column_truncation(temp_db, csv_path): + +def test_column_truncation(temp_db, csv_path) -> None: # width when running test is 80 - test = ( - ShellTest() - .add_argument(temp_db) - .statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN *;') - ) + test = ShellTest().add_argument(temp_db).statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN *;') result = test.run() result.check_stdout("-" * 80) result.check_not_stdout("-" * 81) @@ -128,18 +108,14 @@ def test_column_truncation(temp_db, csv_path): result.check_stdout("(13 columns, 4 shown)") -def long_messages(temp_db): - long_message = '-' * 4096 - test = ( - ShellTest() - .add_argument(temp_db) - .statement(f'RETURN "{long_message}" AS a;') - ) +def long_messages(temp_db) -> None: + long_message = "-" * 4096 + test = ShellTest().add_argument(temp_db).statement(f'RETURN "{long_message}" AS a;') result = test.run() result.check_stdout(long_message) -def test_history_consecutive_repeats(temp_db, history_path): +def test_history_consecutive_repeats(temp_db, history_path) -> None: test = ( ShellTest() .add_argument(temp_db) @@ -150,11 +126,9 @@ def test_history_consecutive_repeats(temp_db, history_path): ) result = test.run() result.check_stdout("| databases rule |") - - f = open(os.path.join(history_path, "history.txt")) - assert f.readline() == 'RETURN "databases rule" AS a;\n' - assert f.readline() == '' - f.close() - - deleteIfExists(os.path.join(history_path, 'history.txt')) - \ No newline at end of file + + with open(os.path.join(history_path, "history.txt")) as f: + assert f.readline() == 'RETURN "databases rule" AS a;\n' + assert f.readline() == "" + + deleteIfExists(os.path.join(history_path, "history.txt")) diff --git a/tools/shell/test/test_shell_commands.py b/tools/shell/test/test_shell_commands.py index 84f75cd992a..b66948faf28 100644 --- a/tools/shell/test/test_shell_commands.py +++ b/tools/shell/test/test_shell_commands.py @@ -1,49 +1,39 @@ -from test_helper import * from conftest import ShellTest -def test_help(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .statement(":help") - ) +def test_help(temp_db) -> None: + test = ShellTest().add_argument(temp_db).statement(":help") result = test.run() - result.check_stdout([" :help get command list", - " :clear clear shell", - " :quit exit from shell", - " :max_rows [max_rows] set maximum number of rows for display (default: 20)", - " :max_width [max_width] set maximum width in characters for display", - "", - " Note: you can change and see several system configurations, such as num-threads, ", - " timeout, and logging_level using Cypher CALL statements.", - " e.g. CALL THREADS=5; or CALL current_setting('threads') return *;", - " See: https://kuzudb.com/docusaurus/cypher/configuration"]) - - -def test_clear(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .statement(":clear") + result.check_stdout( + [ + " :help get command list", + " :clear clear shell", + " :quit exit from shell", + " :max_rows [max_rows] set maximum number of rows for display (default: 20)", + " :max_width [max_width] set maximum width in characters for display", + "", + " Note: you can change and see several system configurations, such as num-threads, ", + " timeout, and progress_bar using Cypher CALL statements.", + " e.g. CALL THREADS=5; or CALL current_setting('threads') return *;", + " See: https://docs.kuzudb.com/cypher/configuration", + ], ) + + +def test_clear(temp_db) -> None: + test = ShellTest().add_argument(temp_db).statement(":clear") result = test.run() result.check_stdout("\x1b[H\x1b[2J") - -def test_quit(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .statement(":quit") - .statement('RETURN RANGE(0,10) AS a;') - ) + +def test_quit(temp_db) -> None: + test = ShellTest().add_argument(temp_db).statement(":quit").statement("RETURN RANGE(0,10) AS a;") result = test.run() # check to make sure the return query did not execute result.check_not_stdout("[0,1,2,3,4,5,6,7,8,9,10]") - -def test_max_rows(temp_db, csv_path): + +def test_max_rows(temp_db, csv_path) -> None: # test all rows shown test = ( ShellTest() @@ -54,8 +44,8 @@ def test_max_rows(temp_db, csv_path): result = test.run() result.check_stdout("(21 tuples)") result.check_not_stdout(["| . |", "| . |", "| . |"]) - - # test 1 row shown + + # test 1 row shown test = ( ShellTest() .add_argument(temp_db) @@ -65,7 +55,7 @@ def test_max_rows(temp_db, csv_path): result = test.run() result.check_stdout("(21 tuples, 1 shown)") result.check_stdout(["| . |", "| . |", "| . |"]) - + # test setting back to default test = ( ShellTest() @@ -78,7 +68,7 @@ def test_max_rows(temp_db, csv_path): result.check_stdout(["| . |", "| . |", "| . |"]) -def test_max_width(temp_db, csv_path): +def test_max_width(temp_db, csv_path) -> None: # test all columns shown test = ( ShellTest() @@ -91,21 +81,21 @@ def test_max_width(temp_db, csv_path): result.check_not_stdout("-" * 267) result.check_not_stdout("| ... |") result.check_stdout("(13 columns)") - + # test 2 columns shown test = ( ShellTest() .add_argument(temp_db) - .statement(":max_width 40") + .statement(":max_width 44") .statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN *;') ) result = test.run() - # while max width is 40, the columns that fit have a total width of 34 + # while max width is 44, the columns that fit have a total width of 34 result.check_stdout("-" * 34) result.check_not_stdout("-" * 35) result.check_stdout("| ... |") result.check_stdout("(13 columns, 2 shown)") - + # test too small to display (back to terminal width) test = ( ShellTest() @@ -119,32 +109,32 @@ def test_max_width(temp_db, csv_path): result.check_not_stdout("-" * 81) result.check_stdout("| ... |") result.check_stdout("(13 columns, 4 shown)") - + # test result tuples unaffected by width test = ( ShellTest() .add_argument(temp_db) .statement(":max_width 2") - .statement('CREATE NODE TABLE LANGUAGE_CODE(alpha2 STRING, English STRING, PRIMARY KEY (alpha2));') + .statement( + "CREATE NODE TABLE LANGUAGE_CODE(alpha2 STRING, English STRING, PRIMARY KEY (alpha2));", + ) ) result = test.run() # terminal width when running test is 80 - result.check_stdout("Node table: LANGUAGE_CODE has been created.") + result.check_stdout("Table LANGUAGE_CODE has been created.") result.check_not_stdout("| ... |") result.check_stdout("(1 column)") - - - def test_bad_command(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .statement(":maxrows") - .statement(":quiy") - .statement("clearr;") - ) - result = test.run() - result.check_stdout('Error: Unknown command: ":maxrows". Enter ":help" for help') - result.check_stdout('Did you mean: ":max_rows"?') - result.check_stdout('Error: Unknown command: ":quiy". Enter ":help" for help') - result.check_stdout('Did you mean: ":quit"?') - result.check_stdout('Error: "clearr;" is not a valid Cypher query. Did you mean to issue a CLI command, e.g., ":clear"?') + + +def test_bad_command(temp_db) -> None: + test = ShellTest().add_argument(temp_db).statement(":maxrows").statement(":quiy").statement("clearr;") + result = test.run() + result.check_stdout( + 'Error: Unknown command: ":maxrows". Enter ":help" for help', + ) + result.check_stdout('Did you mean: ":max_rows"?') + result.check_stdout('Error: Unknown command: ":quiy". Enter ":help" for help') + result.check_stdout('Did you mean: ":quit"?') + result.check_stdout( + 'Error: "clearr;" is not a valid Cypher query. Did you mean to issue a CLI command, e.g., ":clear"?', + ) diff --git a/tools/shell/test/test_shell_control_edit.py b/tools/shell/test/test_shell_control_edit.py index bb00abb613d..02f4eb4b1ed 100644 --- a/tools/shell/test/test_shell_control_edit.py +++ b/tools/shell/test/test_shell_control_edit.py @@ -1,24 +1,26 @@ -import pytest +import os + import pexpect -from test_helper import * +import pytest from conftest import ShellTest +from test_helper import KEY_ACTION, deleteIfExists @pytest.mark.parametrize( "key", [ - (KEY_ACTION.CTRL_C.value), - (KEY_ACTION.CTRL_G.value), + KEY_ACTION.CTRL_C.value, + KEY_ACTION.CTRL_G.value, ], ) -def test_sigint(temp_db, key): +def test_sigint(temp_db, key) -> None: # test two consecutive signit required to exit shell test = ShellTest().add_argument(temp_db) test.start() test.send_control_statement(key) test.send_control_statement(key) assert test.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 1 - + # test sending line interupts the two signits to quit test = ShellTest().add_argument(temp_db) test.start() @@ -28,49 +30,49 @@ def test_sigint(temp_db, key): test.send_control_statement(key) test.send_control_statement(key) assert test.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 1 - + # test sigint cancels the query test = ShellTest().add_argument(temp_db) test.start() - test.send_statement('CREATE NODE TABLE t0(i STRING, PRIMARY KEY(i));') + test.send_statement("CREATE NODE TABLE t0(i STRING, PRIMARY KEY(i));") test.send_control_statement(key) test.send_finished_statement("MATCH (a:t0) RETURN *;\r") - assert test.shell_process.expect_exact(["Error: Binder exception: Table t0 does not exist.", pexpect.EOF]) == 0 - + assert ( + test.shell_process.expect_exact( + ["Error: Binder exception: Table t0 does not exist.", pexpect.EOF], + ) + == 0 + ) + @pytest.mark.parametrize( "key", [ - (KEY_ACTION.ENTER.value), - ('\n'), + KEY_ACTION.ENTER.value, + "\n", ], ) -def test_enter(temp_db, key, history_path): - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("-p") - .add_argument(history_path) - ) +def test_enter(temp_db, key, history_path) -> None: + test = ShellTest().add_argument(temp_db).add_argument("-p").add_argument(history_path) test.start() test.send_statement('RETURN "databases rule" AS a;') test.send_finished_statement(key) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 assert test.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 - f = open(os.path.join(history_path, "history.txt")) - assert f.readline() == 'RETURN "databases rule" AS a;\n' - f.close() - deleteIfExists(os.path.join(history_path, 'history.txt')) - + + with open(os.path.join(history_path, "history.txt")) as f: + assert f.readline() == 'RETURN "databases rule" AS a;\n' + deleteIfExists(os.path.join(history_path, "history.txt")) + @pytest.mark.parametrize( "key", [ - (KEY_ACTION.BACKSPACE.value), - (KEY_ACTION.CTRL_H.value), + KEY_ACTION.BACKSPACE.value, + KEY_ACTION.CTRL_H.value, ], ) -def test_backspace(temp_db, key): +def test_backspace(temp_db, key) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a;abc') @@ -79,7 +81,7 @@ def test_backspace(temp_db, key): assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_d(temp_db): +def test_ctrl_d(temp_db) -> None: # ctrl d acts as EOF when line is empty test = ShellTest().add_argument(temp_db) test.start() @@ -90,46 +92,46 @@ def test_ctrl_d(temp_db): test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a;abc') - test.send_statement("\x1b[D" * 3) # move cursor to the left + test.send_statement("\x1b[D" * 3) # move cursor to the left for _ in range(4): test.send_control_statement(KEY_ACTION.CTRL_D.value) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_ctrl_t(temp_db): + +def test_ctrl_t(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS ;a') - test.send_statement("\x1b[D") # move cursor to the left + test.send_statement("\x1b[D") # move cursor to the left test.send_control_statement(KEY_ACTION.CTRL_T.value) - test.shell_process.sendcontrol(KEY_ACTION.CTRL_T.value) # line does not refresh + test.shell_process.sendcontrol(KEY_ACTION.CTRL_T.value) # line does not refresh test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_ctrl_b(temp_db): + +def test_ctrl_b(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() - test.send_statement(';') + test.send_statement(";") test.send_control_statement(KEY_ACTION.CTRL_B.value) - test.shell_process.sendcontrol(KEY_ACTION.CTRL_B.value) # line does not refresh + test.shell_process.sendcontrol(KEY_ACTION.CTRL_B.value) # line does not refresh test.send_finished_statement('RETURN "databases rule" AS a\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_ctrl_f(temp_db): + +def test_ctrl_f(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a') - test.send_statement("\x1b[D") # move cursor to the left + test.send_statement("\x1b[D") # move cursor to the left test.send_control_statement(KEY_ACTION.CTRL_F.value) - test.shell_process.sendcontrol(KEY_ACTION.CTRL_F.value) # line does not refresh - test.send_finished_statement(';\r') + test.shell_process.sendcontrol(KEY_ACTION.CTRL_F.value) # line does not refresh + test.send_finished_statement(";\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - - -def test_ctrl_p(temp_db): + + +def test_ctrl_p(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases rule" AS a;\r') @@ -137,36 +139,36 @@ def test_ctrl_p(temp_db): test.send_control_statement(KEY_ACTION.CTRL_P.value) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_ctrl_n(temp_db): + +def test_ctrl_n(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "kuzu is cool" AS b;\r') assert test.shell_process.expect_exact(["| kuzu is cool |", pexpect.EOF]) == 0 test.send_finished_statement('RETURN "databases rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - test.send_statement("\x1b[A" * 2) # move up in history + test.send_statement("\x1b[A" * 2) # move up in history test.send_control_statement(KEY_ACTION.CTRL_N.value) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + @pytest.mark.parametrize( "key", [ - (KEY_ACTION.CTRL_R.value), - (KEY_ACTION.CTRL_S.value), + KEY_ACTION.CTRL_R.value, + KEY_ACTION.CTRL_S.value, ], ) -def test_search(temp_db, key, history_path): +def test_search(temp_db, key, history_path) -> None: # test search opens test = ShellTest().add_argument(temp_db) test.start() test.send_control_statement(key) assert test.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 assert test.shell_process.expect_exact(["bck-i-search: _", pexpect.EOF]) == 0 - + # test successful search test = ShellTest().add_argument(temp_db) test.start() @@ -175,30 +177,25 @@ def test_search(temp_db, key, history_path): test.send_finished_statement('RETURN "kuzu is cool" AS b;\r') assert test.shell_process.expect_exact(["| kuzu is cool |", pexpect.EOF]) == 0 test.send_control_statement(key) - test.send_statement('databases') + test.send_statement("databases") test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 # test failing search - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("-p") - .add_argument(history_path) - ) + test = ShellTest().add_argument(temp_db).add_argument("-p").add_argument(history_path) test.start() test.send_finished_statement('RETURN "databases rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 test.send_finished_statement('RETURN "kuzu is cool" AS b;\r') assert test.shell_process.expect_exact(["| kuzu is cool |", pexpect.EOF]) == 0 test.send_control_statement(key) - test.send_statement('databases*******************') + test.send_statement("databases*******************") assert test.shell_process.expect_exact(["failing-bck-i-search:", pexpect.EOF]) == 0 # enter should process last match test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - deleteIfExists(os.path.join(history_path, 'history.txt')) - + deleteIfExists(os.path.join(history_path, "history.txt")) + # test starting search with text inputted already test = ShellTest().add_argument(temp_db) test.start() @@ -208,92 +205,102 @@ def test_search(temp_db, key, history_path): assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_u(temp_db): +def test_ctrl_u(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() - test.send_statement('CREATE NODE TABLE t0(i STRING, PRIMARY KEY(i));') + test.send_statement("CREATE NODE TABLE t0(i STRING, PRIMARY KEY(i));") test.send_control_statement(KEY_ACTION.CTRL_U.value) test.send_finished_statement(KEY_ACTION.ENTER.value) test.send_finished_statement("MATCH (a:t0) RETURN *;\r") - assert test.shell_process.expect_exact(["Error: Binder exception: Table t0 does not exist.", pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + ["Error: Binder exception: Table t0 does not exist.", pexpect.EOF], + ) + == 0 + ) -def test_ctrl_k(temp_db): +def test_ctrl_k(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a;abc') - test.send_statement("\x1b[D" * 3) # move cursor to the left + test.send_statement("\x1b[D" * 3) # move cursor to the left test.send_control_statement(KEY_ACTION.CTRL_K.value) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_a(temp_db): +def test_ctrl_a(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('ETURN "databases rule" AS a;') test.send_control_statement(KEY_ACTION.CTRL_A.value) - test.send_finished_statement('R\r') + test.send_finished_statement("R\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_e(temp_db): +def test_ctrl_e(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a') - test.send_statement("\x1b[H") # move cursor to the front + test.send_statement("\x1b[H") # move cursor to the front test.send_control_statement(KEY_ACTION.CTRL_E.value) - test.send_finished_statement(';\r') + test.send_finished_statement(";\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_l(temp_db): +def test_ctrl_l(temp_db) -> None: # clear screen with empty line test = ShellTest().add_argument(temp_db) test.start() test.send_control_statement(KEY_ACTION.CTRL_L.value) assert test.shell_process.expect_exact(["\x1b[H\x1b[2J", pexpect.EOF]) == 0 - + # clear screen with non empty line test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a') test.send_control_statement(KEY_ACTION.CTRL_L.value) assert test.shell_process.expect_exact(["\x1b[H\x1b[2J", pexpect.EOF]) == 0 - test.send_finished_statement(';\r') + test.send_finished_statement(";\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_w(temp_db): +def test_ctrl_w(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a; abc def ghi ') test.send_statement(KEY_ACTION.CTRL_W.value * 3) - test.send_statement("\x1b[H") # move cursor to the front + test.send_statement("\x1b[H") # move cursor to the front test.send_statement(KEY_ACTION.CTRL_W.value) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_tab(temp_db): +def test_tab(temp_db) -> None: # tab is interpreted as four psaces when pasting input test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases\trule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + # tab completion test = ShellTest().add_argument(temp_db) test.start() - test.send_statement('CRE') + test.send_statement("CRE") test.send_statement(KEY_ACTION.TAB.value) - test.send_statement(' N') + test.send_statement(" N") test.send_statement(KEY_ACTION.TAB.value) test.send_statement(KEY_ACTION.TAB.value) - test.send_statement(' TAB') + test.send_statement(" TAB") test.send_statement(KEY_ACTION.TAB.value) test.send_statement(KEY_ACTION.TAB.value) - test.send_statement('LE t0(i STRING, PRIMARY KEY(i));') + test.send_statement("LE t0(i STRING, PRIMARY KEY(i));") test.send_statement(KEY_ACTION.TAB.value) test.send_finished_statement(KEY_ACTION.ENTER.value) - assert test.shell_process.expect_exact(["| Node table: t0 has been created. |", pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + ["| Table t0 has been created. |", pexpect.EOF], + ) + == 0 + ) diff --git a/tools/shell/test/test_shell_control_search.py b/tools/shell/test/test_shell_control_search.py index c862d013a93..7958441dccc 100644 --- a/tools/shell/test/test_shell_control_search.py +++ b/tools/shell/test/test_shell_control_search.py @@ -1,10 +1,12 @@ -import pytest +import os + import pexpect -from test_helper import * +import pytest from conftest import ShellTest +from test_helper import KEY_ACTION, deleteIfExists -def set_up_search(test): +def set_up_search(test) -> None: test.send_finished_statement('RETURN "databases rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 test.send_finished_statement('RETURN "kuzu is cool" AS b;\r') @@ -17,27 +19,27 @@ def set_up_search(test): @pytest.mark.parametrize( "key", [ - (KEY_ACTION.ENTER.value), - ('\n'), + KEY_ACTION.ENTER.value, + "\n", ], ) -def test_enter(temp_db, key): +def test_enter(temp_db, key) -> None: test = ShellTest().add_argument(temp_db) test.start() set_up_search(test) test.send_statement("databases") test.send_finished_statement(key) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + @pytest.mark.parametrize( "key", [ - (KEY_ACTION.CTRL_R.value), - (KEY_ACTION.CTRL_N.value), + KEY_ACTION.CTRL_R.value, + KEY_ACTION.CTRL_N.value, ], ) -def test_search_next(temp_db, key, history_path): +def test_search_next(temp_db, key, history_path) -> None: # test search next once test = ShellTest().add_argument(temp_db) test.start() @@ -45,31 +47,26 @@ def test_search_next(temp_db, key, history_path): test.send_control_statement(key) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| the shell is fun |", pexpect.EOF]) == 0 - + # test search next until top of history - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("-p") - .add_argument(history_path) - ) + test = ShellTest().add_argument(temp_db).add_argument("-p").add_argument(history_path) test.start() set_up_search(test) for _ in range(4): test.send_control_statement(key) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - deleteIfExists(os.path.join(history_path, 'history.txt')) + deleteIfExists(os.path.join(history_path, "history.txt")) @pytest.mark.parametrize( "key", [ - (KEY_ACTION.CTRL_S.value), - (KEY_ACTION.CTRL_P.value), + KEY_ACTION.CTRL_S.value, + KEY_ACTION.CTRL_P.value, ], ) -def test_search_prev(temp_db, key): +def test_search_prev(temp_db, key) -> None: # test search prev once test = ShellTest().add_argument(temp_db) test.start() @@ -79,7 +76,7 @@ def test_search_prev(temp_db, key): test.send_control_statement(key) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| the shell is fun |", pexpect.EOF]) == 0 - + # test search prev until bottom of history test = ShellTest().add_argument(temp_db) test.start() @@ -96,13 +93,21 @@ def test_search_prev(temp_db, key): test.send_control_statement(key) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| searching history |", pexpect.EOF]) == 0 - -def test_ctrl_a(temp_db): + +def test_ctrl_a(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('"databases rule" AS a;\r') - assert test.shell_process.expect_exact(['Error: Parser exception: extraneous input \'"databases rule"\'', pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + [ + "Error: Parser exception: extraneous input '\"databases rule\"'", + pexpect.EOF, + ], + ) + == 0 + ) test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databases") test.send_control_statement(KEY_ACTION.CTRL_A.value) @@ -111,7 +116,7 @@ def test_ctrl_a(temp_db): assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_tab(temp_db): +def test_tab(temp_db) -> None: # test tab becomes space when part of pasted input test = ShellTest().add_argument(temp_db) test.start() @@ -119,34 +124,44 @@ def test_tab(temp_db): test.send_statement("databases\trule") test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + # test tab complete search and go to end of line test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases ;\r') - assert test.shell_process.expect_exact(['Error: Parser exception: Invalid input :', pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + ['Error: Parser exception: Invalid input :', pexpect.EOF], + ) + == 0 + ) test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databases") test.send_statement(KEY_ACTION.TAB.value) - test.send_statement(KEY_ACTION.BACKSPACE.value) # remove semicolon + test.send_statement(KEY_ACTION.BACKSPACE.value) # remove semicolon test.send_finished_statement('rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_ctrl_e(temp_db): + +def test_ctrl_e(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases ;\r') - assert test.shell_process.expect_exact(['Error: Parser exception: Invalid input :', pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + ['Error: Parser exception: Invalid input :', pexpect.EOF], + ) + == 0 + ) test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databases") test.send_control_statement(KEY_ACTION.CTRL_E.value) - test.send_statement(KEY_ACTION.BACKSPACE.value) # remove semicolon + test.send_statement(KEY_ACTION.BACKSPACE.value) # remove semicolon test.send_finished_statement('rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_ctrl_b(temp_db): + +def test_ctrl_b(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databasesrule" AS a;\r') @@ -154,11 +169,11 @@ def test_ctrl_b(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databasesr") test.send_control_statement(KEY_ACTION.CTRL_B.value) - test.send_finished_statement(' \r') + test.send_finished_statement(" \r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_f(temp_db): +def test_ctrl_f(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databasesrule" AS a;\r') @@ -166,11 +181,11 @@ def test_ctrl_f(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("database") test.send_control_statement(KEY_ACTION.CTRL_F.value) - test.send_finished_statement(' \r') + test.send_finished_statement(" \r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_t(temp_db): +def test_ctrl_t(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "database srule" AS a;\r') @@ -178,11 +193,11 @@ def test_ctrl_t(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("database ") test.send_control_statement(KEY_ACTION.CTRL_T.value) - test.send_finished_statement('\r') + test.send_finished_statement("\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_u(temp_db): +def test_ctrl_u(temp_db) -> None: # check if line was cleared test = ShellTest().add_argument(temp_db) test.start() @@ -193,7 +208,7 @@ def test_ctrl_u(temp_db): test.send_control_statement(KEY_ACTION.CTRL_U.value) test.send_finished_statement('RETURN "kuzu is cool" AS a;\r') assert test.shell_process.expect_exact(["| kuzu is cool |", pexpect.EOF]) == 0 - + # check if position in history was maintained test = ShellTest().add_argument(temp_db) test.start() @@ -201,11 +216,11 @@ def test_ctrl_u(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("is cool") test.send_control_statement(KEY_ACTION.CTRL_U.value) - test.send_finished_statement("\x1b[A\r") # move up in history + test.send_finished_statement("\x1b[A\r") # move up in history assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_k(temp_db): +def test_ctrl_k(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases rule" AS aabc;\r') @@ -213,21 +228,21 @@ def test_ctrl_k(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("As a") test.send_control_statement(KEY_ACTION.CTRL_K.value) - test.send_finished_statement(';\r') + test.send_finished_statement(";\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_d(temp_db): +def test_ctrl_d(temp_db) -> None: # ctrl d accepts search and acts as EOF when line is empty test = ShellTest().add_argument(temp_db) test.start() test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_control_statement(KEY_ACTION.CTRL_D.value) - #search gets accepted + # search gets accepted assert test.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 0 # acts as EOF assert test.shell_process.expect_exact(["kuzu", pexpect.EOF]) == 1 - + # test accepts search and delete test = ShellTest().add_argument(temp_db) test.start() @@ -240,8 +255,8 @@ def test_ctrl_d(temp_db): assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_ctrl_l(temp_db): - #clear screen with empty line +def test_ctrl_l(temp_db) -> None: + # clear screen with empty line test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases rule" AS a;\r') @@ -252,7 +267,7 @@ def test_ctrl_l(temp_db): test.send_statement("databases") test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + # clear screen with non empty line test = ShellTest().add_argument(temp_db) test.start() @@ -262,16 +277,16 @@ def test_ctrl_l(temp_db): assert test.shell_process.expect_exact(["\x1b[H\x1b[2J", pexpect.EOF]) == 0 test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + @pytest.mark.parametrize( "key", [ - (KEY_ACTION.CTRL_C.value), - (KEY_ACTION.CTRL_G.value), - ] + KEY_ACTION.CTRL_C.value, + KEY_ACTION.CTRL_G.value, + ], ) -def test_cancel_search(temp_db, key): +def test_cancel_search(temp_db, key) -> None: # check if line is cleared test = ShellTest().add_argument(temp_db) test.start() @@ -282,7 +297,7 @@ def test_cancel_search(temp_db, key): test.send_control_statement(key) test.send_finished_statement('RETURN "kuzu is cool" AS a;\r') assert test.shell_process.expect_exact(["| kuzu is cool |", pexpect.EOF]) == 0 - + # check if position in history was maintained test = ShellTest().add_argument(temp_db) test.start() @@ -290,7 +305,7 @@ def test_cancel_search(temp_db, key): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("is cool") test.send_control_statement(KEY_ACTION.CTRL_U.value) - test.send_statement("\x1b[B") # move down in history + test.send_statement("\x1b[B") # move down in history test.send_finished_statement('RETURN "databases rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 @@ -298,12 +313,12 @@ def test_cancel_search(temp_db, key): @pytest.mark.parametrize( "key", [ - (KEY_ACTION.CTRL_H.value), - (KEY_ACTION.BACKSPACE.value), - (KEY_ACTION.CTRL_W.value) - ] + KEY_ACTION.CTRL_H.value, + KEY_ACTION.BACKSPACE.value, + KEY_ACTION.CTRL_W.value, + ], ) -def test_backspace(temp_db, key): +def test_backspace(temp_db, key) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases rule" AS a;\r') diff --git a/tools/shell/test/test_shell_esc_edit.py b/tools/shell/test/test_shell_esc_edit.py index eae29fa23f9..6f6924e5a62 100644 --- a/tools/shell/test/test_shell_esc_edit.py +++ b/tools/shell/test/test_shell_esc_edit.py @@ -1,37 +1,37 @@ -import pytest import pexpect -from test_helper import * +import pytest from conftest import ShellTest +from test_helper import KEY_ACTION @pytest.mark.parametrize( "esc", [ - ("\x1bb"), - ("\x1b[1;5D"), + "\x1bb", + "\x1b[1;5D", ], ) -def test_move_word_left(temp_db, esc): +def test_move_word_left(temp_db, esc) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement("RETURN AS a;") test.send_statement(esc * 3) test.send_finished_statement(' "databases rule"\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + @pytest.mark.parametrize( "esc", [ - ("\x1bf"), - ("\x1b[1;5C"), + "\x1bf", + "\x1b[1;5C", ], ) -def test_move_word_right(temp_db, esc): +def test_move_word_right(temp_db, esc) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases a;') - test.send_control_statement(KEY_ACTION.CTRL_A.value) # move cursor to front of line + test.send_control_statement(KEY_ACTION.CTRL_A.value) # move cursor to front of line test.send_statement(esc * 3) test.send_finished_statement(' rule" AS\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 @@ -40,21 +40,21 @@ def test_move_word_right(temp_db, esc): @pytest.mark.parametrize( "esc", [ - ("\x1b[H"), - ("\x1b[1~"), - ("\x1bOH"), - ] + "\x1b[H", + "\x1b[1~", + "\x1bOH", + ], ) -def test_move_home(temp_db, esc): +def test_move_home(temp_db, esc) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('ETURN "databases rule" AS a;') test.send_statement(esc) - test.send_finished_statement('R\r') + test.send_finished_statement("R\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_delete(temp_db): + +def test_delete(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a;abc') @@ -63,27 +63,27 @@ def test_delete(temp_db): test.send_statement("\x1b[3~" * 4) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + @pytest.mark.parametrize( "esc", [ - ("\x1b[F"), - ("\x1b[4~"), - ("\x1bOF"), - ] + "\x1b[F", + "\x1b[4~", + "\x1bOF", + ], ) -def test_move_end(temp_db, esc): +def test_move_end(temp_db, esc) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a') - test.send_control_statement(KEY_ACTION.CTRL_A.value) # move cursor to front of line + test.send_control_statement(KEY_ACTION.CTRL_A.value) # move cursor to front of line test.send_statement(esc) - test.send_finished_statement(';\r') + test.send_finished_statement(";\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_next_history(temp_db): +def test_next_history(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases rule" AS a;\r') @@ -91,37 +91,37 @@ def test_next_history(temp_db): test.send_statement("\x1b[A") test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_prev_history(temp_db): + +def test_prev_history(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "kuzu is cool" AS b;\r') assert test.shell_process.expect_exact(["| kuzu is cool |", pexpect.EOF]) == 0 test.send_finished_statement('RETURN "databases rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - test.send_control_statement(KEY_ACTION.CTRL_P.value) # move up in history - test.send_control_statement(KEY_ACTION.CTRL_P.value) # move up in history + test.send_control_statement(KEY_ACTION.CTRL_P.value) # move up in history + test.send_control_statement(KEY_ACTION.CTRL_P.value) # move up in history test.send_statement("\x1b[B") test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_move_left(temp_db): + +def test_move_left(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() - test.send_statement(' a;') + test.send_statement(" a;") test.send_statement("\x1b[D" * 4) test.send_finished_statement('RETURN "databases rule" AS\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_move_right(temp_db): + +def test_move_right(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_statement('RETURN "databases rule" AS a') for _ in range(3): - test.send_control_statement(KEY_ACTION.CTRL_B.value) # move cursor to the left - test.send_statement("\x1b[C" * 4) - test.send_finished_statement(';\r') + test.send_control_statement(KEY_ACTION.CTRL_B.value) # move cursor to the left + test.send_statement("\x1b[C" * 4) + test.send_finished_statement(";\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 diff --git a/tools/shell/test/test_shell_esc_search.py b/tools/shell/test/test_shell_esc_search.py index c1d5412857a..f64da1be108 100644 --- a/tools/shell/test/test_shell_esc_search.py +++ b/tools/shell/test/test_shell_esc_search.py @@ -1,10 +1,10 @@ -import pytest import pexpect -from test_helper import * +import pytest from conftest import ShellTest +from test_helper import KEY_ACTION -def set_up_search(test): +def set_up_search(test) -> None: test.send_finished_statement('RETURN "databases rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 test.send_finished_statement('RETURN "kuzu is cool" AS b;\r') @@ -12,9 +12,9 @@ def set_up_search(test): test.send_finished_statement('RETURN "the shell is fun" AS c;\r') assert test.shell_process.expect_exact(["| the shell is fun |", pexpect.EOF]) == 0 test.send_control_statement(KEY_ACTION.CTRL_R.value) - -def test_accept_search(temp_db): + +def test_accept_search(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases" AS a;\r') @@ -24,21 +24,29 @@ def test_accept_search(temp_db): test.send_statement("\x1b\x1b") test.send_finished_statement(" rule\r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - + @pytest.mark.parametrize( "esc", [ - ("\x1b[H"), - ("\x1b[1~"), - ("\x1bOH"), - ] + "\x1b[H", + "\x1b[1~", + "\x1bOH", + ], ) -def test_accept_move_home(temp_db, esc): +def test_accept_move_home(temp_db, esc) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('"databases rule" AS a;\r') - assert test.shell_process.expect_exact(['Error: Parser exception: extraneous input \'"databases rule"\'', pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + [ + "Error: Parser exception: extraneous input '\"databases rule\"'", + pexpect.EOF, + ], + ) + == 0 + ) test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databases") test.send_statement(esc) @@ -50,26 +58,31 @@ def test_accept_move_home(temp_db, esc): @pytest.mark.parametrize( "esc", [ - ("\x1b[4~"), - ("\x1b[8~"), - ("\x1b[F"), - ("\x1bOF"), - ] + "\x1b[4~", + "\x1b[8~", + "\x1b[F", + "\x1bOF", + ], ) -def test_accept_move_end(temp_db, esc): +def test_accept_move_end(temp_db, esc) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databases ;\r') - assert test.shell_process.expect_exact(['Error: Parser exception: Invalid input :', pexpect.EOF]) == 0 + assert ( + test.shell_process.expect_exact( + ['Error: Parser exception: Invalid input :', pexpect.EOF], + ) + == 0 + ) test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databases") test.send_statement(esc) - test.send_statement(KEY_ACTION.BACKSPACE.value) # remove semicolon + test.send_statement(KEY_ACTION.BACKSPACE.value) # remove semicolon test.send_finished_statement('rule" AS a;\r') assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_next_history(temp_db): +def test_next_history(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() set_up_search(test) @@ -78,9 +91,9 @@ def test_next_history(temp_db): test.send_statement("\x1b[A" * 2) test.send_finished_statement(KEY_ACTION.ENTER.value) assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 - -def test_prev_history(temp_db): + +def test_prev_history(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() set_up_search(test) @@ -91,7 +104,7 @@ def test_prev_history(temp_db): assert test.shell_process.expect_exact(["| the shell is fun |", pexpect.EOF]) == 0 -def test_move_left(temp_db): +def test_move_left(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databasesrule" AS a;\r') @@ -99,11 +112,11 @@ def test_move_left(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("databasesr") test.send_statement("\x1b[D") - test.send_finished_statement(' \r') + test.send_finished_statement(" \r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 -def test_move_right(temp_db): +def test_move_right(temp_db) -> None: test = ShellTest().add_argument(temp_db) test.start() test.send_finished_statement('RETURN "databasesrule" AS a;\r') @@ -111,5 +124,5 @@ def test_move_right(temp_db): test.send_control_statement(KEY_ACTION.CTRL_R.value) test.send_statement("database") test.send_statement("\x1b[C") - test.send_finished_statement(' \r') + test.send_finished_statement(" \r") assert test.shell_process.expect_exact(["| databases rule |", pexpect.EOF]) == 0 diff --git a/tools/shell/test/test_shell_flags.py b/tools/shell/test/test_shell_flags.py index 19720f109c9..8eadd2b3e41 100644 --- a/tools/shell/test/test_shell_flags.py +++ b/tools/shell/test/test_shell_flags.py @@ -1,115 +1,79 @@ +import os + import pytest -from test_helper import * from conftest import ShellTest -import os +from test_helper import KUZU_VERSION, deleteIfExists -def test_database_path(temp_db): +def test_database_path(temp_db) -> None: # no database path - test = ( - ShellTest() - .statement('RETURN "databases rule" AS a;') - ) + test = ShellTest().statement('RETURN "databases rule" AS a;') result = test.run() result.check_stderr("Option 'databasePath' is required") - + # invalid database path - test = ( - ShellTest() - .add_argument("///////") - .statement('RETURN "databases rule" AS a;') - ) + test = ShellTest().add_argument("///////").statement('RETURN "databases rule" AS a;') result = test.run() result.check_stderr("Cannot open file ///////.lock: Permission denied") - + # valid database path - test = ( - ShellTest() - .add_argument(temp_db) - .statement('RETURN "databases rule" AS a;') - ) + test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" AS a;') result = test.run() result.check_stdout("databases rule") @pytest.mark.parametrize( "flag", - [ - ("-h"), - ("--help"), - ], + ["-h", "--help"], ) -def test_help(temp_db, flag): - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument(flag) - ) +def test_help(temp_db, flag) -> None: + test = ShellTest().add_argument(temp_db).add_argument(flag) result = test.run() result.check_stderr("help") - + @pytest.mark.parametrize( "flag", [ - ("-d"), - ("--defaultBPSize"), + "-d", + "--defaultBPSize", ], ) -def test_default_bp_size(temp_db, flag): +def test_default_bp_size(temp_db, flag) -> None: # empty flag argument - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument(flag) - ) + test = ShellTest().add_argument(temp_db).add_argument(flag) result = test.run() - result.check_stderr(f"Flag '{flag.replace('-', '')}' requires an argument but received none") - - # flag argument is not a number - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument(flag) - .add_argument("kuzu") + result.check_stderr( + f"Flag '{flag.replace('-', '')}' requires an argument but received none", ) + + # flag argument is not a number + test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("kuzu") result = test.run() result.check_stderr("Argument '' received invalid value type 'kuzu'") - + # successful flag - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument(flag) - .add_argument("1000") - ) + test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("1000") result = test.run() result.check_stdout(f"Opened the database at path: {temp_db} in read-write mode.") - -def test_no_compression(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("--nocompression") - ) + +def test_no_compression(temp_db) -> None: + test = ShellTest().add_argument(temp_db).add_argument("--nocompression") result = test.run() result.check_stdout(f"Opened the database at path: {temp_db} in read-write mode.") - + @pytest.mark.parametrize( "flag", [ - ("-r"), - ("--readOnly"), + "-r", + "--readOnly", ], ) -def test_read_only(temp_db, flag): +def test_read_only(temp_db, flag) -> None: # cannot open an empty database in read only mode so initialize database - test = ( - ShellTest() - .add_argument(temp_db) - ) + test = ShellTest().add_argument(temp_db) result = test.run() result.check_stdout(f"Opened the database at path: {temp_db} in read-write mode.") @@ -125,30 +89,23 @@ def test_read_only(temp_db, flag): result = test.run() result.check_stdout(f"Opened the database at path: {temp_db} in read-only mode.") result.check_stdout("databases rule") - result.check_stdout("Error: Cannot execute write operations in a read-only database!") + result.check_stdout( + "Error: Cannot execute write operations in a read-only database!", + ) result.check_stdout("kuzu is cool") - -def test_history_path(temp_db, history_path): + +def test_history_path(temp_db, history_path) -> None: # empty flag argument - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("-p") - ) + test = ShellTest().add_argument(temp_db).add_argument("-p") result = test.run() result.check_stderr("Flag 'p' requires an argument but received none") - + # invalid path - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("-p") - .add_argument("///////") - ) + test = ShellTest().add_argument(temp_db).add_argument("-p").add_argument("///////") result = test.run() result.check_stderr("Invalid path to directory for history file") - + # valid path, file doesn't exist test = ( ShellTest() @@ -159,10 +116,9 @@ def test_history_path(temp_db, history_path): ) result = test.run() result.check_stdout("databases rule") - f = open(os.path.join(history_path, "history.txt")) - assert f.readline() == 'RETURN "databases rule" AS a;\n' - f.close() - + with open(os.path.join(history_path, "history.txt")) as f: + assert f.readline() == 'RETURN "databases rule" AS a;\n' + # valid path, file exists test = ( ShellTest() @@ -172,44 +128,31 @@ def test_history_path(temp_db, history_path): .statement('RETURN "kuzu is cool" AS b;') ) result = test.run() - f = open(os.path.join(history_path, "history.txt")) - assert f.readline() == 'RETURN "databases rule" AS a;\n' - assert f.readline() == 'RETURN "kuzu is cool" AS b;\n' - f.close() - - deleteIfExists(os.path.join(history_path, 'history.txt')) - + with open(os.path.join(history_path, "history.txt")) as f: + assert f.readline() == 'RETURN "databases rule" AS a;\n' + assert f.readline() == 'RETURN "kuzu is cool" AS b;\n' + + deleteIfExists(os.path.join(history_path, "history.txt")) + @pytest.mark.parametrize( "flag", [ - ("-v"), - ("--version"), + "-v", + "--version", ], ) -def test_version(temp_db, flag): - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument(flag) - ) +def test_version(temp_db, flag) -> None: + test = ShellTest().add_argument(temp_db).add_argument(flag) result = test.run() result.check_stdout(KUZU_VERSION) - -def test_bad_flag(temp_db): - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("-b") - ) + +def test_bad_flag(temp_db) -> None: + test = ShellTest().add_argument(temp_db).add_argument("-b") result = test.run() - result.check_stderr(f"Flag could not be matched: 'b'") - - test = ( - ShellTest() - .add_argument(temp_db) - .add_argument("--badflag") - ) + result.check_stderr("Flag could not be matched: 'b'") + + test = ShellTest().add_argument(temp_db).add_argument("--badflag") result = test.run() - result.check_stderr(f"Flag could not be matched: badflag") + result.check_stderr("Flag could not be matched: badflag")