`table.get(column=value)` option for retrieving things not by their primary key
This came up working on this feature:
- https://github.com/simonw/llm/pull/186
I have a table with this schema:
CREATE TABLE [collections] (
[id] INTEGER PRIMARY KEY,
[name] TEXT,
[model] TEXT
);
CREATE UNIQUE INDEX [idx_collections_name]
ON [collections] ([name]);
So the primary key is an integer (because it's going to have a huge number of rows foreign key related to it, and I don't want to store a larger text value thousands of times), but there is a unique constraint on the name - that would be the primary key column if not for all of those foreign keys.
Problem is, fetching the collection by name is actually pretty inconvenient.
Fetch by numeric ID:
try:
table["collections"].get(1)
except NotFoundError:
# It doesn't exist
Fetching by name:
def get_collection(db, collection):
rows = db["collections"].rows_where("name = ?", [collection])
try:
return next(rows)
except StopIteration:
raise NotFoundError("Collection not found: {}".format(collection))
It would be neat if, for columns where we know that we should always get 0 or one result, we could do this instead:
try:
collection = table["collections"].get(name="entries")
except NotFoundError:
# It doesn't exist
The existing .get() method doesn't have any non-positional arguments, so using **kwargs like that should work:
https://github.com/simonw/sqlite-utils/blob/1260bdc7bfe31c36c272572c6389125f8de6ef71/sqlite_utils/db.py#L1495
Tips on typing **kwargs: https://adamj.eu/tech/2021/05/11/python-type-hints-args-and-kwargs/
Would be nice to have something like this. I've created a get_by() method previously to do the same thing but adding it to get() makes sense.
Tangentially, a first() method that worked similarly but returned None instead of raising when a record isn't found would also be helpful IMO.