# Standard library imports # PyQt imports # Third party imports from sqlalchemy import select, func from sqlalchemy.orm import aliased from classes import PlaylistRowDTO # App imports from classes import TrackDTO from models import db, Tracks, PlaylistRows, Playdates def tracks_like_title(filter_str: str) -> list[TrackDTO]: """ Return tracks where title is like filter """ # TODO: add in playdates as per Tracks.search_titles with db.Session() as session: stmt = select(Tracks).where(Tracks.title.ilike(f"%{filter_str}%")) results = ( session.execute(stmt).scalars().unique().all() ) # `scalars()` extracts ORM objects return [ TrackDTO(**{k: v for k, v in vars(t).items() if not k.startswith("_")}) for t in results ] def get_playlist_rows(playlist_id: int) -> list[PlaylistRowDTO]: # Alias PlaydatesTable for subquery LatestPlaydate = aliased(Playdates) # Subquery: latest playdate for each track latest_playdate_subq = ( select( LatestPlaydate.track_id, func.max(LatestPlaydate.lastplayed).label("lastplayed") ) .group_by(LatestPlaydate.track_id) .subquery() ) stmt = ( select( PlaylistRows.id.label("playlistrow_id"), PlaylistRows.row_number, PlaylistRows.note, PlaylistRows.played, PlaylistRows.playlist_id, Tracks.id.label("track_id"), Tracks.artist, Tracks.bitrate, Tracks.duration, Tracks.fade_at, Tracks.intro, Tracks.path, Tracks.silence_at, Tracks.start_gap, Tracks.title, latest_playdate_subq.c.lastplayed, ) .outerjoin(Tracks, PlaylistRows.track_id == Tracks.id) .outerjoin(latest_playdate_subq, Tracks.id == latest_playdate_subq.c.track_id) .where(PlaylistRows.playlist_id == playlist_id) .order_by(PlaylistRows.row_number) ) with db.Session() as session: results = session.execute(stmt).all() dto_list = [] for row in results: # Handle cases where track_id is None (no track associated) if row.track_id is None: dto = PlaylistRowDTO( artist="", bitrate=0, duration=0, fade_at=0, intro=None, lastplayed=None, note=row.note, path="", played=row.played, playlist_id=row.playlist_id, playlistrow_id=row.playlistrow_id, row_number=row.row_number, silence_at=0, start_gap=0, title="", track_id=-1, # Additional fields like row_fg, row_bg, etc., use default None values ) else: dto = PlaylistRowDTO( artist=row.artist, bitrate=row.bitrate, duration=row.duration, fade_at=row.fade_at, intro=row.intro, lastplayed=row.lastplayed, note=row.note, path=row.path, played=row.played, playlist_id=row.playlist_id, playlistrow_id=row.playlistrow_id, row_number=row.row_number, silence_at=row.silence_at, start_gap=row.start_gap, title=row.title, track_id=row.track_id, # Additional fields like row_fg, row_bg, etc., use default None values ) dto_list.append(dto) return dto_list