diff --git a/docs/table.rst b/docs/table.rst index 80e006a..df060ed 100644 --- a/docs/table.rst +++ b/docs/table.rst @@ -204,3 +204,21 @@ If you insert additional records into the table you will need to refresh the sea "is_good_dog": True, }, pk="id") dogs.populate_fts(["name", "twitter"]) + +Creating indexes +================ + +You can create an index on a table using the ``.create_index(columns)`` method. The method takes a list of columns: + +.. code-block:: python + + dogs.create_index(["is_good_dog"]) + +By default the index will be named ``idx_{table-name}_{columns}`` - if you want to customize the name of the created index you can pass the ``index_name`` parameter::] + +.. code-block:: python + + dogs.create_index( + ["is_good_dog", "age"], + index_name="good_dogs_by_age" + ) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 3f922c0..82f1f93 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -140,6 +140,19 @@ class Table: self.db.create_table(self.name, columns, pk=pk, foreign_keys=foreign_keys) self.exists = True + def create_index(self, columns, index_name=None): + if index_name is None: + index_name = "idx_{}_{}".format( + self.name.replace(" ", "_"), "_".join(columns) + ) + sql = """ + CREATE INDEX {index_name} + ON {table_name} ({columns}); + """.format( + index_name=index_name, table_name=self.name, columns=", ".join(columns) + ) + self.db.conn.execute(sql) + def drop(self): return self.db.conn.execute("DROP TABLE {}".format(self.name)) diff --git a/tests/test_create.py b/tests/test_create.py index 3ae5fef..966602b 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -1,4 +1,5 @@ from .fixtures import fresh_db +from sqlite_utils.db import Index import pytest import json @@ -68,6 +69,55 @@ def test_create_table_works_for_m2m_with_only_foreign_keys(fresh_db): ) +@pytest.mark.parametrize( + "columns,index_name,expected_index", + ( + ( + ["is_good_dog"], + None, + Index( + seq=0, + name="idx_dogs_is_good_dog", + unique=0, + origin="c", + partial=0, + columns=["is_good_dog"], + ), + ), + ( + ["is_good_dog", "age"], + None, + Index( + seq=0, + name="idx_dogs_is_good_dog_age", + unique=0, + origin="c", + partial=0, + columns=["is_good_dog", "age"], + ), + ), + ( + ["age"], + "age_index", + Index( + seq=0, + name="age_index", + unique=0, + origin="c", + partial=0, + columns=["age"], + ), + ), + ), +) +def test_create_index(fresh_db, columns, index_name, expected_index): + dogs = fresh_db["dogs"] + dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is_good_dog": True}) + assert [] == dogs.indexes + dogs.create_index(columns, index_name) + assert expected_index == dogs.indexes[0] + + @pytest.mark.parametrize( "data_structure", (