diff --git a/docs/python-api.rst b/docs/python-api.rst index b25eb21..85f0296 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -1549,6 +1549,19 @@ The ``.pks`` property returns a list of strings naming the primary key columns f >>> db["PlantType"].pks ['id'] +If a table has no primary keys but is a `rowid table `__, this property will return ``['rowid']``. + +.. _python_api_introspection_use_rowid: + +.use_rowid +---------- + +Almost all SQLite tables have a ``rowid`` column, but a table with no explicitly defined primary keys must use that ``rowid`` as the primary key for identifying individual rows. The ``.use_rowid`` property checks to see if a table needs to use the ``rowid`` in this way - it returns ``True`` if the table has no explicitly defined primary keys and ``False`` otherwise. + + >>> db["PlantType"].use_rowid + False + + .. _python_api_introspection_foreign_keys: .foreign_keys diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 31d4cee..2d8fb24 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -809,6 +809,10 @@ class Table(Queryable): names = ["rowid"] return names + @property + def use_rowid(self): + return not any(column for column in self.columns if column.is_pk) + def get(self, pk_values): if not isinstance(pk_values, (list, tuple)): pk_values = [pk_values] diff --git a/tests/test_introspect.py b/tests/test_introspect.py index d54ca88..6ca578c 100644 --- a/tests/test_introspect.py +++ b/tests/test_introspect.py @@ -237,3 +237,11 @@ def test_virtual_table_using(sql, expected_name, expected_using): db = Database(memory=True) db.execute(sql) assert db[expected_name].virtual_table_using == expected_using + + +def test_use_rowid(): + db = Database(memory=True) + db["rowid_table"].insert({"name": "Cleo"}) + db["regular_table"].insert({"id": 1, "name": "Cleo"}, pk="id") + assert db["rowid_table"].use_rowid + assert not db["regular_table"].use_rowid