From 05b5f0fe26dd461b291c494256a7a36e4662a8cb Mon Sep 17 00:00:00 2001 From: ikatyal21 Date: Sun, 12 Jul 2026 14:18:21 +0000 Subject: [PATCH] Fix transform() dropping AUTOINCREMENT from INTEGER PRIMARY KEY columns Calling .transform() on a table with INTEGER PRIMARY KEY AUTOINCREMENT recreated the table without the AUTOINCREMENT keyword, silently changing the table's behaviour so that deleted row IDs could be reused. The fix adds an autoincrement parameter to create_table_sql() and detects AUTOINCREMENT in the existing schema before calling it from transform_sql(). --- sqlite_utils/db.py | 6 ++++++ tests/test_transform.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index d709fb9cb..798b7b923 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -1400,6 +1400,7 @@ def create_table_sql( extracts: Optional[Union[Dict[str, str], List[str]]] = None, if_not_exists: bool = False, strict: bool = False, + autoincrement: bool = False, ) -> str: """ Returns the SQL ``CREATE TABLE`` statement for creating the specified table. @@ -1496,6 +1497,8 @@ def sort_key(p): column_extras = [] if column_name == single_pk: column_extras.append("PRIMARY KEY") + if autoincrement: + column_extras.append("AUTOINCREMENT") if column_name in not_null: column_extras.append("NOT NULL") if column_name in defaults and defaults[column_name] is not None: @@ -2807,6 +2810,8 @@ def fk_with_renamed_columns(fk: ForeignKey) -> ForeignKey: if column_order is not None: column_order = [rename.get(col) or col for col in column_order] + has_autoincrement = "autoincrement" in self.schema.lower() + sqls = [] sqls.append( self.db.create_table_sql( @@ -2818,6 +2823,7 @@ def fk_with_renamed_columns(fk: ForeignKey) -> ForeignKey: foreign_keys=create_table_foreign_keys, column_order=column_order, strict=self.strict if strict is None else strict, + autoincrement=has_autoincrement, ).strip() ) diff --git a/tests/test_transform.py b/tests/test_transform.py index 3cc5ba60c..b9ec5a176 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -758,6 +758,25 @@ def test_transform_with_indexes_errors(fresh_db, transform_params): ) +def test_transform_preserves_autoincrement(fresh_db): + fresh_db.execute( + "CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT)" + ) + fresh_db["t"].insert({"val": "one"}) + fresh_db["t"].insert({"val": "two"}) + fresh_db["t"].transform(rename={"val": "value"}) + assert "AUTOINCREMENT" in fresh_db["t"].schema + # Confirm the column is still the primary key + assert fresh_db["t"].pks == ["id"] + + +def test_transform_without_autoincrement_not_affected(fresh_db): + fresh_db.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)") + fresh_db["t"].insert({"val": "one"}) + fresh_db["t"].transform(rename={"val": "value"}) + assert "AUTOINCREMENT" not in fresh_db["t"].schema + + def test_transform_with_unique_constraint_implicit_index(fresh_db): dogs = fresh_db["dogs"] # Create a table with a UNIQUE constraint on 'name', which creates an implicit index