Merge branch 'master' into Implement-constant-time-label-and-edge-type-retrieval

This commit is contained in:
gvolfing
2023-12-04 08:00:02 +01:00
18 changed files with 324 additions and 37 deletions

View File

@@ -71,8 +71,10 @@ add_subdirectory(index_hints)
add_subdirectory(query_modules)
add_subdirectory(constraints)
add_subdirectory(inspect_query)
add_subdirectory(filter_info)
add_subdirectory(queries)
add_subdirectory(garbage_collection)
add_subdirectory(query_planning)
copy_e2e_python_files(pytest_runner pytest_runner.sh "")
copy_e2e_python_files(x x.sh "")

View File

@@ -62,7 +62,7 @@ def test_analyze_graph_delete_statistics(delete_query, multi_db):
# After deleting statistics, id2 should be chosen because it has less vertices
expected_explain_after_delete_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id1}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id2}})",),
(f" * Once",),
]
@@ -96,7 +96,7 @@ def test_analyze_full_graph(analyze_query, multi_db):
# Choose id2 before tha analysis because it has less vertices
expected_explain_before_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id1}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id2}})",),
(f" * Once",),
]
@@ -117,7 +117,7 @@ def test_analyze_full_graph(analyze_query, multi_db):
# After analyzing graph, id1 index should be chosen because it has smaller average group size
expected_explain_after_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id2}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id1}})",),
(f" * Once",),
]
@@ -152,7 +152,7 @@ def test_cardinality_different_avg_group_size_uniform_dist(multi_db):
assert analyze_graph_results[1 - first_index] == ("Label", "id2", 100, 20, 5, 0, 0)
expected_explain_after_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id2}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id1}})",),
(f" * Once",),
]
@@ -183,7 +183,7 @@ def test_cardinality_same_avg_group_size_uniform_dist_diff_vertex_count(multi_db
assert analyze_graph_results[1 - first_index] == ("Label", "id2", 50, 50, 1, 0, 0)
expected_explain_after_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id1}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id2}})",),
(f" * Once",),
]
@@ -214,7 +214,7 @@ def test_large_diff_in_num_vertices_v1(multi_db):
assert analyze_graph_results[1 - first_index] == ("Label", "id2", 99, 1, 99, 0, 0)
expected_explain_after_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id1}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id2}})",),
(f" * Once",),
]
@@ -245,7 +245,7 @@ def test_large_diff_in_num_vertices_v2(multi_db):
assert analyze_graph_results[1 - first_index] == ("Label", "id2", 1000, 1000, 1, 0, 0)
expected_explain_after_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id2}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id1}})",),
(f" * Once",),
]
@@ -286,7 +286,7 @@ def test_same_avg_group_size_diff_distribution(multi_db):
assert analyze_graph_results[1 - first_index] == ("Label", "id2", 100, 5, 20, 0, 0)
expected_explain_after_analysis = [
(f" * Produce {{n}}",),
(f" * Filter (n :Label), {{n.id1}}, {{n.id2}}",),
(f" * Filter {{n.id1}}",),
(f" * ScanAllByLabelPropertyValue (n :Label {{id2}})",),
(f" * Once",),
]

View File

@@ -0,0 +1,6 @@
function(copy_filter_info_e2e_python_files FILE_NAME)
copy_e2e_python_files(filter_info ${FILE_NAME})
endfunction()
copy_filter_info_e2e_python_files(common.py)
copy_filter_info_e2e_python_files(filter_info.py)

View File

@@ -0,0 +1,23 @@
# 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.
import pytest
from gqlalchemy import Memgraph
@pytest.fixture
def memgraph(**kwargs) -> Memgraph:
memgraph = Memgraph()
yield memgraph
memgraph.drop_database()
memgraph.drop_indexes()

View File

@@ -0,0 +1,39 @@
# 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.
import sys
import pytest
from common import memgraph
def test_label_index_hint(memgraph):
memgraph.execute("CREATE (n:Label1:Label2 {prop: 1});")
memgraph.execute("CREATE INDEX ON :Label1;")
# TODO: Fix this test since it should only filter on :Label2 and prop
expected_explain = [
" * Produce {n}",
" * Filter (n :Label1:Label2), {n.prop}",
" * ScanAllByLabel (n :Label1)",
" * Once",
]
actual_explain = [
row["QUERY PLAN"]
for row in memgraph.execute_and_fetch("EXPLAIN MATCH (n:Label1:Label2) WHERE n.prop = 1 return n;")
]
assert expected_explain == actual_explain
if __name__ == "__main__":
sys.exit(pytest.main([__file__, "-rA"]))

View File

@@ -0,0 +1,13 @@
filter_info_cluster: &filter_info_cluster
cluster:
main:
args: ["--bolt-port", "7687", "--log-level=TRACE"]
log_file: "filter_info.log"
setup_queries: []
validation_queries: []
workloads:
- name: "Filter info information"
binary: "tests/e2e/pytest_runner.sh"
args: ["filter_info/filter_info.py"]
<<: *filter_info_cluster

View File

