Revert "Fix bug when using random order (#2206)"
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 1 Jun 2025 16:22:05 +0000 (18:22 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 1 Jun 2025 16:22:05 +0000 (18:22 +0200)
This reverts commit 224392b4e758e56ee8ace1fd95dd3ea439caef77.

music_assistant/controllers/media/base.py

index ccdea0a070545ca52289688c61387352842f1633..723b5cf68245d1da3c7e1df6b1b23e3176bcb758 100644 (file)
@@ -714,19 +714,22 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
         query_params = extra_query_params or {}
         query_parts: list[str] = extra_query_parts or []
         join_parts: list[str] = extra_join_parts or []
-
+        # create special performant random query
+        if not search and order_by and order_by.startswith("random"):
+            query_parts.append(
+                f"{self.db_table}.item_id in "
+                f"(SELECT item_id FROM {self.db_table} ORDER BY RANDOM() LIMIT {limit})"
+            )
         # handle search
         if search:
-            safe_search = create_safe_string(search, True, True)
-            query_params["search"] = f"%{safe_search}%"
+            search = create_safe_string(search, True, True)
+            query_params["search"] = f"%{search}%"
             query_parts.append(f"{self.db_table}.search_name LIKE :search")
-
         # handle favorite filter
         if favorite is not None:
             query_parts.append(f"{self.db_table}.favorite = :favorite")
             query_params["favorite"] = favorite
-
-        # handle provider join
+        # handle provider filter
         if provider:
             join_parts.append(
                 f"JOIN provider_mappings ON provider_mappings.item_id = {self.db_table}.item_id "
@@ -734,45 +737,23 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
                 f"AND (provider_mappings.provider_instance = '{provider}' "
                 f"OR provider_mappings.provider_domain = '{provider}')"
             )
-
-        # Prevent duplicate WHERE
+        # prevent duplicate where statement
         query_parts = [x[5:] if x.lower().startswith("where ") else x for x in query_parts]
-
-        # --- Optimized RANDOM ORDER block ---
-        if order_by and order_by.startswith("random"):
-            # Build filtered subquery for item IDs
-            subquery = f"SELECT {self.db_table}.item_id FROM {self.db_table}"
-            if query_parts:
-                subquery += " WHERE " + " AND ".join(query_parts)
-            subquery += f" ORDER BY RANDOM() LIMIT {limit}"
-
-            # Main query joins the subquery
-            sql_query = (
-                f"SELECT * FROM {self.db_table} "
-                f"JOIN ({subquery}) AS filtered_random "
-                f"ON {self.db_table}.item_id = filtered_random.item_id "
-                f"GROUP BY {self.db_table}.item_id"
-            )
-            # Note: limit is already applied in subquery, so use 0 offset
-            # and large limit to pass results
-            query_limit = limit
-            query_offset = 0
-        else:
-            # Normal query path
-            sql_query = self.base_query
-            if join_parts:
-                sql_query += f" {' '.join(join_parts)}"
-            if query_parts:
-                sql_query += " WHERE " + " AND ".join(query_parts)
-            sql_query += f" GROUP BY {self.db_table}.item_id"
-            if order_by and (sort_key := SORT_KEYS.get(order_by)):
+        # concetenate all join and/or where queries
+        if join_parts:
+            sql_query += f" {' '.join(join_parts)} "
+        if query_parts:
+            sql_query += " WHERE " + " AND ".join(query_parts)
+        # build final query
+        sql_query += f" GROUP BY {self.db_table}.item_id"
+        if order_by:
+            if sort_key := SORT_KEYS.get(order_by):
                 sql_query += f" ORDER BY {sort_key}"
-            query_limit = limit
-            query_offset = offset
+        # return dbresult parsed to media item model
         return [
             self.item_cls.from_dict(self._parse_db_row(db_row))
             for db_row in await self.mass.music.database.get_rows_from_query(
-                sql_query, query_params, limit=query_limit, offset=query_offset
+                sql_query, query_params, limit=limit, offset=offset
             )
         ]