Compare commits
5 Commits
v2.14.1-rc
...
orderby-wo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf31496b0f | ||
|
|
1f5a6e5057 | ||
|
|
115e7d87fc | ||
|
|
067387df10 | ||
|
|
646fd8b6da |
8
.github/workflows/daily_benchmark.yaml
vendored
8
.github/workflows/daily_benchmark.yaml
vendored
@@ -75,6 +75,8 @@ jobs:
|
||||
|
||||
./benchmark.py vendor-native --num-workers-for-benchmark 12 --export-results cartesian.json cartesian
|
||||
|
||||
./benchmark.py vendor-native --num-workers-for-benchmark 12 --export-results order_by.json order_by
|
||||
|
||||
- name: Upload mgbench results
|
||||
run: |
|
||||
cd tools/bench-graph-client
|
||||
@@ -104,3 +106,9 @@ jobs:
|
||||
--github-run-id "${{ github.run_id }}" \
|
||||
--github-run-number "${{ github.run_number }}" \
|
||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||
|
||||
./main.py --benchmark-name "order_by" \
|
||||
--benchmark-results "../../tests/mgbench/order_by.json" \
|
||||
--github-run-id "${{ github.run_id }}" \
|
||||
--github-run-number "${{ github.run_number }}" \
|
||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||
|
||||
5
.github/workflows/diff.yaml
vendored
5
.github/workflows/diff.yaml
vendored
@@ -365,11 +365,6 @@ jobs:
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
|
||||
make -j$THREADS memgraph
|
||||
|
||||
- name: Refresh Jepsen Cluster
|
||||
run: |
|
||||
cd tests/jepsen
|
||||
./run.sh cluster-refresh
|
||||
|
||||
- name: Run Jepsen tests
|
||||
run: |
|
||||
cd tests/jepsen
|
||||
|
||||
239
.github/workflows/release_debian10.yaml
vendored
239
.github/workflows/release_debian10.yaml
vendored
@@ -1,7 +1,4 @@
|
||||
name: Release Debian 10
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -13,30 +10,23 @@ on:
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
push:
|
||||
branches:
|
||||
- "release/**"
|
||||
tags:
|
||||
- "v*.*.*-rc*"
|
||||
- "v*.*-rc*"
|
||||
|
||||
schedule:
|
||||
- cron: "0 22 * * *"
|
||||
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
BUILD_TYPE: ${{ github.event.inputs.build_type || 'Release' }}
|
||||
|
||||
jobs:
|
||||
community_build:
|
||||
name: "Community build"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
timeout-minutes: 960
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -50,6 +40,10 @@ jobs:
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Set default build_type to Release
|
||||
INPUT_BUILD_TYPE=${{ github.event.inputs.build_type }}
|
||||
BUILD_TYPE=${INPUT_BUILD_TYPE:-"Release"}
|
||||
|
||||
# Build community binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMG_ENTERPRISE=OFF ..
|
||||
@@ -71,11 +65,10 @@ jobs:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -117,19 +110,22 @@ jobs:
|
||||
tar -czf code_coverage.tar.gz coverage.json html report.json summary.rmu
|
||||
|
||||
- name: Save code coverage
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "Code coverage(Coverage build)"
|
||||
name: "Code coverage"
|
||||
path: tools/github/generated/code_coverage.tar.gz
|
||||
|
||||
debug_build:
|
||||
name: "Debug build"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -161,6 +157,10 @@ jobs:
|
||||
run: |
|
||||
./tests/drivers/run.sh
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
tests/integration/run.sh
|
||||
|
||||
- name: Run cppcheck and clang-format
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
@@ -171,49 +171,23 @@ jobs:
|
||||
./cppcheck_and_clang_format diff
|
||||
|
||||
- name: Save cppcheck and clang-format errors
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "Code coverage(Debug build)"
|
||||
name: "Code coverage"
|
||||
path: tools/github/cppcheck_and_clang_format.txt
|
||||
|
||||
debug_integration_test:
|
||||
name: "Debug integration tests"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build debug binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build debug binaries.
|
||||
cd build
|
||||
cmake ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
tests/integration/run.sh
|
||||
|
||||
release_build:
|
||||
name: "Release build"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
runs-on: [self-hosted, Linux, X64, Debian10, BigMemory]
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
timeout-minutes: 960
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -227,6 +201,10 @@ jobs:
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Set default build_type to Release
|
||||
INPUT_BUILD_TYPE=${{ github.event.inputs.build_type }}
|
||||
BUILD_TYPE=${INPUT_BUILD_TYPE:-"Release"}
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
@@ -248,60 +226,11 @@ jobs:
|
||||
cpack -G DEB --config ../CPackConfig.cmake
|
||||
|
||||
- name: Save enterprise DEB package
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "Enterprise DEB package"
|
||||
path: build/output/memgraph*.deb
|
||||
|
||||
- name: Run GQL Behave tests
|
||||
run: |
|
||||
cd tests
|
||||
./setup.sh /opt/toolchain-v4/activate
|
||||
cd gql_behave
|
||||
./continuous_integration
|
||||
|
||||
- name: Save quality assurance status
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "GQL Behave Status"
|
||||
path: |
|
||||
tests/gql_behave/gql_behave_status.csv
|
||||
tests/gql_behave/gql_behave_status.html
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Run unit tests.
|
||||
cd build
|
||||
ctest -R memgraph__unit --output-on-failure
|
||||
|
||||
release_benchmark_tests:
|
||||
name: "Release Benchmark Tests"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run micro benchmark tests
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
@@ -328,37 +257,29 @@ jobs:
|
||||
--num-database-workers 9 --num-clients-workers 30 \
|
||||
--no-strict
|
||||
|
||||
release_e2e_test:
|
||||
name: "Release End-to-end Test"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
- name: Run GQL Behave tests
|
||||
run: |
|
||||
cd tests
|
||||
./setup.sh /opt/toolchain-v4/activate
|
||||
cd gql_behave
|
||||
./continuous_integration
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Save quality assurance status
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
name: "GQL Behave Status"
|
||||
path: |
|
||||
tests/gql_behave/gql_behave_status.csv
|
||||
tests/gql_behave/gql_behave_status.html
|
||||
|
||||
- name: Build release binaries
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries
|
||||
# Run unit tests.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Ensure Kafka and Pulsar are up
|
||||
run: |
|
||||
cd tests/e2e/streams/kafka
|
||||
docker-compose up -d
|
||||
cd ../pulsar
|
||||
docker-compose up -d
|
||||
ctest -R memgraph__unit --output-on-failure
|
||||
|
||||
- name: Run e2e tests
|
||||
run: |
|
||||
@@ -368,40 +289,6 @@ jobs:
|
||||
cd e2e
|
||||
./run.sh
|
||||
|
||||
- name: Ensure Kafka and Pulsar are down
|
||||
if: always()
|
||||
run: |
|
||||
cd tests/e2e/streams/kafka
|
||||
docker-compose down
|
||||
cd ../pulsar
|
||||
docker-compose down
|
||||
|
||||
release_durability_stress_tests:
|
||||
name: "Release durability and stress tests"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10]
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run stress test (plain)
|
||||
run: |
|
||||
cd tests/stress
|
||||
@@ -412,6 +299,11 @@ jobs:
|
||||
cd tests/stress
|
||||
./continuous_integration --use-ssl
|
||||
|
||||
- name: Run stress test (large)
|
||||
run: |
|
||||
cd tests/stress
|
||||
./continuous_integration --large-dataset
|
||||
|
||||
- name: Run durability test (plain)
|
||||
run: |
|
||||
cd tests/stress
|
||||
@@ -427,11 +319,15 @@ jobs:
|
||||
release_jepsen_test:
|
||||
name: "Release Jepsen Test"
|
||||
runs-on: [self-hosted, Linux, X64, Debian10, JepsenControl]
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -444,23 +340,22 @@ jobs:
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Set default build_type to Release
|
||||
INPUT_BUILD_TYPE=${{ github.event.inputs.build_type }}
|
||||
BUILD_TYPE=${INPUT_BUILD_TYPE:-"Release"}
|
||||
|
||||
# Build only memgraph release binary.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS memgraph
|
||||
|
||||
- name: Refresh Jepsen Cluster
|
||||
run: |
|
||||
cd tests/jepsen
|
||||
./run.sh cluster-refresh
|
||||
|
||||
- name: Run Jepsen tests
|
||||
run: |
|
||||
cd tests/jepsen
|
||||
./run.sh test-all-individually --binary ../../build/memgraph --ignore-run-stdout-logs --ignore-run-stderr-logs
|
||||
|
||||
- name: Save Jepsen report
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: "Jepsen Report"
|
||||
|
||||
224
.github/workflows/release_ubuntu2004.yaml
vendored
224
.github/workflows/release_ubuntu2004.yaml
vendored
@@ -1,7 +1,4 @@
|
||||
name: Release Ubuntu 20.04
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -13,30 +10,23 @@ on:
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
push:
|
||||
branches:
|
||||
- "release/**"
|
||||
tags:
|
||||
- "v*.*.*-rc*"
|
||||
- "v*.*-rc*"
|
||||
|
||||
schedule:
|
||||
- cron: "0 22 * * *"
|
||||
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
BUILD_TYPE: ${{ github.event.inputs.build_type || 'Release' }}
|
||||
|
||||
jobs:
|
||||
community_build:
|
||||
name: "Community build"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
timeout-minutes: 960
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -50,6 +40,10 @@ jobs:
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Set default build_type to Release
|
||||
INPUT_BUILD_TYPE=${{ github.event.inputs.build_type }}
|
||||
BUILD_TYPE=${INPUT_BUILD_TYPE:-"Release"}
|
||||
|
||||
# Build community binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMG_ENTERPRISE=OFF ..
|
||||
@@ -67,11 +61,14 @@ jobs:
|
||||
coverage_build:
|
||||
name: "Coverage build"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -113,19 +110,22 @@ jobs:
|
||||
tar -czf code_coverage.tar.gz coverage.json html report.json summary.rmu
|
||||
|
||||
- name: Save code coverage
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "Code coverage(Coverage build)"
|
||||
name: "Code coverage"
|
||||
path: tools/github/generated/code_coverage.tar.gz
|
||||
|
||||
debug_build:
|
||||
name: "Debug build"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -157,6 +157,10 @@ jobs:
|
||||
run: |
|
||||
./tests/drivers/run.sh
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
tests/integration/run.sh
|
||||
|
||||
- name: Run cppcheck and clang-format
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
@@ -167,49 +171,23 @@ jobs:
|
||||
./cppcheck_and_clang_format diff
|
||||
|
||||
- name: Save cppcheck and clang-format errors
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "Code coverage(Debug build)"
|
||||
name: "Code coverage"
|
||||
path: tools/github/cppcheck_and_clang_format.txt
|
||||
|
||||
debug_integration_test:
|
||||
name: "Debug integration tests"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build debug binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build debug binaries.
|
||||
cd build
|
||||
cmake ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
tests/integration/run.sh
|
||||
|
||||
release_build:
|
||||
name: "Release build"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
timeout-minutes: 960
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
@@ -223,6 +201,10 @@ jobs:
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Set default build_type to Release
|
||||
INPUT_BUILD_TYPE=${{ github.event.inputs.build_type }}
|
||||
BUILD_TYPE=${INPUT_BUILD_TYPE:-"Release"}
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
@@ -244,60 +226,11 @@ jobs:
|
||||
cpack -G DEB --config ../CPackConfig.cmake
|
||||
|
||||
- name: Save enterprise DEB package
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "Enterprise DEB package"
|
||||
path: build/output/memgraph*.deb
|
||||
|
||||
- name: Run GQL Behave tests
|
||||
run: |
|
||||
cd tests
|
||||
./setup.sh /opt/toolchain-v4/activate
|
||||
cd gql_behave
|
||||
./continuous_integration
|
||||
|
||||
- name: Save quality assurance status
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "GQL Behave Status"
|
||||
path: |
|
||||
tests/gql_behave/gql_behave_status.csv
|
||||
tests/gql_behave/gql_behave_status.html
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Run unit tests.
|
||||
cd build
|
||||
ctest -R memgraph__unit --output-on-failure
|
||||
|
||||
release_benchmark_tests:
|
||||
name: "Release Benchmark Tests"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run micro benchmark tests
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
@@ -324,37 +257,29 @@ jobs:
|
||||
--num-database-workers 9 --num-clients-workers 30 \
|
||||
--no-strict
|
||||
|
||||
release_e2e_test:
|
||||
name: "Release End-to-end Test"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
- name: Run GQL Behave tests
|
||||
run: |
|
||||
cd tests
|
||||
./setup.sh /opt/toolchain-v4/activate
|
||||
cd gql_behave
|
||||
./continuous_integration
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Save quality assurance status
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
name: "GQL Behave Status"
|
||||
path: |
|
||||
tests/gql_behave/gql_behave_status.csv
|
||||
tests/gql_behave/gql_behave_status.html
|
||||
|
||||
- name: Build release binaries
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries
|
||||
# Run unit tests.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Ensure Kafka and Pulsar are up
|
||||
run: |
|
||||
cd tests/e2e/streams/kafka
|
||||
docker-compose up -d
|
||||
cd ../pulsar
|
||||
docker-compose up -d
|
||||
ctest -R memgraph__unit --output-on-failure
|
||||
|
||||
- name: Run e2e tests
|
||||
run: |
|
||||
@@ -364,40 +289,6 @@ jobs:
|
||||
cd e2e
|
||||
./run.sh
|
||||
|
||||
- name: Ensure Kafka and Pulsar are down
|
||||
if: always()
|
||||
run: |
|
||||
cd tests/e2e/streams/kafka
|
||||
docker-compose down
|
||||
cd ../pulsar
|
||||
docker-compose down
|
||||
|
||||
release_durability_stress_tests:
|
||||
name: "Release durability and stress tests"
|
||||
runs-on: [self-hosted, Linux, X64, Ubuntu20.04]
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run stress test (plain)
|
||||
run: |
|
||||
cd tests/stress
|
||||
@@ -408,6 +299,11 @@ jobs:
|
||||
cd tests/stress
|
||||
./continuous_integration --use-ssl
|
||||
|
||||
- name: Run stress test (large)
|
||||
run: |
|
||||
cd tests/stress
|
||||
./continuous_integration --large-dataset
|
||||
|
||||
- name: Run durability test (plain)
|
||||
run: |
|
||||
cd tests/stress
|
||||
|
||||
68
.github/workflows/stress_test_large.yaml
vendored
68
.github/workflows/stress_test_large.yaml
vendored
@@ -1,68 +0,0 @@
|
||||
name: Stress test large
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_type:
|
||||
type: choice
|
||||
description: "Memgraph Build type. Default value is Release."
|
||||
default: 'Release'
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*-rc*"
|
||||
- "v*.*-rc*"
|
||||
schedule:
|
||||
- cron: "0 22 * * *"
|
||||
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
BUILD_TYPE: ${{ github.event.inputs.build_type || 'Release' }}
|
||||
|
||||
jobs:
|
||||
stress_test_large:
|
||||
name: "Stress test large"
|
||||
timeout-minutes: 720
|
||||
strategy:
|
||||
matrix:
|
||||
os: [Debian10, Ubuntu20.04]
|
||||
extra: [BigMemory, Gen8]
|
||||
exclude:
|
||||
- os: Debian10
|
||||
extra: Gen8
|
||||
- os: Ubuntu20.04
|
||||
extra: BigMemory
|
||||
runs-on: [self-hosted, Linux, X64, "${{ matrix.os }}", "${{ matrix.extra }}"]
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run stress test (large)
|
||||
run: |
|
||||
cd tests/stress
|
||||
./continuous_integration --large-dataset
|
||||
@@ -1,32 +0,0 @@
|
||||
# Tantivy ADR
|
||||
|
||||
**Author**
|
||||
Marko Budiselic (github.com/gitbuda)
|
||||
|
||||
**Status**
|
||||
APPROVED
|
||||
|
||||
**Date**
|
||||
January 5, 2024
|
||||
|
||||
**Problem**
|
||||
|
||||
For some of Memgraph workloads, text search is a required feature. We don't
|
||||
want to build a new text search engine because that's not Memgraph's core
|
||||
value.
|
||||
|
||||
**Criteria**
|
||||
|
||||
- easy integration with our C++ codebase
|
||||
- ability to operate in-memory and on-disk
|
||||
- sufficient features (regex, full-text search, fuzzy search, aggregations over
|
||||
text data)
|
||||
- production-ready
|
||||
|
||||
**Decision**
|
||||
|
||||
All known C++ libraries are not production-ready. Recent Rust libraries, in
|
||||
particular [Tantivy](https://github.com/quickwit-oss/tantivy), seem to provide
|
||||
much more features, it is production ready. The way how we'll integrate Tantivy
|
||||
into the current Memgraph codebase is via
|
||||
[cxx](https://github.com/dtolnay/cxx). **We select Tantivy.**
|
||||
@@ -1,34 +0,0 @@
|
||||
# NuRaft ADR
|
||||
|
||||
**Author**
|
||||
Marko Budiselic (github.com/gitbuda)
|
||||
|
||||
**Status**
|
||||
PROPOSED
|
||||
|
||||
**Date**
|
||||
January 10, 2024
|
||||
|
||||
**Problem**
|
||||
|
||||
In order to enhance Memgraph to have High Availability features as requested by
|
||||
customers, we want to have reliable coordinators backed by RAFT consensus algorithm. Implementing
|
||||
RAFT to be correct and performant is a very challenging task. Skillful Memgraph
|
||||
engineers already tried 3 times and failed to deliver in a reasonable timeframe
|
||||
all three times (approximately 4 person-weeks of engineering work each time).
|
||||
|
||||
**Criteria**
|
||||
|
||||
- easy integration with our C++ codebase
|
||||
- heavily tested in production environments
|
||||
- implementation of performance optimizations on top of the canonical Raft
|
||||
implementation
|
||||
|
||||
**Decision**
|
||||
|
||||
There are a few, robust C++ implementations of Raft but as a part of other
|
||||
projects or bigger libraries. **We select
|
||||
[NuRaft](https://github.com/eBay/NuRaft)** because it focuses on delivering
|
||||
Raft without bloatware, and it's used by
|
||||
[Clickhouse](https://github.com/ClickHouse/ClickHouse) (an comparable peer to
|
||||
Memgraph, a very well-established product).
|
||||
@@ -64,7 +64,7 @@ option(MG_ENTERPRISE "Build Memgraph Enterprise Edition" ON)
|
||||
# Set the current version here to override the automatic version detection. The
|
||||
# version must be specified as `X.Y.Z`. Primarily used when building new patch
|
||||
# versions.
|
||||
set(MEMGRAPH_OVERRIDE_VERSION "2.14.0")
|
||||
set(MEMGRAPH_OVERRIDE_VERSION "")
|
||||
|
||||
# Custom suffix that this version should have. The suffix can be any arbitrary
|
||||
# string. Primarily used when building a version for a specific customer.
|
||||
|
||||
@@ -36,7 +36,7 @@ ADDITIONAL USE GRANT: You may use the Licensed Work in accordance with the
|
||||
3. using the Licensed Work to create a work or solution
|
||||
which competes (or might reasonably be expected to
|
||||
compete) with the Licensed Work.
|
||||
CHANGE DATE: 2028-21-01
|
||||
CHANGE DATE: 2027-08-12
|
||||
CHANGE LICENSE: Apache License, Version 2.0
|
||||
|
||||
For information about alternative licensing arrangements, please visit: https://memgraph.com/legal.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -92,7 +92,7 @@ void RegisterLicenseSettings(LicenseChecker &license_checker, utils::Settings &s
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
LicenseChecker global_license_checker;
|
||||
|
||||
LicenseChecker::~LicenseChecker() { Finalize(); }
|
||||
LicenseChecker::~LicenseChecker() { scheduler_.Stop(); }
|
||||
|
||||
std::pair<std::string, std::string> LicenseChecker::ExtractLicenseInfo(const utils::Settings &settings) const {
|
||||
if (license_info_override_) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -89,8 +89,6 @@ struct LicenseChecker {
|
||||
|
||||
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> &GetLicenseInfo();
|
||||
|
||||
void Finalize() { scheduler_.Stop(); }
|
||||
|
||||
private:
|
||||
std::pair<std::string, std::string> ExtractLicenseInfo(const utils::Settings &settings) const;
|
||||
void RevalidateLicense(const utils::Settings &settings);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -257,8 +257,6 @@ int main(int argc, char **argv) {
|
||||
// register all runtime settings
|
||||
memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker,
|
||||
memgraph::utils::global_settings);
|
||||
memgraph::utils::OnScopeExit global_license_finalizer([] { memgraph::license::global_license_checker.Finalize(); });
|
||||
|
||||
memgraph::flags::run_time::Initialize();
|
||||
|
||||
memgraph::license::global_license_checker.CheckEnvLicense();
|
||||
@@ -548,7 +546,6 @@ int main(int argc, char **argv) {
|
||||
|
||||
memgraph::query::procedure::gModuleRegistry.UnloadAllModules();
|
||||
|
||||
python_gc_scheduler.Stop();
|
||||
Py_END_ALLOW_THREADS;
|
||||
// Shutdown Python
|
||||
Py_Finalize();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -36,22 +36,14 @@ namespace memgraph::memory {
|
||||
|
||||
void QueriesMemoryControl::UpdateThreadToTransactionId(const std::thread::id &thread_id, uint64_t transaction_id) {
|
||||
auto accessor = thread_id_to_transaction_id.access();
|
||||
auto elem = accessor.find(thread_id);
|
||||
if (elem == accessor.end()) {
|
||||
accessor.insert({thread_id, {transaction_id, 1}});
|
||||
} else {
|
||||
elem->transaction_id.cnt++;
|
||||
}
|
||||
accessor.insert({thread_id, transaction_id});
|
||||
}
|
||||
|
||||
void QueriesMemoryControl::EraseThreadToTransactionId(const std::thread::id &thread_id, uint64_t transaction_id) {
|
||||
auto accessor = thread_id_to_transaction_id.access();
|
||||
auto elem = accessor.find(thread_id);
|
||||
MG_ASSERT(elem != accessor.end() && elem->transaction_id == transaction_id);
|
||||
elem->transaction_id.cnt--;
|
||||
if (elem->transaction_id.cnt == 0) {
|
||||
accessor.remove(thread_id);
|
||||
}
|
||||
accessor.remove(thread_id);
|
||||
}
|
||||
|
||||
void QueriesMemoryControl::TrackAllocOnCurrentThread(size_t size) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -78,20 +78,9 @@ class QueriesMemoryControl {
|
||||
bool IsThreadTracked();
|
||||
|
||||
private:
|
||||
struct TransactionId {
|
||||
uint64_t id;
|
||||
uint64_t cnt;
|
||||
|
||||
bool operator<(const TransactionId &other) const { return id < other.id; }
|
||||
bool operator==(const TransactionId &other) const { return id == other.id; }
|
||||
|
||||
bool operator<(uint64_t other) const { return id < other; }
|
||||
bool operator==(uint64_t other) const { return id == other; }
|
||||
};
|
||||
|
||||
struct ThreadIdToTransactionId {
|
||||
std::thread::id thread_id;
|
||||
TransactionId transaction_id;
|
||||
uint64_t transaction_id;
|
||||
|
||||
bool operator<(const ThreadIdToTransactionId &other) const { return thread_id < other.thread_id; }
|
||||
bool operator==(const ThreadIdToTransactionId &other) const { return thread_id == other.thread_id; }
|
||||
@@ -109,9 +98,6 @@ class QueriesMemoryControl {
|
||||
|
||||
bool operator<(uint64_t other) const { return transaction_id < other; }
|
||||
bool operator==(uint64_t other) const { return transaction_id == other; }
|
||||
|
||||
bool operator<(TransactionId other) const { return transaction_id < other.id; }
|
||||
bool operator==(TransactionId other) const { return transaction_id == other.id; }
|
||||
};
|
||||
|
||||
utils::SkipList<ThreadIdToTransactionId> thread_id_to_transaction_id;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -114,17 +114,12 @@ class Path {
|
||||
/** Expands the path with the given vertex. */
|
||||
void Expand(const VertexAccessor &vertex) {
|
||||
DMG_ASSERT(vertices_.size() == edges_.size(), "Illegal path construction order");
|
||||
DMG_ASSERT(edges_.empty() || (!edges_.empty() && (edges_.back().To().Gid() == vertex.Gid() ||
|
||||
edges_.back().From().Gid() == vertex.Gid())),
|
||||
"Illegal path construction order");
|
||||
vertices_.emplace_back(vertex);
|
||||
}
|
||||
|
||||
/** Expands the path with the given edge. */
|
||||
void Expand(const EdgeAccessor &edge) {
|
||||
DMG_ASSERT(vertices_.size() - 1 == edges_.size(), "Illegal path construction order");
|
||||
DMG_ASSERT(vertices_.back().Gid() == edge.From().Gid() || vertices_.back().Gid() == edge.To().Gid(),
|
||||
"Illegal path construction order");
|
||||
edges_.emplace_back(edge);
|
||||
}
|
||||
|
||||
@@ -135,14 +130,6 @@ class Path {
|
||||
Expand(others...);
|
||||
}
|
||||
|
||||
void Shrink() {
|
||||
DMG_ASSERT(!vertices_.empty(), "Vertices should not be empty in the path before shrink.");
|
||||
vertices_.pop_back();
|
||||
if (!edges_.empty()) {
|
||||
edges_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the number of expansions (edges) in this path. */
|
||||
auto size() const { return edges_.size(); }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -1057,8 +1057,7 @@ class ExpandVariableCursor : public Cursor {
|
||||
if (!self_.common_.existing_node) {
|
||||
frame[self_.common_.node_symbol] = start_vertex;
|
||||
return true;
|
||||
}
|
||||
if (CheckExistingNode(start_vertex, self_.common_.node_symbol, frame)) {
|
||||
} else if (CheckExistingNode(start_vertex, self_.common_.node_symbol, frame)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1244,10 +1243,6 @@ class ExpandVariableCursor : public Cursor {
|
||||
MG_ASSERT(frame[self_.filter_lambda_.accumulated_path_symbol.value()].IsPath(),
|
||||
"Accumulated path must be path");
|
||||
Path &accumulated_path = frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath();
|
||||
// Shrink the accumulated path including current level if necessary
|
||||
while (accumulated_path.size() >= edges_on_frame.size()) {
|
||||
accumulated_path.Shrink();
|
||||
}
|
||||
accumulated_path.Expand(current_edge.first);
|
||||
accumulated_path.Expand(current_vertex);
|
||||
}
|
||||
@@ -1265,9 +1260,10 @@ class ExpandVariableCursor : public Cursor {
|
||||
if (self_.common_.existing_node && !CheckExistingNode(current_vertex, self_.common_.node_symbol, frame)) continue;
|
||||
|
||||
// We only yield true if we satisfy the lower bound.
|
||||
if (static_cast<int64_t>(edges_on_frame.size()) >= lower_bound_) {
|
||||
if (static_cast<int64_t>(edges_on_frame.size()) >= lower_bound_)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1531,8 +1527,8 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
: self_(self),
|
||||
input_cursor_(self_.input()->MakeCursor(mem)),
|
||||
processed_(mem),
|
||||
to_visit_next_(mem),
|
||||
to_visit_current_(mem) {
|
||||
to_visit_current_(mem),
|
||||
to_visit_next_(mem) {
|
||||
MG_ASSERT(!self_.common_.existing_node,
|
||||
"Single source shortest path algorithm "
|
||||
"should not be used when `existing_node` "
|
||||
@@ -1562,14 +1558,12 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
#endif
|
||||
frame[self_.filter_lambda_.inner_edge_symbol] = edge;
|
||||
frame[self_.filter_lambda_.inner_node_symbol] = vertex;
|
||||
std::optional<Path> curr_acc_path = std::nullopt;
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
MG_ASSERT(frame[self_.filter_lambda_.accumulated_path_symbol.value()].IsPath(),
|
||||
"Accumulated path must have Path type");
|
||||
Path &accumulated_path = frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath();
|
||||
accumulated_path.Expand(edge);
|
||||
accumulated_path.Expand(vertex);
|
||||
curr_acc_path = accumulated_path;
|
||||
}
|
||||
|
||||
if (self_.filter_lambda_.expression) {
|
||||
@@ -1584,33 +1578,21 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
throw QueryRuntimeException("Expansion condition must evaluate to boolean or null.");
|
||||
}
|
||||
}
|
||||
to_visit_next_.emplace_back(edge, vertex, std::move(curr_acc_path));
|
||||
to_visit_next_.emplace_back(edge, vertex);
|
||||
processed_.emplace(vertex, edge);
|
||||
};
|
||||
|
||||
auto restore_frame_state_after_expansion = [this, &frame]() {
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath().Shrink();
|
||||
}
|
||||
};
|
||||
|
||||
// populates the to_visit_next_ structure with expansions
|
||||
// from the given vertex. skips expansions that don't satisfy
|
||||
// the "where" condition.
|
||||
auto expand_from_vertex = [this, &expand_pair, &restore_frame_state_after_expansion](const auto &vertex) {
|
||||
auto expand_from_vertex = [this, &expand_pair](const auto &vertex) {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::IN) {
|
||||
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types)).edges;
|
||||
for (const auto &edge : out_edges) {
|
||||
expand_pair(edge, edge.To());
|
||||
restore_frame_state_after_expansion();
|
||||
}
|
||||
for (const auto &edge : out_edges) expand_pair(edge, edge.To());
|
||||
}
|
||||
if (self_.common_.direction != EdgeAtom::Direction::OUT) {
|
||||
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types)).edges;
|
||||
for (const auto &edge : in_edges) {
|
||||
expand_pair(edge, edge.From());
|
||||
restore_frame_state_after_expansion();
|
||||
}
|
||||
for (const auto &edge : in_edges) expand_pair(edge, edge.From());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1656,14 +1638,14 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
}
|
||||
|
||||
// take the next expansion from the queue
|
||||
auto [curr_edge, curr_vertex, curr_acc_path] = to_visit_current_.back();
|
||||
auto expansion = to_visit_current_.back();
|
||||
to_visit_current_.pop_back();
|
||||
|
||||
// create the frame value for the edges
|
||||
auto *pull_memory = context.evaluation_context.memory;
|
||||
utils::pmr::vector<TypedValue> edge_list(pull_memory);
|
||||
edge_list.emplace_back(curr_edge);
|
||||
auto last_vertex = curr_vertex;
|
||||
edge_list.emplace_back(expansion.first);
|
||||
auto last_vertex = expansion.second;
|
||||
while (true) {
|
||||
const EdgeAccessor &last_edge = edge_list.back().ValueEdge();
|
||||
last_vertex = last_edge.From() == last_vertex ? last_edge.To() : last_edge.From();
|
||||
@@ -1675,17 +1657,11 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
}
|
||||
|
||||
// expand only if what we've just expanded is less then max depth
|
||||
if (static_cast<int64_t>(edge_list.size()) < upper_bound_) {
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
MG_ASSERT(curr_acc_path.has_value(), "Expected non-null accumulated path");
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()] = std::move(curr_acc_path.value());
|
||||
}
|
||||
expand_from_vertex(curr_vertex);
|
||||
}
|
||||
if (static_cast<int64_t>(edge_list.size()) < upper_bound_) expand_from_vertex(expansion.second);
|
||||
|
||||
if (static_cast<int64_t>(edge_list.size()) < lower_bound_) continue;
|
||||
|
||||
frame[self_.common_.node_symbol] = curr_vertex;
|
||||
frame[self_.common_.node_symbol] = expansion.second;
|
||||
|
||||
// place edges on the frame in the correct order
|
||||
std::reverse(edge_list.begin(), edge_list.end());
|
||||
@@ -1717,9 +1693,9 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
// edge because the root does not get expanded from anything.
|
||||
// contains visited vertices as well as those scheduled to be visited.
|
||||
utils::pmr::unordered_map<VertexAccessor, std::optional<EdgeAccessor>> processed_;
|
||||
// edge, vertex we have yet to visit, for current and next depth and their accumulated paths
|
||||
utils::pmr::vector<std::tuple<EdgeAccessor, VertexAccessor, std::optional<Path>>> to_visit_next_;
|
||||
utils::pmr::vector<std::tuple<EdgeAccessor, VertexAccessor, std::optional<Path>>> to_visit_current_;
|
||||
// edge/vertex pairs we have yet to visit, for current and next depth
|
||||
utils::pmr::vector<std::pair<EdgeAccessor, VertexAccessor>> to_visit_current_;
|
||||
utils::pmr::vector<std::pair<EdgeAccessor, VertexAccessor>> to_visit_next_;
|
||||
};
|
||||
|
||||
namespace {
|
||||
@@ -1792,7 +1768,6 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
|
||||
ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.db_accessor,
|
||||
storage::View::OLD);
|
||||
|
||||
auto create_state = [this](const VertexAccessor &vertex, int64_t depth) {
|
||||
return std::make_pair(vertex, upper_bound_set_ ? depth : 0);
|
||||
};
|
||||
@@ -1816,7 +1791,6 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
frame[self_.weight_lambda_->inner_node_symbol] = vertex;
|
||||
TypedValue next_weight = CalculateNextWeight(self_.weight_lambda_, total_weight, evaluator);
|
||||
|
||||
std::optional<Path> curr_acc_path = std::nullopt;
|
||||
if (self_.filter_lambda_.expression) {
|
||||
frame[self_.filter_lambda_.inner_edge_symbol] = edge;
|
||||
frame[self_.filter_lambda_.inner_node_symbol] = vertex;
|
||||
@@ -1826,7 +1800,6 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
Path &accumulated_path = frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath();
|
||||
accumulated_path.Expand(edge);
|
||||
accumulated_path.Expand(vertex);
|
||||
curr_acc_path = accumulated_path;
|
||||
|
||||
if (self_.filter_lambda_.accumulated_weight_symbol) {
|
||||
frame[self_.filter_lambda_.accumulated_weight_symbol.value()] = next_weight;
|
||||
@@ -1842,32 +1815,24 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
if (found_it != total_cost_.end() && (found_it->second.IsNull() || (found_it->second <= next_weight).ValueBool()))
|
||||
return;
|
||||
|
||||
pq_.emplace(next_weight, depth + 1, vertex, edge, curr_acc_path);
|
||||
};
|
||||
|
||||
auto restore_frame_state_after_expansion = [this, &frame]() {
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath().Shrink();
|
||||
}
|
||||
pq_.emplace(next_weight, depth + 1, vertex, edge);
|
||||
};
|
||||
|
||||
// Populates the priority queue structure with expansions
|
||||
// from the given vertex. skips expansions that don't satisfy
|
||||
// the "where" condition.
|
||||
auto expand_from_vertex = [this, &expand_pair, &restore_frame_state_after_expansion](
|
||||
const VertexAccessor &vertex, const TypedValue &weight, int64_t depth) {
|
||||
auto expand_from_vertex = [this, &expand_pair](const VertexAccessor &vertex, const TypedValue &weight,
|
||||
int64_t depth) {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::IN) {
|
||||
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types)).edges;
|
||||
for (const auto &edge : out_edges) {
|
||||
expand_pair(edge, edge.To(), weight, depth);
|
||||
restore_frame_state_after_expansion();
|
||||
}
|
||||
}
|
||||
if (self_.common_.direction != EdgeAtom::Direction::OUT) {
|
||||
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types)).edges;
|
||||
for (const auto &edge : in_edges) {
|
||||
expand_pair(edge, edge.From(), weight, depth);
|
||||
restore_frame_state_after_expansion();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1885,12 +1850,9 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
// Skip expansion for such nodes.
|
||||
if (node.IsNull()) continue;
|
||||
}
|
||||
|
||||
std::optional<Path> curr_acc_path;
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
// Add initial vertex of path to the accumulated path
|
||||
curr_acc_path = Path(vertex);
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()] = curr_acc_path.value();
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()] = Path(vertex);
|
||||
}
|
||||
if (self_.upper_bound_) {
|
||||
upper_bound_ = EvaluateInt(&evaluator, self_.upper_bound_, "Max depth in weighted shortest path expansion");
|
||||
@@ -1914,7 +1876,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
total_cost_.clear();
|
||||
yielded_vertices_.clear();
|
||||
|
||||
pq_.emplace(current_weight, 0, vertex, std::nullopt, curr_acc_path);
|
||||
pq_.emplace(current_weight, 0, vertex, std::nullopt);
|
||||
// We are adding the starting vertex to the set of yielded vertices
|
||||
// because we don't want to yield paths that end with the starting
|
||||
// vertex.
|
||||
@@ -1923,7 +1885,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
|
||||
while (!pq_.empty()) {
|
||||
AbortCheck(context);
|
||||
auto [current_weight, current_depth, current_vertex, current_edge, curr_acc_path] = pq_.top();
|
||||
auto [current_weight, current_depth, current_vertex, current_edge] = pq_.top();
|
||||
pq_.pop();
|
||||
|
||||
auto current_state = create_state(current_vertex, current_depth);
|
||||
@@ -1936,12 +1898,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
total_cost_.emplace(current_state, current_weight);
|
||||
|
||||
// Expand only if what we've just expanded is less than max depth.
|
||||
if (current_depth < upper_bound_) {
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()] = std::move(curr_acc_path.value());
|
||||
}
|
||||
expand_from_vertex(current_vertex, current_weight, current_depth);
|
||||
}
|
||||
if (current_depth < upper_bound_) expand_from_vertex(current_vertex, current_weight, current_depth);
|
||||
|
||||
// If we yielded a path for a vertex already, make the expansion but
|
||||
// don't return the path again.
|
||||
@@ -1964,12 +1921,12 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
// Place destination node on the frame, handle existence flag.
|
||||
if (self_.common_.existing_node) {
|
||||
const auto &node = frame[self_.common_.node_symbol];
|
||||
if ((node != TypedValue(current_vertex, pull_memory)).ValueBool()) {
|
||||
if ((node != TypedValue(current_vertex, pull_memory)).ValueBool())
|
||||
continue;
|
||||
}
|
||||
// Prevent expanding other paths, because we found the
|
||||
// shortest to existing node.
|
||||
ClearQueue();
|
||||
else
|
||||
// Prevent expanding other paths, because we found the
|
||||
// shortest to existing node.
|
||||
ClearQueue();
|
||||
} else {
|
||||
frame[self_.common_.node_symbol] = current_vertex;
|
||||
}
|
||||
@@ -2022,9 +1979,8 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
// Priority queue comparator. Keep lowest weight on top of the queue.
|
||||
class PriorityQueueComparator {
|
||||
public:
|
||||
bool operator()(
|
||||
const std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>, std::optional<Path>> &lhs,
|
||||
const std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>, std::optional<Path>> &rhs) {
|
||||
bool operator()(const std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>> &lhs,
|
||||
const std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>> &rhs) {
|
||||
const auto &lhs_weight = std::get<0>(lhs);
|
||||
const auto &rhs_weight = std::get<0>(rhs);
|
||||
// Null defines minimum value for all types
|
||||
@@ -2041,9 +1997,8 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
}
|
||||
};
|
||||
|
||||
std::priority_queue<std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>, std::optional<Path>>,
|
||||
utils::pmr::vector<std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>,
|
||||
std::optional<Path>>>,
|
||||
std::priority_queue<std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>>,
|
||||
utils::pmr::vector<std::tuple<TypedValue, int64_t, VertexAccessor, std::optional<EdgeAccessor>>>,
|
||||
PriorityQueueComparator>
|
||||
pq_;
|
||||
|
||||
@@ -2069,9 +2024,6 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
|
||||
ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.db_accessor,
|
||||
storage::View::OLD);
|
||||
|
||||
auto *memory = context.evaluation_context.memory;
|
||||
|
||||
auto create_state = [this](const VertexAccessor &vertex, int64_t depth) {
|
||||
return std::make_pair(vertex, upper_bound_set_ ? depth : 0);
|
||||
};
|
||||
@@ -2089,7 +2041,6 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
TypedValue next_weight = CalculateNextWeight(self_.weight_lambda_, total_weight, evaluator);
|
||||
|
||||
// If filter expression exists, evaluate filter
|
||||
std::optional<Path> curr_acc_path = std::nullopt;
|
||||
if (self_.filter_lambda_.expression) {
|
||||
frame[self_.filter_lambda_.inner_edge_symbol] = edge;
|
||||
frame[self_.filter_lambda_.inner_node_symbol] = next_vertex;
|
||||
@@ -2099,7 +2050,6 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
Path &accumulated_path = frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath();
|
||||
accumulated_path.Expand(edge);
|
||||
accumulated_path.Expand(next_vertex);
|
||||
curr_acc_path = accumulated_path;
|
||||
|
||||
if (self_.filter_lambda_.accumulated_weight_symbol) {
|
||||
frame[self_.filter_lambda_.accumulated_weight_symbol.value()] = next_weight;
|
||||
@@ -2126,20 +2076,14 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
}
|
||||
|
||||
DirectedEdge directed_edge = {edge, direction, next_weight};
|
||||
pq_.emplace(next_weight, depth + 1, next_vertex, directed_edge, curr_acc_path);
|
||||
};
|
||||
|
||||
auto restore_frame_state_after_expansion = [this, &frame]() {
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()].ValuePath().Shrink();
|
||||
}
|
||||
pq_.emplace(next_weight, depth + 1, next_vertex, directed_edge);
|
||||
};
|
||||
|
||||
// Populates the priority queue structure with expansions
|
||||
// from the given vertex. skips expansions that don't satisfy
|
||||
// the "where" condition.
|
||||
auto expand_from_vertex = [this, &expand_vertex, &context, &restore_frame_state_after_expansion](
|
||||
const VertexAccessor &vertex, const TypedValue &weight, int64_t depth) {
|
||||
auto expand_from_vertex = [this, &expand_vertex, &context](const VertexAccessor &vertex, const TypedValue &weight,
|
||||
int64_t depth) {
|
||||
if (self_.common_.direction != EdgeAtom::Direction::IN) {
|
||||
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types)).edges;
|
||||
for (const auto &edge : out_edges) {
|
||||
@@ -2152,7 +2096,6 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
}
|
||||
#endif
|
||||
expand_vertex(edge, EdgeAtom::Direction::OUT, weight, depth);
|
||||
restore_frame_state_after_expansion();
|
||||
}
|
||||
}
|
||||
if (self_.common_.direction != EdgeAtom::Direction::OUT) {
|
||||
@@ -2167,12 +2110,12 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
}
|
||||
#endif
|
||||
expand_vertex(edge, EdgeAtom::Direction::IN, weight, depth);
|
||||
restore_frame_state_after_expansion();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::optional<VertexAccessor> start_vertex;
|
||||
auto *memory = context.evaluation_context.memory;
|
||||
|
||||
auto create_path = [this, &frame, &memory]() {
|
||||
auto ¤t_level = traversal_stack_.back();
|
||||
@@ -2224,11 +2167,11 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
return true;
|
||||
};
|
||||
|
||||
auto create_DFS_traversal_tree = [this, &context, &memory, &frame, &create_state, &expand_from_vertex]() {
|
||||
auto create_DFS_traversal_tree = [this, &context, &memory, &create_state, &expand_from_vertex]() {
|
||||
while (!pq_.empty()) {
|
||||
AbortCheck(context);
|
||||
|
||||
auto [current_weight, current_depth, current_vertex, directed_edge, acc_path] = pq_.top();
|
||||
const auto [current_weight, current_depth, current_vertex, directed_edge] = pq_.top();
|
||||
pq_.pop();
|
||||
|
||||
const auto &[current_edge, direction, weight] = directed_edge;
|
||||
@@ -2240,10 +2183,6 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
} else {
|
||||
total_cost_.emplace(current_state, current_weight);
|
||||
if (current_depth < upper_bound_) {
|
||||
if (self_.filter_lambda_.accumulated_path_symbol) {
|
||||
DMG_ASSERT(acc_path.has_value(), "Path must be already filled in AllShortestPath DFS traversals");
|
||||
frame[self_.filter_lambda_.accumulated_path_symbol.value()] = std::move(acc_path.value());
|
||||
}
|
||||
expand_from_vertex(current_vertex, current_weight, current_depth);
|
||||
}
|
||||
}
|
||||
@@ -2376,8 +2315,8 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
// Priority queue comparator. Keep lowest weight on top of the queue.
|
||||
class PriorityQueueComparator {
|
||||
public:
|
||||
bool operator()(const std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge, std::optional<Path>> &lhs,
|
||||
const std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge, std::optional<Path>> &rhs) {
|
||||
bool operator()(const std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge> &lhs,
|
||||
const std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge> &rhs) {
|
||||
const auto &lhs_weight = std::get<0>(lhs);
|
||||
const auto &rhs_weight = std::get<0>(rhs);
|
||||
// Null defines minimum value for all types
|
||||
@@ -2396,10 +2335,9 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
|
||||
|
||||
// Priority queue - core element of the algorithm.
|
||||
// Stores: {weight, depth, next vertex, edge and direction}
|
||||
std::priority_queue<
|
||||
std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge, std::optional<Path>>,
|
||||
utils::pmr::vector<std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge, std::optional<Path>>>,
|
||||
PriorityQueueComparator>
|
||||
std::priority_queue<std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge>,
|
||||
utils::pmr::vector<std::tuple<TypedValue, int64_t, VertexAccessor, DirectedEdge>>,
|
||||
PriorityQueueComparator>
|
||||
pq_;
|
||||
|
||||
void ClearQueue() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -868,10 +868,7 @@ py::Object MgpListToPyTuple(mgp_list *list, PyObject *py_graph) {
|
||||
}
|
||||
|
||||
void PyCollectGarbage() {
|
||||
// NOTE: No need to call _Py_IsFinalizing(), we ensure
|
||||
// Python GC thread is stopped before Py_Finalize() is called
|
||||
// in memgraph.cpp
|
||||
if (!Py_IsInitialized()) {
|
||||
if (!Py_IsInitialized() || _Py_IsFinalizing()) {
|
||||
// Calling EnsureGIL will crash the program if this is true.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -762,16 +762,6 @@ Feature: Match
|
||||
| path |
|
||||
| <(:label1 {id: 1})-[:type2 {id: 10}]->(:label3 {id: 3})> |
|
||||
|
||||
Scenario: Test DFS variable expand using IN edges with filter by edge type1
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
"""
|
||||
MATCH path=(:label3)<-[* (e, n, p | NOT(type(e)='type1' AND type(last(relationships(p))) = 'type1'))]-(:label1) RETURN path;
|
||||
"""
|
||||
Then the result should be:
|
||||
| path |
|
||||
| <(:label3 {id: 3})<-[:type2 {id: 10}]-(:label1 {id: 1})> |
|
||||
|
||||
Scenario: Test DFS variable expand with filter by edge type2
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
@@ -782,16 +772,6 @@ Feature: Match
|
||||
| path |
|
||||
| <(:label1 {id: 1})-[:type1 {id: 1}]->(:label2 {id: 2})-[:type1 {id: 2}]->(:label3 {id: 3})> |
|
||||
|
||||
Scenario: Test DFS variable expand using IN edges with filter by edge type2
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
"""
|
||||
MATCH path=(:label3)<-[* (e, n, p | NOT(type(e)='type2' AND type(last(relationships(p))) = 'type2'))]-(:label1) RETURN path;
|
||||
"""
|
||||
Then the result should be:
|
||||
| path |
|
||||
| <(:label3 {id: 3})<-[:type1 {id: 2}]-(:label2 {id: 2})<-[:type1 {id: 1}]-(:label1 {id: 1})> |
|
||||
|
||||
Scenario: Using path indentifier from CREATE in MERGE
|
||||
Given an empty graph
|
||||
And having executed:
|
||||
|
||||
@@ -205,7 +205,11 @@ Feature: All Shortest Path
|
||||
| 20.3 |
|
||||
|
||||
Scenario: Test match AllShortest with accumulated path filtered by order of ids
|
||||
Given graph "graph_edges"
|
||||
Given an empty graph
|
||||
And having executed:
|
||||
"""
|
||||
CREATE (:label1 {id: 1})-[:type1 {id:1}]->(:label2 {id: 2})-[:type1 {id: 2}]->(:label3 {id: 3})-[:type1 {id: 3}]->(:label4 {id: 4});
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH pth=(:label1)-[*ALLSHORTEST (r, n | r.id) total_weight (e,n,p | e.id > 0 and (nodes(p)[-1]).id > (nodes(p)[-2]).id)]->(:label4) RETURN pth, total_weight;
|
||||
@@ -214,16 +218,6 @@ Feature: All Shortest Path
|
||||
| pth | total_weight |
|
||||
| <(:label1{id:1})-[:type1{id:1}]->(:label2{id:2})-[:type1{id:2}]->(:label3{id:3})-[:type1{id:3}]->(:label4{id:4})> | 6 |
|
||||
|
||||
Scenario: Test match AllShortest using IN edges with accumulated path filtered by order of ids
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
"""
|
||||
MATCH pth=(:label4)<-[*ALLSHORTEST (r, n | r.id) total_weight (e,n,p | e.id > 0 and (nodes(p)[-1]).id < (nodes(p)[-2]).id)]-(:label1) RETURN pth, total_weight;
|
||||
"""
|
||||
Then the result should be:
|
||||
| pth | total_weight |
|
||||
| <(:label4{id:4})<-[:type1{id:3}]-(:label3{id:3})<-[:type1{id:2}]-(:label2{id:2})<-[:type1{id:1}]-(:label1{id:1})> | 6 |
|
||||
|
||||
Scenario: Test match AllShortest with accumulated path filtered by edge type1
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
|
||||
@@ -136,42 +136,6 @@ Feature: Bfs
|
||||
| pth |
|
||||
| <(:label1{id:1})-[:type1{id:1}]->(:label2{id:2})-[:type1{id:2}]->(:label3{id:3})> |
|
||||
|
||||
Scenario: Test BFS variable expand using IN edges with filter by last edge type of accumulated path
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
"""
|
||||
MATCH pth=(:label3)<-[*BFS (e,n,p | type(relationships(p)[-1]) = 'type1')]-(:label1) return pth;
|
||||
"""
|
||||
Then the result should be:
|
||||
| pth |
|
||||
| <(:label3 {id: 3})<-[:type1 {id: 2}]-(:label2 {id: 2})<-[:type1 {id: 1}]-(:label1 {id: 1})> |
|
||||
|
||||
Scenario: Test BFS variable expand using IN edges with filter by number of vertices in the accumulated path
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
"""
|
||||
MATCH p=(n)<-[*BFS (r, n, p | size(nodes(p)) > 0)]-(m {id:1}) return p;
|
||||
"""
|
||||
Then the result should be:
|
||||
| p |
|
||||
| <(:label2 {id: 2})<-[:type1 {id: 1}]-(:label1 {id: 1})> |
|
||||
| <(:label3 {id: 3})<-[:type2 {id: 10}]-(:label1 {id: 1})> |
|
||||
| <(:label4 {id: 4})<-[:type1 {id: 3}]-(:label3 {id: 3})<-[:type2 {id: 10}]-(:label1 {id: 1})> |
|
||||
| <(:label5 {id: 5})<-[:type3 {id: 20}]-(:label1 {id: 1})> |
|
||||
|
||||
Scenario: Test BFS variable expand using IN edges with filter by id of vertices but accumulated path is not used
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
"""
|
||||
MATCH p=(n)<-[*BFS (r, n, p | r.id > 0)]-(m {id:1}) return p;
|
||||
"""
|
||||
Then the result should be:
|
||||
| p |
|
||||
| <(:label2 {id: 2})<-[:type1 {id: 1}]-(:label1 {id: 1})> |
|
||||
| <(:label3 {id: 3})<-[:type2 {id: 10}]-(:label1 {id: 1})> |
|
||||
| <(:label4 {id: 4})<-[:type1 {id: 3}]-(:label3 {id: 3})<-[:type2 {id: 10}]-(:label1 {id: 1})> |
|
||||
| <(:label5 {id: 5})<-[:type3 {id: 20}]-(:label1 {id: 1})> |
|
||||
|
||||
Scenario: Test BFS variable expand with restict filter by last edge type of accumulated path
|
||||
Given an empty graph
|
||||
And having executed:
|
||||
|
||||
@@ -170,20 +170,6 @@ Feature: Weighted Shortest Path
|
||||
| pth | total_weight |
|
||||
| <(:label1{id:1})-[:type1{id:1}]->(:label2{id:2})-[:type1{id:2}]->(:label3{id:3})-[:type1{id:3}]->(:label4{id:4})> | 6 |
|
||||
|
||||
Scenario: Test match wShortest using IN edges with accumulated path filtered by order of ids
|
||||
Given an empty graph
|
||||
And having executed:
|
||||
"""
|
||||
CREATE (:label1 {id: 1})-[:type1 {id:1}]->(:label2 {id: 2})-[:type1 {id: 2}]->(:label3 {id: 3})-[:type1 {id: 3}]->(:label4 {id: 4});
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH pth=(:label4)<-[*WSHORTEST (r, n | r.id) total_weight (e,n,p | e.id > 0 and (nodes(p)[-1]).id < (nodes(p)[-2]).id)]-(:label1) RETURN pth, total_weight;
|
||||
"""
|
||||
Then the result should be:
|
||||
| pth | total_weight |
|
||||
| <(:label4{id:4})<-[:type1{id:3}]-(:label3{id:3})<-[:type1{id:2}]-(:label2{id:2})<-[:type1{id:1}]-(:label1{id:1})> | 6 |
|
||||
|
||||
Scenario: Test match wShortest with accumulated path filtered by edge type1
|
||||
Given graph "graph_edges"
|
||||
When executing query:
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CREATE (:label1 {id: 1})-[:type1 {id:1}]->(:label2 {id: 2})-[:type1 {id: 2}]->(:label3 {id: 3})-[:type1 {id: 3}]->(:label4 {id: 4});
|
||||
MATCH (n :label1), (m :label3) CREATE (n)-[:type2 {id: 10}]->(m);
|
||||
MATCH (n :label1) CREATE (n)-[:type3 {id: 20}]->(:label5 { id: 5 });
|
||||
|
||||
@@ -24,7 +24,7 @@ PRINT_CONTEXT() {
|
||||
|
||||
HELP_EXIT() {
|
||||
echo ""
|
||||
echo "HELP: $0 help|cluster-up|cluster-refresh|cluster-cleanup|cluster-dealloc|mgbuild|test|test-all-individually [args]"
|
||||
echo "HELP: $0 help|cluster-up|cluster-cleanup|cluster-dealloc|mgbuild|test|test-all-individually [args]"
|
||||
echo ""
|
||||
echo " test args --binary MEMGRAPH_BINARY_PATH"
|
||||
echo " --ignore-run-stdout-logs Ignore lein run stdout logs."
|
||||
@@ -184,37 +184,6 @@ PROCESS_RESULTS() {
|
||||
INFO "Result processing (printing and packing) DONE."
|
||||
}
|
||||
|
||||
CLUSTER_UP() {
|
||||
PRINT_CONTEXT
|
||||
"$script_dir/jepsen/docker/bin/up" --daemon
|
||||
sleep 10
|
||||
# Ensure all SSH connections between Jepsen containers work
|
||||
for node in $(docker ps --filter name=jepsen* --filter status=running --format "{{.Names}}"); do
|
||||
if [ "$node" == "jepsen-control" ]; then
|
||||
continue
|
||||
fi
|
||||
node_hostname="${node##jepsen-}"
|
||||
docker exec jepsen-control bash -c "ssh -oStrictHostKeyChecking=no -t $node_hostname exit"
|
||||
done
|
||||
}
|
||||
|
||||
CLUSTER_DEALLOC() {
|
||||
ps=$(docker ps --filter name=jepsen* --filter status=running -q)
|
||||
if [[ ! -z ${ps} ]]; then
|
||||
echo "Killing ${ps}"
|
||||
docker rm -f ${ps}
|
||||
imgs=$(docker images "jepsen*" -q)
|
||||
if [[ ! -z ${imgs} ]]; then
|
||||
echo "Removing ${imgs}"
|
||||
docker images "jepsen*" -q | xargs docker image rmi -f
|
||||
else
|
||||
echo "No Jepsen images detected!"
|
||||
fi
|
||||
else
|
||||
echo "No Jepsen containers detected!"
|
||||
fi
|
||||
}
|
||||
|
||||
# Initialize testing context by copying source/binary files. Inside CI,
|
||||
# Memgraph is tested on a single machine cluster based on Docker containers.
|
||||
# Once these tests will be part of the official Jepsen repo, the majority of
|
||||
@@ -227,16 +196,8 @@ case $1 in
|
||||
# the current cluster is broken because it relies on the folder. That can
|
||||
# happen easiliy because the jepsen folder is git ignored.
|
||||
cluster-up)
|
||||
CLUSTER_UP
|
||||
;;
|
||||
|
||||
cluster-refresh)
|
||||
CLUSTER_DEALLOC
|
||||
CLUSTER_UP
|
||||
;;
|
||||
|
||||
cluster-dealloc)
|
||||
CLUSTER_DEALLOC
|
||||
PRINT_CONTEXT
|
||||
"$script_dir/jepsen/docker/bin/up" --daemon
|
||||
;;
|
||||
|
||||
cluster-cleanup)
|
||||
@@ -251,6 +212,23 @@ case $1 in
|
||||
done
|
||||
;;
|
||||
|
||||
cluster-dealloc)
|
||||
ps=$(docker ps --filter name=jepsen* --filter status=running -q)
|
||||
if [[ ! -z ${ps} ]]; then
|
||||
echo "Killing ${ps}"
|
||||
docker rm -f ${ps}
|
||||
imgs=$(docker images "jepsen*" -q)
|
||||
if [[ ! -z ${imgs} ]]; then
|
||||
echo "Removing ${imgs}"
|
||||
docker images "jepsen*" -q | xargs docker image rmi -f
|
||||
else
|
||||
echo "No Jepsen images detected!"
|
||||
fi
|
||||
else
|
||||
echo "No Jepsen containers detected!"
|
||||
fi
|
||||
;;
|
||||
|
||||
mgbuild)
|
||||
PRINT_CONTEXT
|
||||
echo ""
|
||||
|
||||
46
tests/mgbench/workloads/order_by.py
Normal file
46
tests/mgbench/workloads/order_by.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# Copyright 2023 Memgraph Ltd.
|
||||
#
|
||||
# Use of this software is governed by the Business Source License
|
||||
# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
# License, and you may not use this file except in compliance with the Business Source License.
|
||||
#
|
||||
# As of the Change Date specified in that file, in accordance with
|
||||
# the Business Source License, use of this software will be governed
|
||||
# by the Apache License, Version 2.0, included in the file
|
||||
# licenses/APL.txt.
|
||||
|
||||
from workloads.base import Workload
|
||||
|
||||
|
||||
class OrderBy(Workload):
|
||||
NAME = "order_by"
|
||||
CARDINALITY = 10000
|
||||
|
||||
def indexes_generator(self):
|
||||
return [
|
||||
("CREATE INDEX ON :Node;", {}),
|
||||
("CREATE INDEX ON :Node(prop1);", {}),
|
||||
("CREATE INDEX ON :Node(prop2);", {}),
|
||||
("CREATE INDEX ON :Node(prop3);", {}),
|
||||
]
|
||||
|
||||
def dataset_generator(self):
|
||||
queries = []
|
||||
for i in range(0, OrderBy.CARDINALITY):
|
||||
queries.append(
|
||||
(
|
||||
"""CREATE
|
||||
(:Node {prop1: $id, prop2: $id, prop3: $id
|
||||
});
|
||||
""",
|
||||
{"id": i},
|
||||
)
|
||||
)
|
||||
|
||||
return queries
|
||||
|
||||
def benchmark__test__order_by(self):
|
||||
return (
|
||||
"MATCH (n:Node) RETURN n ORDER BY n.prop1",
|
||||
{},
|
||||
)
|
||||
Reference in New Issue
Block a user