Skip to content

Commit

Permalink
Merge pull request #739 from python-rope/fix-autoimport-nocase-index
Browse files Browse the repository at this point in the history
Ensure autoimport requests uses indexes
  • Loading branch information
lieryan authored Jan 6, 2024
2 parents faa0b69 + 59f8a84 commit 95585e8
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 11 additions & 3 deletions rope/contrib/autoimport/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]):
Expand Down Expand Up @@ -100,9 +103,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 (?)")
Expand Down
36 changes: 36 additions & 0 deletions ropetest/contrib/autoimport/autoimporttest.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,39 @@ 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 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()
assert (
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()
assert (
self.explain(autoimport, query)
== "SEARCH names USING INDEX names_name_nocase (name>? AND name<?)"
)

def test_search_module_like_uses_index(self, autoimport):
query = models.Name.search_module_like.select_star()
assert (
self.explain(autoimport, query)
== "SEARCH names USING INDEX names_module_nocase (module>? AND module<?)"
)

def test_search_submodule_like_uses_index(self, autoimport):
query = models.Name.search_submodule_like.select_star()
assert (
self.explain(autoimport, query)
== "SCAN names" # FIXME: avoid full table scan
)

0 comments on commit 95585e8

Please sign in to comment.