wrolpi/alembic/versions/2026_09_16_1200_file_group_stem.py
lrnselfreliance 9352839106
Some checks are pending
CodeQL / Analyze (push) Waiting to run
Controller Tests / controller-tests (push) Waiting to run
Jest Tests / jest-tests (push) Waiting to run
files: SQL FileGroup compare, stem column, drop unused discovery path (#713)
* files: SQL FileGroup compare, stem column, drop unused discovery path

Refresh walked the tree twice (find, then stat every unchanged group),
and a two-directory refresh scanned the whole media directory.  Compare
now diffs in SQL on a TEMP table that already has mtime, accepts multiple
roots, and groups by a stored stem that is versioned so a suffix-rule
change cannot delete-and-reinsert tagged files.

Deletes refresh_discover_paths and /api/files/refresh_progress, which
nothing in production called.  Video/doc/zim modelers use the same
(no domain row OR indexed != True) gate.

* files: keep stem current on reorganize; NUL-safe find parse

Reorganize wrote the new primary_path but not stem, so the next refresh
treated the FileGroup as deleted+new and dropped tags.  GNU find now
emits NUL-delimited records so a tab or newline in a filename cannot
abort a global refresh.  Stem backfill skips the table scan once the
algorithm version matches, and runs off the event loop.  An empty roots
list is a global refresh, not invalid SQL.
2026-09-18 08:57:56 -06:00

37 lines
1.2 KiB
Python

"""Add file_group.stem for (directory, stem) grouping.
A stored stem is a cache of split_path_stem_and_suffix. Compare joins on it.
NULL stems (and algorithm-version mismatches) are backfilled at refresh by
ensure_file_group_stems() before any compare is allowed.
The unique (directory, stem) index is intentionally omitted: duplicates are
collapsed at refresh time. A later release can add UNIQUE after a full refresh.
Revision ID: 2026_09_16_1200
Revises: 2026_07_14_0900
"""
from alembic import op
# revision identifiers, used by Alembic.
revision = '2026_09_16_1200'
down_revision = '2026_07_14_0900'
branch_labels = None
depends_on = None
def upgrade():
op.execute('ALTER TABLE file_group ADD COLUMN stem VARCHAR')
op.execute('CREATE INDEX IF NOT EXISTS file_group_directory_stem_idx '
'ON file_group (directory, stem)')
op.execute('''
CREATE TABLE IF NOT EXISTS wrolpi_kv (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
)
''')
def downgrade():
op.execute('DROP INDEX IF EXISTS file_group_directory_stem_idx')
# SQLite cannot DROP COLUMN without rebuilding the table; leave stem in place.
op.execute('DROP TABLE IF EXISTS wrolpi_kv')