From a4ba013306ab7823e48313527daad1446e9f3372 Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Tue, 22 Apr 2025 20:18:56 +0100 Subject: [PATCH] Change id columns to TABLENAME_id --- app/dbtables.py | 36 ++++---- app/ds.py | 72 ++++++++-------- ...ea0_notes_substrings_indexing_playlist_.py | 68 +++++++++++++++ ...65923a_have_id_field_reflect_table_name.py | 86 +++++++++++++++++++ 4 files changed, 208 insertions(+), 54 deletions(-) create mode 100644 migrations/versions/6d36cde8dea0_notes_substrings_indexing_playlist_.py create mode 100644 migrations/versions/8e06d465923a_have_id_field_reflect_table_name.py diff --git a/app/dbtables.py b/app/dbtables.py index 8567efe..7cefcaa 100644 --- a/app/dbtables.py +++ b/app/dbtables.py @@ -52,7 +52,7 @@ class JSONEncodedDict(TypeDecorator): class NoteColours(Model): __tablename__ = "notecolours" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + notecolour_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) substring: Mapped[str] = mapped_column(String(256), index=True, unique=True) colour: Mapped[str] = mapped_column(String(21), index=False) enabled: Mapped[bool] = mapped_column(default=True, index=True) @@ -64,7 +64,7 @@ class NoteColours(Model): def __repr__(self) -> str: return ( - f"" ) @@ -92,9 +92,9 @@ class NoteColours(Model): class Playdates(Model): __tablename__ = "playdates" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + playdate_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) lastplayed: Mapped[dt.datetime] = mapped_column(index=True) - track_id: Mapped[int] = mapped_column(ForeignKey("tracks.id", ondelete="CASCADE")) + track_id: Mapped[int] = mapped_column(ForeignKey("tracks.track_id", ondelete="CASCADE")) track: Mapped["Tracks"] = relationship( "Tracks", back_populates="playdates", @@ -116,7 +116,7 @@ class Playdates(Model): def __repr__(self) -> str: return ( - f"" ) @@ -128,7 +128,7 @@ class Playlists(Model): __tablename__ = "playlists" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + playlist_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(32), unique=True) last_used: Mapped[Optional[dt.datetime]] = mapped_column(DateTime, default=None) tab: Mapped[Optional[int]] = mapped_column(default=None) @@ -146,7 +146,7 @@ class Playlists(Model): def __repr__(self) -> str: return ( - f"" ) @@ -161,24 +161,24 @@ class Playlists(Model): # If a template is specified, copy from it if template_id: - PlaylistRows.copy_playlist(session, template_id, self.id) + PlaylistRows.copy_playlist(session, template_id, self.playlist_id) class PlaylistRows(Model): __tablename__ = "playlist_rows" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + playlistrow_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) row_number: Mapped[int] = mapped_column(index=True) note: Mapped[str] = mapped_column( String(2048), index=False, default="", nullable=False ) playlist_id: Mapped[int] = mapped_column( - ForeignKey("playlists.id", ondelete="CASCADE"), index=True + ForeignKey("playlists.playlist_id", ondelete="CASCADE"), index=True ) playlist: Mapped[Playlists] = relationship(back_populates="rows") track_id: Mapped[Optional[int]] = mapped_column( - ForeignKey("tracks.id", ondelete="CASCADE") + ForeignKey("tracks.track_id", ondelete="CASCADE") ) track: Mapped["Tracks"] = relationship( "Tracks", @@ -190,7 +190,7 @@ class PlaylistRows(Model): def __repr__(self) -> str: return ( - f"" ) @@ -217,7 +217,7 @@ class PlaylistRows(Model): class Queries(Model): __tablename__ = "queries" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + query_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(128), nullable=False) _filter_data: Mapped[dict | None] = mapped_column("filter_data", JSONEncodedDict, nullable=False) favourite: Mapped[bool] = mapped_column(Boolean, nullable=False, index=False, default=False) @@ -236,7 +236,7 @@ class Queries(Model): filter = property(_get_filter, _set_filter) def __repr__(self) -> str: - return f"" + return f"" def __init__( self, @@ -260,7 +260,7 @@ class Settings(Model): __tablename__ = "settings" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + setting_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(64), unique=True) f_datetime: Mapped[Optional[dt.datetime]] = mapped_column(default=None) f_int: Mapped[Optional[int]] = mapped_column(default=None) @@ -268,7 +268,7 @@ class Settings(Model): def __repr__(self) -> str: return ( - f"" ) @@ -282,7 +282,7 @@ class Settings(Model): class Tracks(Model): __tablename__ = "tracks" - id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + track_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) artist: Mapped[str] = mapped_column(String(256), index=True) bitrate: Mapped[int] = mapped_column(default=None) duration: Mapped[int] = mapped_column(index=True) @@ -308,7 +308,7 @@ class Tracks(Model): def __repr__(self) -> str: return ( - f"" ) diff --git a/app/ds.py b/app/ds.py index 5f2b117..52b059f 100644 --- a/app/ds.py +++ b/app/ds.py @@ -110,7 +110,7 @@ def _notecolours_all(session: Session) -> list[NoteColoursDTO]: results: list[NoteColoursDTO] = [] for record in records: result = NoteColoursDTO( - notecolour_id=record.id, + notecolour_id=record.notecolour_id, substring=record.substring, colour=record.colour, enabled=record.enabled, @@ -211,7 +211,7 @@ def _tracks_where( ) stmt = ( select( - Tracks.id.label("track_id"), + Tracks.track_id, Tracks.artist, Tracks.bitrate, Tracks.duration, @@ -223,7 +223,7 @@ def _tracks_where( Tracks.title, latest_playdate_subq.c.lastplayed, ) - .outerjoin(latest_playdate_subq, Tracks.id == latest_playdate_subq.c.track_id) + .outerjoin(latest_playdate_subq, Tracks.track_id == latest_playdate_subq.c.track_id) .where(query) ) @@ -259,7 +259,7 @@ def track_add_to_header(playlistrow_id: int, track_id: int) -> None: with db.Session() as session: session.execute( update(PlaylistRows) - .where(PlaylistRows.id == playlistrow_id) + .where(PlaylistRows.playlistrow_id == playlistrow_id) .values(track_id=track_id) ) session.commit() @@ -268,7 +268,7 @@ def track_add_to_header(playlistrow_id: int, track_id: int) -> None: def tracks_all() -> list[TrackDTO]: """Return a list of all tracks""" - return _tracks_where(Tracks.id > 0) + return _tracks_where(Tracks.track_id > 0) def tracks_by_artist(filter_str: str) -> list[TrackDTO]: @@ -284,7 +284,7 @@ def track_by_id(track_id: int) -> TrackDTO | None: Return track with specified id """ - track_list = _tracks_where(Tracks.id == track_id) + track_list = _tracks_where(Tracks.track_id == track_id) if not track_list: return None if len(track_list) > 1: @@ -333,7 +333,7 @@ def track_create(metadata: dict[str, str | int | float]) -> TrackDTO: bitrate=int(metadata["bitrate"]), ) - track_id = track.id + track_id = track.track_id session.commit() except Exception: raise ApplicationError("Can't create Track") @@ -387,8 +387,8 @@ def tracks_filtered(filter: Filter) -> list[TrackDTO]: # Process comparator if filter.last_played_comparator == Config.FILTER_PLAYED_COMPARATOR_NEVER: # Select tracks that have never been played - query = query.outerjoin(Playdates, Tracks.id == Playdates.track_id).where( - Playdates.id.is_(None) + query = query.outerjoin(Playdates, Tracks.track_id == Playdates.track_id).where( + Playdates.playdate_id.is_(None) ) else: # Last played specification @@ -414,7 +414,7 @@ def tracks_filtered(filter: Filter) -> list[TrackDTO]: .group_by(Playdates.track_id) .subquery() ) - query = query.join(subquery, Tracks.id == subquery.c.track_id).where( + query = query.join(subquery, Tracks.track_id == subquery.c.track_id).where( subquery.c.max_last_played < before ) @@ -438,7 +438,7 @@ def tracks_filtered(filter: Filter) -> list[TrackDTO]: silence_at=record.silence_at, start_gap=record.start_gap, title=record.title, - track_id=record.id, + track_id=record.track_id, ) results.append(dto) @@ -498,7 +498,7 @@ def _playlist_check_playlist( msg = ( "_check_playlist_integrity: incorrect row number " - f"({plr.id=}, {plr.row_number=}, {idx=})" + f"({plr.playlistrow_id=}, {plr.row_number=}, {idx=})" ) if fix: log.debug(msg) @@ -542,7 +542,7 @@ def _playlists_where( select( Playlists.favourite, Playlists.is_template, - Playlists.id.label("playlist_id"), + Playlists.playlist_id, Playlists.name, Playlists.open, ) @@ -570,7 +570,7 @@ def _playlists_where( def playlists_all(): """Return all playlists""" - return _playlists_where(Playlists.id > 0) + return _playlists_where(Playlists.playlist_id > 0) # @log_call @@ -579,7 +579,7 @@ def playlist_by_id(playlist_id: int) -> PlaylistDTO | None: Return playlist with specified id """ - playlist_list = _playlists_where(Playlists.id == playlist_id) + playlist_list = _playlists_where(Playlists.playlist_id == playlist_id) if not playlist_list: return None if len(playlist_list) > 1: @@ -627,7 +627,7 @@ def playlist_create( try: playlist = Playlists(session, name, template_id) playlist.is_template = as_template - playlist_id = playlist.id + playlist_id = playlist.playlist_id session.commit() except Exception: raise ApplicationError("Can't create Playlist") @@ -679,7 +679,7 @@ def playlist_insert_row( track_id=track_id, ) session.commit() - playlist_row_id = playlist_row.id + playlist_row_id = playlist_row.playlistrow_id # Sanity check _playlist_check_playlist(session, playlist_id, fix=False) @@ -697,7 +697,7 @@ def playlist_mark_status(playlist_id: int, open: bool) -> None: with db.Session() as session: session.execute( - update(Playlists).where(Playlists.id == playlist_id).values(open=open) + update(Playlists).where(Playlists.playlist_id == playlist_id).values(open=open) ) session.commit() @@ -778,7 +778,7 @@ def _playlist_move_rows_between_playlists( # Resequence row numbers in source _playlist_check_playlist(session, from_playlist_id, fix=True) - # Sanity check destionation + # Sanity check destination _playlist_check_playlist(session, from_playlist_id, fix=False) @@ -844,7 +844,7 @@ def _playlist_move_rows_within_playlist( plrid = old_row_to_id[old_row] update_list.append({"id": plrid, "row_number": new_row}) - # Updte database + # Update database session.execute(update(PlaylistRows), update_list) session.commit() @@ -867,7 +867,7 @@ def playlist_rename(playlist_id: int, new_name: str) -> None: with db.Session() as session: session.execute( - update(Playlists).where(Playlists.id == playlist_id).values(name=new_name) + update(Playlists).where(Playlists.playlist_id == playlist_id).values(name=new_name) ) session.commit() @@ -989,12 +989,12 @@ def playlist_save_tabs(playlist_id_to_tab: dict[int, int]) -> None: # Clear all existing tab numbers session.execute( update(Playlists) - .where(Playlists.id.in_(playlist_id_to_tab.keys())) + .where(Playlists.playlist_id.in_(playlist_id_to_tab.keys())) .values(tab=None) ) for playlist_id, tab in playlist_id_to_tab.items(): session.execute( - update(Playlists).where(Playlists.id == playlist_id).values(tab=tab) + update(Playlists).where(Playlists.playlist_id == playlist_id).values(tab=tab) ) session.commit() @@ -1006,7 +1006,7 @@ def playlist_update_template_favourite(template_id: int, favourite: bool) -> Non with db.Session() as session: session.execute( update(Playlists) - .where(Playlists.id == template_id) + .where(Playlists.playlist_id == template_id) .values(favourite=favourite) ) session.commit() @@ -1024,7 +1024,7 @@ def playlistrow_by_id(playlistrow_id: int) -> PlaylistRowDTO | None: with db.Session() as session: record = ( session.execute( - select(PlaylistRows).where(PlaylistRows.id == playlistrow_id) + select(PlaylistRows).where(PlaylistRows.playlistrow_id == playlistrow_id) ) .scalars() .one_or_none() @@ -1040,7 +1040,7 @@ def playlistrow_by_id(playlistrow_id: int) -> PlaylistRowDTO | None: note=record.note, played=record.played, playlist_id=record.playlist_id, - playlistrow_id=record.id, + playlistrow_id=record.playlistrow_id, row_number=record.row_number, track=track, ) @@ -1074,7 +1074,7 @@ def playlistrows_by_playlist( note=record.note, played=record.played, playlist_id=record.playlist_id, - playlistrow_id=record.id, + playlistrow_id=record.playlistrow_id, row_number=record.row_number, track=track, ) @@ -1112,7 +1112,7 @@ def playlistrow_played(playlistrow_id: int, status: bool) -> None: with db.Session() as session: session.execute( update(PlaylistRows) - .where(PlaylistRows.id == playlistrow_id) + .where(PlaylistRows.playlistrow_id == playlistrow_id) .values(played=status) ) session.commit() @@ -1165,7 +1165,7 @@ def playdates_between_dates( end = dt.datetime.now() stmt = select( - Playdates.id.label("playdate_id"), + Playdates.playdate_id, Playdates.lastplayed, Playdates.track_id, Playdates.track, @@ -1213,7 +1213,7 @@ def _queries_where( favourite=record.favourite, filter=record.filter, name=record.name, - query_id=record.id, + query_id=record.query_id, ) results.append(dto) @@ -1223,14 +1223,14 @@ def _queries_where( def queries_all(favourites_only: bool = False) -> list[QueryDTO]: """Return a list of all queries""" - query = Queries.id > 0 + query = Queries.query_id > 0 return _queries_where(query) def query_by_id(query_id: int) -> QueryDTO | None: """Return query""" - query_list = _queries_where(Queries.id == query_id) + query_list = _queries_where(Queries.query_id == query_id) if not query_list: return None if len(query_list) > 1: @@ -1246,7 +1246,7 @@ def query_create(name: str, filter: Filter) -> QueryDTO: with db.Session() as session: try: query = Queries(session=session, name=name, filter=filter) - query_id = query.id + query_id = query.query_id session.commit() except Exception: raise ApplicationError("Can't create Query") @@ -1272,7 +1272,7 @@ def query_update_favourite(query_id: int, favourite: bool) -> None: with db.Session() as session: session.execute( - update(Queries).where(Queries.id == query_id).values(favourite=favourite) + update(Queries).where(Queries.query_id == query_id).values(favourite=favourite) ) session.commit() @@ -1282,7 +1282,7 @@ def query_update_filter(query_id: int, filter: Filter) -> None: with db.Session() as session: session.execute( - update(Queries).where(Queries.id == query_id).values(filter=filter) + update(Queries).where(Queries.query_id == query_id).values(filter=filter) ) session.commit() @@ -1291,7 +1291,7 @@ def query_update_name(query_id: int, name: str) -> None: """Update query name""" with db.Session() as session: - session.execute(update(Queries).where(Queries.id == query_id).values(name=name)) + session.execute(update(Queries).where(Queries.query_id == query_id).values(name=name)) session.commit() diff --git a/migrations/versions/6d36cde8dea0_notes_substrings_indexing_playlist_.py b/migrations/versions/6d36cde8dea0_notes_substrings_indexing_playlist_.py new file mode 100644 index 0000000..08083cb --- /dev/null +++ b/migrations/versions/6d36cde8dea0_notes_substrings_indexing_playlist_.py @@ -0,0 +1,68 @@ +"""notes substrings, indexing, playlist faviourites, bitrate not null + +Revision ID: 6d36cde8dea0 +Revises: 4fc2a9a82ab0 +Create Date: 2025-04-22 17:03:00.497945 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision = '6d36cde8dea0' +down_revision = '4fc2a9a82ab0' +branch_labels = None +depends_on = None + + +def upgrade(engine_name: str) -> None: + globals()["upgrade_%s" % engine_name]() + + +def downgrade(engine_name: str) -> None: + globals()["downgrade_%s" % engine_name]() + + + + + +def upgrade_() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('notecolours', schema=None) as batch_op: + batch_op.add_column(sa.Column('strip_substring', sa.Boolean(), nullable=False)) + batch_op.create_index(batch_op.f('ix_notecolours_substring'), ['substring'], unique=True) + + with op.batch_alter_table('playlist_rows', schema=None) as batch_op: + batch_op.create_index(batch_op.f('ix_playlist_rows_playlist_id'), ['playlist_id'], unique=False) + + with op.batch_alter_table('playlists', schema=None) as batch_op: + batch_op.add_column(sa.Column('favourite', sa.Boolean(), nullable=False)) + + with op.batch_alter_table('tracks', schema=None) as batch_op: + batch_op.alter_column('bitrate', + existing_type=mysql.INTEGER(display_width=11), + nullable=False) + + # ### end Alembic commands ### + + +def downgrade_() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('tracks', schema=None) as batch_op: + batch_op.alter_column('bitrate', + existing_type=mysql.INTEGER(display_width=11), + nullable=True) + + with op.batch_alter_table('playlists', schema=None) as batch_op: + batch_op.drop_column('favourite') + + with op.batch_alter_table('playlist_rows', schema=None) as batch_op: + batch_op.drop_index(batch_op.f('ix_playlist_rows_playlist_id')) + + with op.batch_alter_table('notecolours', schema=None) as batch_op: + batch_op.drop_index(batch_op.f('ix_notecolours_substring')) + batch_op.drop_column('strip_substring') + + # ### end Alembic commands ### + diff --git a/migrations/versions/8e06d465923a_have_id_field_reflect_table_name.py b/migrations/versions/8e06d465923a_have_id_field_reflect_table_name.py new file mode 100644 index 0000000..ade8000 --- /dev/null +++ b/migrations/versions/8e06d465923a_have_id_field_reflect_table_name.py @@ -0,0 +1,86 @@ +"""Have id field reflect table name + +Revision ID: 8e06d465923a +Revises: 6d36cde8dea0 +Create Date: 2025-04-22 13:23:18.813024 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql +from dataclasses import dataclass + + +@dataclass +class TableInfo: + table: str + old: str + new: str + + +data = [ + TableInfo("notecolours", "id", "notecolour_id"), + TableInfo("playdates", "id", "playdate_id"), + TableInfo("playlists", "id", "playlist_id"), + TableInfo("playlist_rows", "id", "playlistrow_id"), + TableInfo("queries", "id", "query_id"), + TableInfo("settings", "id", "setting_id"), + TableInfo("tracks", "id", "track_id"), +] + + +# revision identifiers, used by Alembic. +revision = '8e06d465923a' +down_revision = '6d36cde8dea0' +branch_labels = None +depends_on = None + + +def upgrade(engine_name: str) -> None: + globals()["upgrade_%s" % engine_name]() + + +def downgrade(engine_name: str) -> None: + globals()["downgrade_%s" % engine_name]() + + +def upgrade_() -> None: + # Drop foreign key constraints + op.drop_constraint('fk_playdates_track_id_tracks', 'playdates', type_='foreignkey') + op.drop_constraint('fk_playlist_rows_track_id_tracks', 'playlist_rows', type_='foreignkey') + + for record in data: + op.alter_column( + record.table, + record.old, + new_column_name=record.new, + existing_type=sa.Integer(), # Specify the existing column type + existing_nullable=False # If the column is NOT NULL, specify that too + ) + + + # Recreate the foreign key constraints + op.create_foreign_key('fk_playdates_track_id_tracks', 'playdates', 'tracks', ['track_id'], ['track_id']) + op.create_foreign_key('fk_playlist_rows_track_id_tracks', 'playlist_rows', 'tracks', ['track_id'], ['track_id']) + # ### end Alembic commands ### + + +def downgrade_() -> None: + # Drop foreign key constraints + op.drop_constraint('fk_playdates_track_id_tracks', 'playdates', type_='foreignkey') + op.drop_constraint('fk_playlist_rows_track_id_tracks', 'playlist_rows', type_='foreignkey') + + for record in data: + op.alter_column( + record.table, + record.new, + new_column_name=record.old, + existing_type=sa.Integer(), # Specify the existing column type + existing_nullable=False # If the column is NOT NULL, specify that too + ) + + # Recreate the foreign key constraints + op.create_foreign_key('fk_playdates_track_id_tracks', 'playdates', 'tracks', ['track_id'], ['track_id']) + op.create_foreign_key('fk_playlist_rows_track_id_tracks', 'playlist_rows', 'tracks', ['track_id'], ['track_id']) + + # ### end Alembic commands ###