"""Utils for isrc merging.""" from sqlalchemy import or_ from sqlalchemy.orm import Query from typing import Dict, Iterable, List, Union from apollo_main_db.apollo.models import IsrcRelation from apollo_main_db.spotify import SpotifyTrack2 from src.db.base import session def get_relation_query(main_isrc: str = None, related_isrc: List[str] = None, union: bool = False) -> Query: """Get isrc relation query with filtering. Use union=True to filter with 'or' statement instead 'and'. """ q = session.query(IsrcRelation) main_term = IsrcRelation.main_isrc == main_isrc related_term = IsrcRelation.isrc.in_(related_isrc or []) if union and main_isrc and related_isrc: q = q.filter(or_(main_term, related_term)).all() return q if main_isrc: q = q.filter(main_term) if related_isrc: q = q.filter(related_term) return q def add_relation(main_isrc: str, related_isrc: List[str]): """Add new isrc child to parent relation.""" session.bulk_save_objects([IsrcRelation(main_isrc=main_isrc, isrc=_isrc) for _isrc in related_isrc]) session.commit() def delete_relation(main_isrc: str, isrc: str = None) -> List[IsrcRelation]: """Remove isrc relation.""" rows_affected = get_relation_query(main_isrc, [isrc] if isrc else None).delete(synchronize_session=False) session.commit() return rows_affected def get_isrc_to_id_map_for_isrc(isrc_list: Iterable[str]) -> Dict[str, Union[str, int]]: """Return isrc to track_id dictionary for particular list of isrc from Apollo database in upper-case to avoid further duplicates in upper/down cases """ query = ( session.query(SpotifyTrack2.id, SpotifyTrack2.isrc) .filter(SpotifyTrack2.isrc.in_(isrc_list)) .group_by(SpotifyTrack2.isrc) ) result = {t.isrc.upper(): t.id for t in query} return result