html_url,id,node_id,tag_name,target_commitish,name,draft,author,prerelease,created_at,published_at,body,repo,reactions https://github.com/simonw/sqlite-utils/releases/tag/2.20,31680849,MDc6UmVsZWFzZTMxNjgwODQ5,2.20,main,2.20,0,9599,0,2020-09-23T00:35:52Z,2020-09-23T00:37:01Z,"This release introduces two key new capabilities: **transform** ([#114](https://github.com/simonw/sqlite-utils/issues/114)) and **extract** ([#42](https://github.com/simonw/sqlite-utils/issues/42)). ### Transform SQLite's ALTER TABLE has [several documented limitations](https://sqlite.org/lang_altertable.html). The `table.transform()` Python method and `sqlite-utils transform` CLI command work around these limitations using a pattern where a new table with the desired structure is created, data is copied over to it and the old table is then dropped and replaced by the new one. You can use these tools to drop columns, change column types, rename columns, add and remove `NOT NULL` and defaults, remove foreign key constraints and more. See the [transforming tables (CLI)](https://sqlite-utils.readthedocs.io/en/stable/cli.html#cli-transform-table) and [transforming tables (Python library)](https://sqlite-utils.readthedocs.io/en/stable/python-api.html#python-api-transform) documentation for full details of how to use them. ### Extract Sometimes a database table - especially one imported from a CSV file - will contain duplicate data. A `Trees` table may include a `Species` column with only a few dozen unique values, when the table itself contains thousands of rows. The `table.extract()` method and `sqlite-utils extract` commands can extract a column - or multiple columns - out into a separate lookup table, and set up a foreign key relationship from the original table. The Python library [extract() documentation](https://sqlite-utils.readthedocs.io/en/stable/python-api.html#python-api-extract) describes how extraction works in detail, and [Extracting columns into a separate table](https://sqlite-utils.readthedocs.io/en/stable/cli.html#cli-extract) in the CLI documentation includes a detailed example. ### Other changes - The `@db.register_function` decorator can be used to quickly register Python functions as custom SQL functions, see [Registering custom SQL functions](https://sqlite-utils.readthedocs.io/en/stable/python-api.html#python-api-register-function). ([#162](https://github.com/simonw/sqlite-utils/issues/162)) - The `table.rows_where()` method now accepts an optional `select=` argument for specifying which columns should be selected, see [Listing rows](https://sqlite-utils.readthedocs.io/en/stable/python-api.html#python-api-rows).",140912432,