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:
- search = create_safe_string(search, True, True)
- query_params["search"] = f"%{search}%"
+ safe_search = create_safe_string(search, True, True)
+ query_params["search"] = f"%{safe_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 filter
+
+ # handle provider join
if provider:
join_parts.append(
f"JOIN provider_mappings ON provider_mappings.item_id = {self.db_table}.item_id "
f"AND (provider_mappings.provider_instance = '{provider}' "
f"OR provider_mappings.provider_domain = '{provider}')"
)
- # prevent duplicate where statement
+
+ # Prevent duplicate WHERE
query_parts = [x[5:] if x.lower().startswith("where ") else x for x in query_parts]
- # 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):
+
+ # --- 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)):
sql_query += f" ORDER BY {sort_key}"
- # return dbresult parsed to media item model
+ query_limit = limit
+ query_offset = offset
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=limit, offset=offset
+ sql_query, query_params, limit=query_limit, offset=query_offset
)
]