Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

table.pks_and_rows_where() method returning primary keys along with the rows #240

Closed
simonw opened this issue Feb 25, 2021 · 7 comments
Closed
Labels
enhancement New feature or request python-library

Comments

@simonw
Copy link
Owner

simonw commented Feb 25, 2021

Original title: Easier way to update a row returned from .rows

Here's a surprisingly hard problem I ran into while trying to implement #239 - given a row returned by db[table].rows how can you update that row?

The problem is that the db[table].update(...) method requires a primary key. But if you have a row from the db[table].rows iterator it might not even contain the primary key - provided the table is a rowid table.

Instead, currently, you need to introspect the table and, if rowid is a primary key, explicitly include that in the select= argument to table.rows_where(...) - otherwise it will not be returned.

A utility mechanism to make this easier would be very welcome.

@simonw simonw added enhancement New feature or request python-library labels Feb 25, 2021
@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

One option: .rows_where() could grow a ensure_pk=True option which checks to see if the table is a rowid table and, if it is, includes that in the select.

Or... how about you can call .rows_where(..., pks=True) and it will yield (pk, rowdict) tuple pairs instead of just returning the sequence of dictionaries?

I'm always a little bit nervous of methods that vary their return type based on their arguments. Maybe this would be a separate method instead?

    for pk, row in table.pk_rows_where(...):
        # ...

@simonw simonw changed the title Easier way to update a row returned from .rows table.pk_rows_where() method returning primary keys along with the rows Feb 25, 2021
@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

Is pk_rows_where() a good name? It sounds like it returns "primary key rows" which isn't a thing. It actually returns rows along with their primary key.

Other options:

  • table.rows_with_pk_where(...) - should this return (row, pk) rather than (pk, row)?
  • table.rows_where_pk(...)
  • table.pk_and_rows_where(...)
  • table.pk_with_rows_where(...)
  • table.pks_with_rows_where(...) - because rows is pluralized, so pks should be pluralized too?
  • table.pks_rows_where(...)

@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

I quite like pks_with_rows_where(...) - but grammatically it suggests it will return the primary keys that exist where their rows match the criteria - "pks with rows" can be interpreted as "pks for the rows that..." as opposed to "pks accompanied by rows"

@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

table.pks_and_rows_where(...) is explicit and I think less ambiguous than the other options.

@simonw simonw changed the title table.pk_rows_where() method returning primary keys along with the rows table.pks_and_rows_where() method returning primary keys along with the rows Feb 25, 2021
@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

I prototyped this and I like it:

In [1]: import sqlite_utils
In [2]: db = sqlite_utils.Database("/Users/simon/Dropbox/Development/datasette/fixtures.db")
In [3]: list(db["compound_primary_key"].pks_and_rows_where())
Out[3]: [(('a', 'b'), {'pk1': 'a', 'pk2': 'b', 'content': 'c'})]

@simonw simonw closed this as completed in 38e688f Feb 25, 2021
simonw added a commit that referenced this issue Feb 25, 2021
@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

@simonw
Copy link
Owner Author

simonw commented Feb 25, 2021

Example from the docs:

>>> db = sqlite_utils.Database(memory=True)
>>> db["dogs"].insert({"name": "Cleo"})
>>> for pk, row in db["dogs"].pks_and_rows_where():
...     print(pk, row)
1 {'rowid': 1, 'name': 'Cleo'}

>>> db["dogs_with_pk"].insert({"id": 5, "name": "Cleo"}, pk="id")
>>> for pk, row in db["dogs_with_pk"].pks_and_rows_where():
...     print(pk, row)
5 {'id': 5, 'name': 'Cleo'}

>>> db["dogs_with_compound_pk"].insert(
...     {"species": "dog", "id": 3, "name": "Cleo"},
...     pk=("species", "id")
... )
>>> for pk, row in db["dogs_with_compound_pk"].pks_and_rows_where():
...     print(pk, row)
('dog', 3) {'species': 'dog', 'id': 3, 'name': 'Cleo'}

simonw added a commit that referenced this issue May 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request python-library
Projects
None yet
Development

No branches or pull requests

1 participant