Skip to content

Clarify transform() behavior for indexes, views, and triggers - #896

Draft
ParsingMAINFRAME wants to merge 1 commit into
simonw:mainfrom
ParsingMAINFRAME:docs/611-transform-schema
Draft

ParsingMAINFRAME wants to merge 1 commit into
simonw:mainfrom
ParsingMAINFRAME:docs/611-transform-schema

Conversation

@ParsingMAINFRAME

@ParsingMAINFRAME ParsingMAINFRAME commented Oct 3, 2026 •

Copy link
Copy Markdown

Refs #611.

The custom-transform documentation says transform() does not automatically
"upgrade" indexes, views, or triggers. That no longer explains the behavior:
indexes have been recreated since 3.38, and simple indexes on renamed columns
are supported in 4.2.

This documentation-only change explains the differences on current main:

  • Explicit indexes are recreated, with simple column references renamed.
    It describes which index cases raise TransformError and when to recreate
    indexes manually.
  • Views keep their definitions, with a link to the existing explanation.
  • Triggers on the original table are dropped, or remain on the retained
    table when keep_table is used. Triggers attached elsewhere are unchanged.

It also explains how to append CREATE TRIGGER statements to transform_sql()
when renaming a column, and removes wording suggesting stale view references
are inherent to SQLite views. transform(rename=...) rebuilds the table;
SQLite's native ALTER TABLE ... RENAME COLUMN has different behavior.

Validation on macOS, Python 3.14.7 / SQLite 3.53.4, base 6bc1d33:

  • pytest: 1497 passed, 16 skipped.
  • transform tests with --sqlite-autocommit: 112 passed.
  • Sphinx HTML build with warnings as errors, Black, flake8, mypy, Pyright,
    ty, Cog, and codespell passed.
  • Synthetic in-memory examples inspected generated SQL and sqlite_master
    before/after, including trigger loss, keep_table, stale references, index
    rejection, and rollback after a failed unique-index recreation.
  • The CLI check without dev dependencies passed, including clean isolated
    editable builds of both unchanged main and the patched source. An initial
    editable-install failure was traced to a local cached .pth file carrying
    macOS's hidden flag, which Python skips; it also failed on unchanged main
    using that same affected cache artifact.

Small example of the trigger behavior:

from sqlite_utils import Database

with Database(memory=True) as db:
    db.executescript("""
        CREATE TABLE thread (subject TEXT);
        CREATE TABLE audit (value TEXT);
        CREATE TRIGGER subject_changed AFTER UPDATE OF subject ON thread
        BEGIN INSERT INTO audit VALUES (NEW.subject); END;
    """)
    print([trigger.name for trigger in db.triggers])  # ['subject_changed']
    db["thread"].transform(rename={"subject": "title"})
    print(db.triggers)  # []

AI assistance: OpenAI Codex helped investigate the behavior, draft the wording,
and run the checks.


📚 Documentation preview 📚: https://sqlite-utils--896.org.readthedocs.build/en/896/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant