From c611ed80d2e9f721fc7848fd74e6e6baebe5adde Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 31 Jul 2018 18:31:29 -0700 Subject: [PATCH] .indexes property for introspecting indexes --- docs/table.rst | 10 ++++++++++ sqlite_utils/db.py | 13 +++++++++++++ tests/test_introspect.py | 24 +++++++++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/docs/table.rst b/docs/table.rst index 5fa7260..4bed6b9 100644 --- a/docs/table.rst +++ b/docs/table.rst @@ -167,6 +167,16 @@ The ``.schema`` property outputs the table's schema as a SQL string:: FOREIGN KEY ("qCareAssistant") REFERENCES [qCareAssistant](id), FOREIGN KEY ("qLegalStatus") REFERENCES [qLegalStatus](id)) +The ``.indexes`` property shows you all indexes created for a table:: + + >>> db["Street_Tree_List"].indexes + [Index(seq=0, name='"Street_Tree_List_qLegalStatus"', unique=0, origin='c', partial=0, columns=['qLegalStatus']), + Index(seq=1, name='"Street_Tree_List_qCareAssistant"', unique=0, origin='c', partial=0, columns=['qCareAssistant']), + Index(seq=2, name='"Street_Tree_List_qSiteInfo"', unique=0, origin='c', partial=0, columns=['qSiteInfo']), + Index(seq=3, name='"Street_Tree_List_qSpecies"', unique=0, origin='c', partial=0, columns=['qSpecies']), + Index(seq=4, name='"Street_Tree_List_qCaretaker"', unique=0, origin='c', partial=0, columns=['qCaretaker']), + Index(seq=5, name='"Street_Tree_List_PlantType"', unique=0, origin='c', partial=0, columns=['PlantType'])] + Enabling full-text search ========================= diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 2d6c30a..3f922c0 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -8,6 +8,7 @@ Column = namedtuple( ForeignKey = namedtuple( "ForeignKey", ("table", "column", "other_table", "other_column") ) +Index = namedtuple("Index", ("seq", "name", "unique", "origin", "partial", "columns")) class Database: @@ -122,6 +123,18 @@ class Table: "select sql from sqlite_master where name = ?", (self.name,) ).fetchone()[0] + @property + def indexes(self): + sql = "select * from pragma_index_list(?)" + indexes = [] + for row in list(self.db.conn.execute(sql, (self.name,)).fetchall()): + column_sql = "select name from pragma_index_info(?) order by seqno" + columns = [ + r[0] for r in self.db.conn.execute(column_sql, (row[1],)).fetchall() + ] + indexes.append(Index(*(row + (columns,)))) + return indexes + def create(self, columns, pk=None, foreign_keys=None): columns = {name: value for (name, value) in columns.items()} self.db.create_table(self.name, columns, pk=pk, foreign_keys=foreign_keys) diff --git a/tests/test_introspect.py b/tests/test_introspect.py index fc1f226..b06ea91 100644 --- a/tests/test_introspect.py +++ b/tests/test_introspect.py @@ -1,4 +1,5 @@ -from .fixtures import existing_db +from .fixtures import existing_db, fresh_db +from sqlite_utils.db import Index def test_table_names(existing_db): @@ -27,3 +28,24 @@ def test_schema(existing_db): def test_table_repr(existing_db): assert "" == repr(existing_db["foo"]) + + +def test_indexes(fresh_db): + fresh_db.conn.executescript( + """ + create table Gosh (c1 text, c2 text, c3 text); + create index Gosh_c1 on Gosh(c1); + create index Gosh_c2c3 on Gosh(c2, c3); + """ + ) + assert [ + Index( + seq=0, + name="Gosh_c2c3", + unique=0, + origin="c", + partial=0, + columns=["c2", "c3"], + ), + Index(seq=1, name="Gosh_c1", unique=0, origin="c", partial=0, columns=["c1"]), + ] == fresh_db["Gosh"].indexes