From c374d7ef040f6d8e407fbf57cf7166f82e01929c Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Fri, 28 May 2021 21:32:03 -0700 Subject: [PATCH] DescIndex(column) for descending index columns, refs #260 --- docs/python-api.rst | 11 +++++++++++ sqlite_utils/db.py | 13 ++++++++++++- tests/test_create.py | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/python-api.rst b/docs/python-api.rst index ad7b394d1..418c58d5f 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -1866,6 +1866,17 @@ By default the index will be named ``idx_{table-name}_{columns}`` - if you want index_name="good_dogs_by_age" ) +To create an index in descending order for a column, wrap the column name in ``db.DescIndex()`` like this: + +.. code-block:: python + + from sqlite_utils.db import DescIndex + + db["dogs"].create_index( + ["is_good_dog", DescIndex("age")], + index_name="good_dogs_by_age" + ) + You can create a unique index by passing ``unique=True``: .. code-block:: python diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 0e37b1203..fdfe360aa 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -144,6 +144,10 @@ class InvalidColumns(Exception): pass +class DescIndex(str): + pass + + _COUNTS_TABLE_CREATE_SQL = """ CREATE TABLE IF NOT EXISTS [{}]( [table] TEXT PRIMARY KEY, @@ -1156,6 +1160,13 @@ def create_index(self, columns, index_name=None, unique=False, if_not_exists=Fal index_name = "idx_{}_{}".format( self.name.replace(" ", "_"), "_".join(columns) ) + columns_sql = [] + for column in columns: + if isinstance(column, DescIndex): + fmt = "[{}] desc" + else: + fmt = "[{}]" + columns_sql.append(fmt.format(column)) sql = ( textwrap.dedent( """ @@ -1167,7 +1178,7 @@ def create_index(self, columns, index_name=None, unique=False, if_not_exists=Fal .format( index_name=index_name, table_name=self.name, - columns=", ".join("[{}]".format(c) for c in columns), + columns=", ".join(columns_sql), unique="UNIQUE " if unique else "", if_not_exists="IF NOT EXISTS " if if_not_exists else "", ) diff --git a/tests/test_create.py b/tests/test_create.py index e08eb2514..6e925dcf9 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -1,6 +1,7 @@ from sqlite_utils.db import ( Index, Database, + DescIndex, ForeignKey, AlterError, NoObviousTable, @@ -739,6 +740,19 @@ def test_create_index_if_not_exists(fresh_db): dogs.create_index(["name"], if_not_exists=True) +def test_create_index_desc(fresh_db): + dogs = fresh_db["dogs"] + dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is good dog": True}) + assert [] == dogs.indexes + dogs.create_index([DescIndex("age"), "name"]) + sql = fresh_db.execute( + "select sql from sqlite_master where name='idx_dogs_age_name'" + ).fetchone()[0] + assert sql == ( + "CREATE INDEX [idx_dogs_age_name]\n" " ON [dogs] ([age] desc, [name])" + ) + + @pytest.mark.parametrize( "data_structure", (