Skip to content

Commit 95585e8

Browse files
authored
Merge pull request #739 from python-rope/fix-autoimport-nocase-index
Ensure autoimport requests uses indexes
2 parents faa0b69 + 59f8a84 commit 95585e8

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- #733 skip directories with perm error when building autoimport index (@MrBago)
44
- #722, #723 Remove site-packages from packages search tree (@tkrabel)
55
- #738 Implement os.PathLike on Resource (@lieryan)
6+
- #739, #736 Ensure autoimport requests uses indexes (@lieryan)
67

78
# Release 1.11.0
89

rope/contrib/autoimport/models.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ def __init__(self, query):
99
def __repr__(self):
1010
return f'{self.__class__.__name__}("{self._query}")'
1111

12+
def explain(self):
13+
return FinalQuery("EXPLAIN QUERY PLAN " + self._query)
14+
1215

1316
class Query:
1417
def __init__(self, query: str, columns: List[str]):
@@ -100,9 +103,14 @@ class Name(Model):
100103
@classmethod
101104
def create_table(cls, connection):
102105
super().create_table(connection)
103-
connection.execute("CREATE INDEX IF NOT EXISTS name ON names(name)")
104-
connection.execute("CREATE INDEX IF NOT EXISTS module ON names(module)")
105-
connection.execute("CREATE INDEX IF NOT EXISTS package ON names(package)")
106+
# fmt: off
107+
connection.execute("CREATE INDEX IF NOT EXISTS names_name ON names(name)")
108+
connection.execute("CREATE INDEX IF NOT EXISTS names_module ON names(module)")
109+
connection.execute("CREATE INDEX IF NOT EXISTS names_package ON names(package)")
110+
connection.execute("CREATE INDEX IF NOT EXISTS names_name_nocase ON names(name COLLATE NOCASE)")
111+
connection.execute("CREATE INDEX IF NOT EXISTS names_module_nocase ON names(module COLLATE NOCASE)")
112+
connection.execute("CREATE INDEX IF NOT EXISTS names_package_nocase ON names(package COLLATE NOCASE)")
113+
# fmt: on
106114

107115
search_submodule_like = objects.where('module LIKE ("%." || ?)')
108116
search_module_like = objects.where("module LIKE (?)")

ropetest/contrib/autoimport/autoimporttest.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,39 @@ def test_setup_db_metadata_table_is_current(autoimport):
186186
with assert_database_is_preserved(conn), \
187187
patch("rope.base.versioning.calculate_version_hash", return_value="up-to-date-value"):
188188
autoimport._setup_db()
189+
190+
191+
class TestQueryUsesIndexes:
192+
def explain(self, autoimport, query):
193+
explanation = list(autoimport._execute(query.explain(), ("abc",)))[0][-1]
194+
# the explanation text varies, on some sqlite version
195+
explanation = explanation.replace("TABLE ", "")
196+
return explanation
197+
198+
def test_search_by_name_uses_index(self, autoimport):
199+
query = models.Name.search_by_name.select_star()
200+
assert (
201+
self.explain(autoimport, query)
202+
== "SEARCH names USING INDEX names_name (name=?)"
203+
)
204+
205+
def test_search_by_name_like_uses_index(self, autoimport):
206+
query = models.Name.search_by_name_like.select_star()
207+
assert (
208+
self.explain(autoimport, query)
209+
== "SEARCH names USING INDEX names_name_nocase (name>? AND name<?)"
210+
)
211+
212+
def test_search_module_like_uses_index(self, autoimport):
213+
query = models.Name.search_module_like.select_star()
214+
assert (
215+
self.explain(autoimport, query)
216+
== "SEARCH names USING INDEX names_module_nocase (module>? AND module<?)"
217+
)
218+
219+
def test_search_submodule_like_uses_index(self, autoimport):
220+
query = models.Name.search_submodule_like.select_star()
221+
assert (
222+
self.explain(autoimport, query)
223+
== "SCAN names" # FIXME: avoid full table scan
224+
)

0 commit comments

Comments
 (0)