From bd9262f38312b7494d0b3ebc3d1f8382f77b650b Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Sun, 7 Jan 2024 01:41:42 +1100 Subject: [PATCH 1/4] Create a nocase index for use with the LIKE queries --- rope/contrib/autoimport/models.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/rope/contrib/autoimport/models.py b/rope/contrib/autoimport/models.py index 817a51ae7..fc310592f 100644 --- a/rope/contrib/autoimport/models.py +++ b/rope/contrib/autoimport/models.py @@ -100,9 +100,14 @@ class Name(Model): @classmethod def create_table(cls, connection): super().create_table(connection) - connection.execute("CREATE INDEX IF NOT EXISTS name ON names(name)") - connection.execute("CREATE INDEX IF NOT EXISTS module ON names(module)") - connection.execute("CREATE INDEX IF NOT EXISTS package ON names(package)") + # fmt: off + connection.execute("CREATE INDEX IF NOT EXISTS names_name ON names(name)") + connection.execute("CREATE INDEX IF NOT EXISTS names_module ON names(module)") + connection.execute("CREATE INDEX IF NOT EXISTS names_package ON names(package)") + connection.execute("CREATE INDEX IF NOT EXISTS names_name_nocase ON names(name COLLATE NOCASE)") + connection.execute("CREATE INDEX IF NOT EXISTS names_module_nocase ON names(module COLLATE NOCASE)") + connection.execute("CREATE INDEX IF NOT EXISTS names_package_nocase ON names(package COLLATE NOCASE)") + # fmt: on search_submodule_like = objects.where('module LIKE ("%." || ?)') search_module_like = objects.where("module LIKE (?)") From 83fff697e2fafcc49437f2808b9e0c6fe6741ba7 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Sun, 7 Jan 2024 03:59:42 +1100 Subject: [PATCH 2/4] Add test for use of indexes in the queries --- rope/contrib/autoimport/models.py | 3 ++ ropetest/contrib/autoimport/autoimporttest.py | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/rope/contrib/autoimport/models.py b/rope/contrib/autoimport/models.py index fc310592f..d0acdca48 100644 --- a/rope/contrib/autoimport/models.py +++ b/rope/contrib/autoimport/models.py @@ -9,6 +9,9 @@ def __init__(self, query): def __repr__(self): return f'{self.__class__.__name__}("{self._query}")' + def explain(self): + return FinalQuery("EXPLAIN QUERY PLAN " + self._query) + class Query: def __init__(self, query: str, columns: List[str]): diff --git a/ropetest/contrib/autoimport/autoimporttest.py b/ropetest/contrib/autoimport/autoimporttest.py index d8bbd87ee..45f1d5290 100644 --- a/ropetest/contrib/autoimport/autoimporttest.py +++ b/ropetest/contrib/autoimport/autoimporttest.py @@ -186,3 +186,33 @@ def test_setup_db_metadata_table_is_current(autoimport): with assert_database_is_preserved(conn), \ patch("rope.base.versioning.calculate_version_hash", return_value="up-to-date-value"): autoimport._setup_db() + + +class TestQueryUsesIndexes: + def test_search_by_name_uses_index(self, autoimport): + query = models.Name.search_by_name.select_star().explain() + assert ( + list(autoimport._execute(query, ("abc",)))[0][-1] + == "SEARCH names USING INDEX names_name (name=?)" + ) + + def test_search_by_name_like_uses_index(self, autoimport): + query = models.Name.search_by_name_like.select_star().explain() + assert ( + list(autoimport._execute(query, ("abc",)))[0][-1] + == "SEARCH names USING INDEX names_name_nocase (name>? AND name? AND module Date: Sun, 7 Jan 2024 04:51:29 +1100 Subject: [PATCH 3/4] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fbad4fe2..cd0c47c1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - #733 skip directories with perm error when building autoimport index (@MrBago) - #722, #723 Remove site-packages from packages search tree (@tkrabel) - #738 Implement os.PathLike on Resource (@lieryan) +- #739, #736 Ensure autoimport requests uses indexes (@lieryan) # Release 1.11.0 From 59f8a8490271df91aad16bdf1026fa83be10d1a0 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Sun, 7 Jan 2024 05:54:16 +1100 Subject: [PATCH 4/4] Fix test on windows due to differing explain text --- ropetest/contrib/autoimport/autoimporttest.py | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/ropetest/contrib/autoimport/autoimporttest.py b/ropetest/contrib/autoimport/autoimporttest.py index 45f1d5290..072ab1ed8 100644 --- a/ropetest/contrib/autoimport/autoimporttest.py +++ b/ropetest/contrib/autoimport/autoimporttest.py @@ -189,30 +189,36 @@ def test_setup_db_metadata_table_is_current(autoimport): class TestQueryUsesIndexes: + def explain(self, autoimport, query): + explanation = list(autoimport._execute(query.explain(), ("abc",)))[0][-1] + # the explanation text varies, on some sqlite version + explanation = explanation.replace("TABLE ", "") + return explanation + def test_search_by_name_uses_index(self, autoimport): - query = models.Name.search_by_name.select_star().explain() + query = models.Name.search_by_name.select_star() assert ( - list(autoimport._execute(query, ("abc",)))[0][-1] + self.explain(autoimport, query) == "SEARCH names USING INDEX names_name (name=?)" ) def test_search_by_name_like_uses_index(self, autoimport): - query = models.Name.search_by_name_like.select_star().explain() + query = models.Name.search_by_name_like.select_star() assert ( - list(autoimport._execute(query, ("abc",)))[0][-1] + self.explain(autoimport, query) == "SEARCH names USING INDEX names_name_nocase (name>? AND name? AND module