@@ -162,12 +162,13 @@ def test_label_property_index_hint(memgraph):
expected_explain_no_hint = [
" * Produce {n}",
" * Filter (n :Label), {n.id1}, {n.id2}",
" * Filter {n.id1}",
" * ScanAllByLabelPropertyValue (n :Label {id2})",
" * Once",
]
expected_explain_with_hint = [
row.replace("(n :Label {id2})", "(n :Label {id1})") for row in expected_explain_no_hint
row.replace("(n :Label {id2})", "(n :Label {id1})").replace(" * Filter {n.id1}", " * Filter {n.id2}")
for row in expected_explain_no_hint
]
explain_no_hint = [
@@ -192,7 +193,7 @@ def test_label_property_index_hint_alternative_orderings(memgraph):
expected_explain_with_hint = [
" * Produce {n}",
" * Filter (n :Label), {n.id1}, {n.id2}",
" * Filter {n.id2}",
" * ScanAllByLabelPropertyValue (n :Label {id1})",
" * Once",
]
@@ -221,7 +222,7 @@ def test_multiple_label_property_index_hints(memgraph):
expected_explain_with_hint = [
" * Produce {n}",
" * Filter (n :Label), {n.id1}, {n.id2}",
" * Filter {n.id2}",
" * ScanAllByLabelPropertyValue (n :Label {id1})",
" * Once",
]
@@ -251,7 +252,7 @@ def test_multiple_applicable_label_property_index_hints(memgraph):
expected_explain_with_hint = [
" * Produce {n}",
" * Filter (n :Label), {n.id1}, {n.id2}",
" * Filter {n.id2}",
" * ScanAllByLabelPropertyValue (n :Label {id1})",
" * Once",
]
@@ -275,12 +276,13 @@ def test_multiple_applicable_label_property_index_hints_alternative_orderings(me
expected_explain_with_hint_1 = [
" * Produce {n}",
" * Filter (n :Label), {n.id1}, {n.id2}",
" * Filter {n.id2}",
" * ScanAllByLabelPropertyValue (n :Label {id1})",
" * Once",
]
expected_explain_with_hint_2 = [
row.replace("(n :Label {id1})", "(n :Label {id2})") for row in expected_explain_with_hint_1
row.replace("(n :Label {id1})", "(n :Label {id2})").replace(" * Filter {n.id2}", " * Filter {n.id1}")
for row in expected_explain_with_hint_1
]
explain_with_hint_ordering_1a = [
@@ -407,6 +409,7 @@ def test_multiple_match_query(memgraph):
memgraph.execute("CREATE INDEX ON :Label2;")
memgraph.execute("CREATE INDEX ON :Label3;")
# TODO: Fix this test since it has the filtering info wrong (filtering by label that's already indexed)
expected_explain_with_hint = [
" * Produce {n, m}",
" * Cartesian {m : n}",
@@ -414,7 +417,7 @@ def test_multiple_match_query(memgraph):
" | * Filter (n :Label1:Label2), {n.id}",
" | * ScanAllByLabel (n :Label1)",
" | * Once",
" * Filter (m :Label2:Label3), (n :Label1:Label2), {n.id}",
" * Filter (m :Label2:Label3)",
" * ScanAllByLabel (m :Label2)",
" * Once",
]

View File

@@ -0,0 +1,6 @@
function(copy_query_planning_e2e_python_files FILE_NAME)
copy_e2e_python_files(query_planning ${FILE_NAME})
endfunction()
copy_query_planning_e2e_python_files(common.py)
copy_query_planning_e2e_python_files(query_planning_cartesian.py)

View File

@@ -0,0 +1,24 @@
# 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.
import pytest
from gqlalchemy import Memgraph
@pytest.fixture
def memgraph(**kwargs) -> Memgraph:
memgraph = Memgraph()
yield memgraph
memgraph.drop_indexes()
memgraph.ensure_constraints([])
memgraph.drop_database()

View File

@@ -0,0 +1,42 @@
# 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.
import sys
import pytest
from common import memgraph
QUERY_PLAN = "QUERY PLAN"
def test_indexed_join_with_indices(memgraph):
memgraph.execute("CREATE INDEX ON :Node(id);")
expected_explain = [
f" * Produce {{a, b, r}}",
f" * Filter (a :Node), {{a.id}}",
f" * Expand (b)-[r:EDGE]-(a)",
f" * ScanAllByLabelPropertyValue (b :Node {{id}})",
f" * Once",
]
results = list(
memgraph.execute_and_fetch(
"EXPLAIN MATCH (a:Node {id: 1}) MATCH (b:Node {id: 2}) MATCH (a)-[r:EDGE]-(b) return a,b,r;"
)
)
actual_explain = [x[QUERY_PLAN] for x in results]
assert expected_explain == actual_explain
if __name__ == "__main__":
sys.exit(pytest.main([__file__, "-rA"]))

View File

@@ -0,0 +1,14 @@
queries_cluster: &queries_cluster
cluster:
main:
args: ["--bolt-port", "7687", "--log-level=TRACE"]
log_file: "query_planning.log"
setup_queries: []
validation_queries: []
workloads:
- name: "Query planning cartesian"
binary: "tests/e2e/pytest_runner.sh"
args: ["query_planning/query_planning_cartesian.py"]
<<: *queries_cluster