- New
table.checks,table.column_checksandtable.table_checksintrospection properties expose column-level and table-levelCHECKconstraints. (#834) - New
sqlite_utils.ANYmarker type for creating and introspecting SQLiteANYcolumns. The Python API and CLI can create, add and transform these columns, andtable.transform()andtable.extract()now preserveANYcolumns and their values inSTRICTtables. (#790) table.default_valuesnow unescapes doubled single quotes in string defaults, so a default such as'O''Brien'is returned as"O'Brien". Thanks, ikatyal2110. (#811)table.default_valuesnow decodes unquotedTRUE,FALSEandNULLdefault literals asTrue,FalseandNonerespectively. (#836)table.enable_fts(..., tokenize=...)andsqlite-utils enable-fts --tokenizenow safely quote the tokenizer argument, preventing a crafted value from injecting additional SQL. Thanks, Bunlong Heng. (#828)rows_where(),pks_and_rows_where(),search()andsearch_sql()now supportoffset=without requiringlimit=. Thesqlite-utils rows --offsetoption now works without--limittoo. Thanks, ethanhawkes-gif. (#816, #821)- Empty or whitespace-only input passed to
rows_from_file()is now handled as an empty CSV file instead of raisingcsv.Error. Thanks, Rami Abdelrazzaq. (#808, #837) sqlite-utils convert --dry-runnow works for table and column names containing closing square brackets. (#829)table.indexesandtable.xindexesnow work for table, index and column names containing double quotes. This also fixestable.transform()for tables with those identifiers. Thanks, nyxst4ck. (#824, #825)- Improved type annotations throughout the package and added Pyright regression checks to CI. (#833)
- Changing a
TEXTcolumn toINTEGER,FLOATorREALusingtable.transform()orsqlite-utilstransformnow converts exact empty strings toNULL. Previously they remained empty strings in the numeric column. Thanks, ikatyal2110. (#488, #805)
table.transform() can handle many more edge-cases:
table.transform()now preserves column-level and compositeUNIQUEconstraints, including constraint names, collations, sort order andON CONFLICTbehavior. Renaming columns updates those constraints, while dropping any constituent column removes the entire constraint. (#762)table.transform()now preservesAUTOINCREMENTprimary keys and their sequence high-water marks. Previously a transform removedAUTOINCREMENTand could reuse deleted row IDs. (#602)table.transform()now preservesCHECKconstraints, including comments within their expressions. Renaming a column rewrites identifier references in checks without changing string literals or function names. Dropping a column drops a check owned by that column, and raisesTransformErrorif a remaining check depends on it. (#762)table.transform()now preserves comments immediately before or after column definitions. These comments move with the column if it is renamed or reordered, and are removed if the column is dropped. (#762)table.transform(rename=...)now preserves explicit indexes on renamed columns by dropping and recreating those indexes against the new column names. Previously this raised aTransformError. (#822)table.transform()now works for tables that are referenced by views. Previously theALTER TABLE... RENAME TOstep raisedno such tableif a view referenced the table being transformed. View definitions are left unchanged - see Tables referenced by views. This also fixes a bug wheretransform(keep_table=...)silently rewrote dependent views to point at the frozen backup table instead of the live one. (#831)