diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index ef55976..29b2286 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -848,7 +848,14 @@ class Table: ), "Use either ignore=True or upsert=True, not both" all_columns = None first = True - for chunk in chunks(records, batch_size): + # We can only handle a max of 999 variables in a SQL insert, so + # we need to adjust the batch_size down if we have too many cols + records = iter(records) + # Peek at first record to count its columns: + first_record = next(records) + num_columns = len(first_record.keys()) + batch_size = max(1, min(batch_size, 999 // num_columns)) + for chunk in chunks(itertools.chain([first_record], records), batch_size): chunk = list(chunk) if first: if not self.exists: diff --git a/tests/test_create.py b/tests/test_create.py index 222a967..8f30347 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -500,6 +500,42 @@ def test_upsert_rows_alter_table(fresh_db, use_table_factory): ] == list(table.rows) +def test_bulk_insert_more_than_999_values(fresh_db): + "Inserting 100 items with 11 columns should work" + fresh_db["big"].insert_all( + ( + { + "id": i + 1, + "c2": 2, + "c3": 3, + "c4": 4, + "c5": 5, + "c6": 6, + "c7": 7, + "c8": 8, + "c8": 9, + "c10": 10, + "c11": 11, + } + for i in range(100) + ), + pk="id", + ) + assert 100 == fresh_db["big"].count + + +@pytest.mark.parametrize( + "num_columns,should_error", ((900, False), (999, False), (1000, True)) +) +def test_error_if_more_than_999_columns(fresh_db, num_columns, should_error): + record = dict([("c{}".format(i), i) for i in range(num_columns)]) + if should_error: + with pytest.raises(Exception): + fresh_db["big"].insert(record) + else: + fresh_db["big"].insert(record) + + @pytest.mark.parametrize( "columns,index_name,expected_index", (