diff --git a/docs/python-api.rst b/docs/python-api.rst index 28adfba..c656045 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -716,6 +716,8 @@ If it cannot find such a table, it will create a new one using the names of the It it finds multiple candidate tables with foreign keys to both of the specified tables it will raise a ``sqlite_utils.db.NoObviousTable`` exception. You can avoid this error by specifying the correct table using ``m2m_table=``. +The ``.m2m()`` method also takes an optional ``pk=`` argument to specify the primary key that should be used if the table is created, and an optional ``alter=True`` argument to specify that any missing columns of an existing table should be added if they are needed. + .. _python_api_m2m_lookup: Using m2m and lookup tables together diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index c6bc606..14a9efc 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -2009,6 +2009,7 @@ class Table(Queryable): pk=DEFAULT, lookup=None, m2m_table=None, + alter=False, ): if isinstance(other_table, str): other_table = self.db.table(other_table, pk=pk) @@ -2045,7 +2046,9 @@ class Table(Queryable): ) # Ensure each record exists in other table for record in records: - id = other_table.insert(record, pk=pk, replace=True).last_pk + id = other_table.insert( + record, pk=pk, replace=True, alter=alter + ).last_pk m2m_table.insert( { "{}_id".format(other_table.name): id, diff --git a/tests/test_m2m.py b/tests/test_m2m.py index cbc9015..5423d2b 100644 --- a/tests/test_m2m.py +++ b/tests/test_m2m.py @@ -14,6 +14,24 @@ def test_insert_m2m_single(fresh_db): assert [{"humans_id": 1, "dogs_id": 1}] == list(dogs_humans.rows) +def test_insert_m2m_alter(fresh_db): + dogs = fresh_db["dogs"] + dogs.insert({"id": 1, "name": "Cleo"}, pk="id").m2m( + "humans", {"id": 1, "name": "Natalie D"}, pk="id" + ) + dogs.update(1).m2m( + "humans", {"id": 2, "name": "Simon W", "nerd": True}, pk="id", alter=True + ) + assert list(fresh_db["humans"].rows) == [ + {"id": 1, "name": "Natalie D", "nerd": None}, + {"id": 2, "name": "Simon W", "nerd": 1}, + ] + assert list(fresh_db["dogs_humans"].rows) == [ + {"humans_id": 1, "dogs_id": 1}, + {"humans_id": 2, "dogs_id": 1}, + ] + + def test_insert_m2m_list(fresh_db): dogs = fresh_db["dogs"] dogs.insert({"id": 1, "name": "Cleo"}, pk="id").m2m(